x86: ivybridge: Perform initial CPU setup
Set up the flex ratio (controls speed versus heat output) and a few other very early things. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
eddbad224b
commit
f5fbbe9579
|
@ -14,13 +14,123 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fdtdec.h>
|
#include <fdtdec.h>
|
||||||
#include <asm/cpu.h>
|
#include <asm/cpu.h>
|
||||||
|
#include <asm/io.h>
|
||||||
|
#include <asm/msr.h>
|
||||||
|
#include <asm/mtrr.h>
|
||||||
#include <asm/pci.h>
|
#include <asm/pci.h>
|
||||||
#include <asm/post.h>
|
#include <asm/post.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
#include <asm/arch/model_206ax.h>
|
||||||
#include <asm/arch/pch.h>
|
#include <asm/arch/pch.h>
|
||||||
|
|
||||||
DECLARE_GLOBAL_DATA_PTR;
|
DECLARE_GLOBAL_DATA_PTR;
|
||||||
|
|
||||||
|
static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev)
|
||||||
|
{
|
||||||
|
/* Enable port 80 POST on LPC */
|
||||||
|
pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1);
|
||||||
|
clrbits_le32(RCB_REG(GCS), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enable Prefetching and Caching.
|
||||||
|
*/
|
||||||
|
static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev)
|
||||||
|
{
|
||||||
|
u8 reg8;
|
||||||
|
|
||||||
|
pci_hose_read_config_byte(hose, dev, 0xdc, ®8);
|
||||||
|
reg8 &= ~(3 << 2);
|
||||||
|
reg8 |= (2 << 2); /* Prefetching and Caching Enabled */
|
||||||
|
pci_hose_write_config_byte(hose, dev, 0xdc, reg8);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_var_mtrr(
|
||||||
|
unsigned reg, unsigned base, unsigned size, unsigned type)
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Bit Bit 32-35 of MTRRphysMask should be set to 1 */
|
||||||
|
/* FIXME: It only support 4G less range */
|
||||||
|
wrmsr(MTRRphysBase_MSR(reg), base | type, 0);
|
||||||
|
wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid,
|
||||||
|
(1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void enable_rom_caching(void)
|
||||||
|
{
|
||||||
|
disable_caches();
|
||||||
|
set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT);
|
||||||
|
enable_caches();
|
||||||
|
|
||||||
|
/* Enable Variable MTRRs */
|
||||||
|
wrmsr(MTRRdefType_MSR, 0x800, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_flex_ratio_to_tdp_nominal(void)
|
||||||
|
{
|
||||||
|
msr_t flex_ratio, msr;
|
||||||
|
u8 nominal_ratio;
|
||||||
|
|
||||||
|
/* Minimum CPU revision for configurable TDP support */
|
||||||
|
if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Check for Flex Ratio support */
|
||||||
|
flex_ratio = msr_read(MSR_FLEX_RATIO);
|
||||||
|
if (!(flex_ratio.lo & FLEX_RATIO_EN))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Check for >0 configurable TDPs */
|
||||||
|
msr = msr_read(MSR_PLATFORM_INFO);
|
||||||
|
if (((msr.hi >> 1) & 3) == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Use nominal TDP ratio for flex ratio */
|
||||||
|
msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
|
||||||
|
nominal_ratio = msr.lo & 0xff;
|
||||||
|
|
||||||
|
/* See if flex ratio is already set to nominal TDP ratio */
|
||||||
|
if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Set flex ratio to nominal TDP ratio */
|
||||||
|
flex_ratio.lo &= ~0xff00;
|
||||||
|
flex_ratio.lo |= nominal_ratio << 8;
|
||||||
|
flex_ratio.lo |= FLEX_RATIO_LOCK;
|
||||||
|
msr_write(MSR_FLEX_RATIO, flex_ratio);
|
||||||
|
|
||||||
|
/* Set flex ratio in soft reset data register bits 11:6 */
|
||||||
|
clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6,
|
||||||
|
(nominal_ratio & 0x3f) << 6);
|
||||||
|
|
||||||
|
/* Set soft reset control to use register value */
|
||||||
|
setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1);
|
||||||
|
|
||||||
|
/* Issue warm reset, will be "CPU only" due to soft reset data */
|
||||||
|
outb(0x0, PORT_RESET);
|
||||||
|
outb(0x6, PORT_RESET);
|
||||||
|
cpu_hlt();
|
||||||
|
|
||||||
|
/* Not reached */
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_spi_speed(void)
|
||||||
|
{
|
||||||
|
u32 fdod;
|
||||||
|
|
||||||
|
/* Observe SPI Descriptor Component Section 0 */
|
||||||
|
writel(0x1000, RCB_REG(SPI_DESC_COMP0));
|
||||||
|
|
||||||
|
/* Extract the1 Write/Erase SPI Frequency from descriptor */
|
||||||
|
fdod = readl(RCB_REG(SPI_FREQ_WR_ERA));
|
||||||
|
fdod >>= 24;
|
||||||
|
fdod &= 7;
|
||||||
|
|
||||||
|
/* Set Software Sequence frequency to match */
|
||||||
|
clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod);
|
||||||
|
}
|
||||||
|
|
||||||
int arch_cpu_init(void)
|
int arch_cpu_init(void)
|
||||||
{
|
{
|
||||||
const void *blob = gd->fdt_blob;
|
const void *blob = gd->fdt_blob;
|
||||||
|
@ -46,6 +156,26 @@ int arch_cpu_init(void)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
enable_spi_prefetch(hose, PCH_LPC_DEV);
|
||||||
|
|
||||||
|
/* This is already done in start.S, but let's do it in C */
|
||||||
|
enable_port80_on_lpc(hose, PCH_LPC_DEV);
|
||||||
|
|
||||||
|
/* already done in car.S */
|
||||||
|
if (false)
|
||||||
|
enable_rom_caching();
|
||||||
|
|
||||||
|
set_spi_speed();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We should do as little as possible before the serial console is
|
||||||
|
* up. Perhaps this should move to later. Our next lot of init
|
||||||
|
* happens in print_cpuinfo() when we have a console
|
||||||
|
*/
|
||||||
|
ret = set_flex_ratio_to_tdp_nominal();
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* From Coreboot file of the same name
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 The ChromiumOS Authors.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ASM_ARCH_MODEL_206AX_H
|
||||||
|
#define _ASM_ARCH_MODEL_206AX_H
|
||||||
|
|
||||||
|
/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */
|
||||||
|
#define SANDYBRIDGE_BCLK 100
|
||||||
|
|
||||||
|
#define CPUID_VMX (1 << 5)
|
||||||
|
#define CPUID_SMX (1 << 6)
|
||||||
|
#define MSR_FEATURE_CONFIG 0x13c
|
||||||
|
#define MSR_FLEX_RATIO 0x194
|
||||||
|
#define FLEX_RATIO_LOCK (1 << 20)
|
||||||
|
#define FLEX_RATIO_EN (1 << 16)
|
||||||
|
#define IA32_PLATFORM_DCA_CAP 0x1f8
|
||||||
|
#define IA32_MISC_ENABLE 0x1a0
|
||||||
|
#define MSR_TEMPERATURE_TARGET 0x1a2
|
||||||
|
#define IA32_PERF_CTL 0x199
|
||||||
|
#define IA32_THERM_INTERRUPT 0x19b
|
||||||
|
#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0
|
||||||
|
#define ENERGY_POLICY_PERFORMANCE 0
|
||||||
|
#define ENERGY_POLICY_NORMAL 6
|
||||||
|
#define ENERGY_POLICY_POWERSAVE 15
|
||||||
|
#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2
|
||||||
|
#define MSR_LT_LOCK_MEMORY 0x2e7
|
||||||
|
#define IA32_MC0_STATUS 0x401
|
||||||
|
|
||||||
|
#define MSR_PIC_MSG_CONTROL 0x2e
|
||||||
|
#define PLATFORM_INFO_SET_TDP (1 << 29)
|
||||||
|
|
||||||
|
#define MSR_MISC_PWR_MGMT 0x1aa
|
||||||
|
#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0)
|
||||||
|
#define MSR_TURBO_RATIO_LIMIT 0x1ad
|
||||||
|
#define MSR_POWER_CTL 0x1fc
|
||||||
|
|
||||||
|
#define MSR_PKGC3_IRTL 0x60a
|
||||||
|
#define MSR_PKGC6_IRTL 0x60b
|
||||||
|
#define MSR_PKGC7_IRTL 0x60c
|
||||||
|
#define IRTL_VALID (1 << 15)
|
||||||
|
#define IRTL_1_NS (0 << 10)
|
||||||
|
#define IRTL_32_NS (1 << 10)
|
||||||
|
#define IRTL_1024_NS (2 << 10)
|
||||||
|
#define IRTL_32768_NS (3 << 10)
|
||||||
|
#define IRTL_1048576_NS (4 << 10)
|
||||||
|
#define IRTL_33554432_NS (5 << 10)
|
||||||
|
#define IRTL_RESPONSE_MASK (0x3ff)
|
||||||
|
|
||||||
|
/* long duration in low dword, short duration in high dword */
|
||||||
|
#define PKG_POWER_LIMIT_MASK 0x7fff
|
||||||
|
#define PKG_POWER_LIMIT_EN (1 << 15)
|
||||||
|
#define PKG_POWER_LIMIT_CLAMP (1 << 16)
|
||||||
|
#define PKG_POWER_LIMIT_TIME_SHIFT 17
|
||||||
|
#define PKG_POWER_LIMIT_TIME_MASK 0x7f
|
||||||
|
|
||||||
|
#define MSR_PP0_CURRENT_CONFIG 0x601
|
||||||
|
#define PP0_CURRENT_LIMIT (112 << 3) /* 112 A */
|
||||||
|
#define MSR_PP1_CURRENT_CONFIG 0x602
|
||||||
|
#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */
|
||||||
|
#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */
|
||||||
|
#define MSR_PKG_POWER_SKU_UNIT 0x606
|
||||||
|
#define MSR_PKG_POWER_SKU 0x614
|
||||||
|
|
||||||
|
#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2
|
||||||
|
#define MSR_CONFIG_TDP_NOMINAL 0x648
|
||||||
|
#define MSR_CONFIG_TDP_LEVEL1 0x649
|
||||||
|
#define MSR_CONFIG_TDP_LEVEL2 0x64a
|
||||||
|
#define MSR_CONFIG_TDP_CONTROL 0x64b
|
||||||
|
#define MSR_TURBO_ACTIVATION_RATIO 0x64c
|
||||||
|
|
||||||
|
/* P-state configuration */
|
||||||
|
#define PSS_MAX_ENTRIES 8
|
||||||
|
#define PSS_RATIO_STEP 2
|
||||||
|
#define PSS_LATENCY_TRANSITION 10
|
||||||
|
#define PSS_LATENCY_BUSMASTER 10
|
||||||
|
|
||||||
|
#endif
|
|
@ -35,6 +35,66 @@
|
||||||
#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */
|
#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */
|
||||||
#define LPC_GENX_DEC(x) (0x84 + 4 * (x))
|
#define LPC_GENX_DEC(x) (0x84 + 4 * (x))
|
||||||
|
|
||||||
|
#define DEFAULT_RCBA 0xfed1c000
|
||||||
|
|
||||||
|
/* Root Complex Register Block */
|
||||||
|
#define RCB_REG(reg) (DEFAULT_RCBA + (reg))
|
||||||
|
|
||||||
|
#define PCH_RCBA_BASE 0xf0
|
||||||
|
|
||||||
|
#define VCH 0x0000 /* 32bit */
|
||||||
|
#define VCAP1 0x0004 /* 32bit */
|
||||||
|
#define VCAP2 0x0008 /* 32bit */
|
||||||
|
#define PVC 0x000c /* 16bit */
|
||||||
|
#define PVS 0x000e /* 16bit */
|
||||||
|
|
||||||
|
#define V0CAP 0x0010 /* 32bit */
|
||||||
|
#define V0CTL 0x0014 /* 32bit */
|
||||||
|
#define V0STS 0x001a /* 16bit */
|
||||||
|
|
||||||
|
#define V1CAP 0x001c /* 32bit */
|
||||||
|
#define V1CTL 0x0020 /* 32bit */
|
||||||
|
#define V1STS 0x0026 /* 16bit */
|
||||||
|
|
||||||
|
#define RCTCL 0x0100 /* 32bit */
|
||||||
|
#define ESD 0x0104 /* 32bit */
|
||||||
|
#define ULD 0x0110 /* 32bit */
|
||||||
|
#define ULBA 0x0118 /* 64bit */
|
||||||
|
|
||||||
|
#define RP1D 0x0120 /* 32bit */
|
||||||
|
#define RP1BA 0x0128 /* 64bit */
|
||||||
|
#define RP2D 0x0130 /* 32bit */
|
||||||
|
#define RP2BA 0x0138 /* 64bit */
|
||||||
|
#define RP3D 0x0140 /* 32bit */
|
||||||
|
#define RP3BA 0x0148 /* 64bit */
|
||||||
|
#define RP4D 0x0150 /* 32bit */
|
||||||
|
#define RP4BA 0x0158 /* 64bit */
|
||||||
|
#define HDD 0x0160 /* 32bit */
|
||||||
|
#define HDBA 0x0168 /* 64bit */
|
||||||
|
#define RP5D 0x0170 /* 32bit */
|
||||||
|
#define RP5BA 0x0178 /* 64bit */
|
||||||
|
#define RP6D 0x0180 /* 32bit */
|
||||||
|
#define RP6BA 0x0188 /* 64bit */
|
||||||
|
|
||||||
|
#define RPC 0x0400 /* 32bit */
|
||||||
|
#define RPFN 0x0404 /* 32bit */
|
||||||
|
|
||||||
|
#define SPI_FREQ_SWSEQ 0x3893
|
||||||
|
#define SPI_DESC_COMP0 0x38b0
|
||||||
|
#define SPI_FREQ_WR_ERA 0x38b4
|
||||||
|
#define SOFT_RESET_CTRL 0x38f4
|
||||||
|
#define SOFT_RESET_DATA 0x38f8
|
||||||
|
|
||||||
|
#define RC 0x3400 /* 32bit */
|
||||||
|
#define HPTC 0x3404 /* 32bit */
|
||||||
|
#define GCS 0x3410 /* 32bit */
|
||||||
|
#define BUC 0x3414 /* 32bit */
|
||||||
|
#define PCH_DISABLE_GBE (1 << 5)
|
||||||
|
#define FD 0x3418 /* 32bit */
|
||||||
|
#define DISPBDF 0x3424 /* 16bit */
|
||||||
|
#define FD2 0x3428 /* 32bit */
|
||||||
|
#define CG 0x341c /* 32bit */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* lpc_early_init() - set up LPC serial ports and other early things
|
* lpc_early_init() - set up LPC serial ports and other early things
|
||||||
*
|
*
|
||||||
|
|
|
@ -32,6 +32,8 @@ enum {
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
#define PORT_RESET 0xcf9
|
||||||
|
|
||||||
static inline __attribute__((always_inline)) void cpu_hlt(void)
|
static inline __attribute__((always_inline)) void cpu_hlt(void)
|
||||||
{
|
{
|
||||||
asm("hlt");
|
asm("hlt");
|
||||||
|
|
Loading…
Reference in New Issue