[U-Boot] [PATCH v2 23/33] x86: ivybridge: Perform initial CPU setup

Simon Glass sjg at chromium.org
Tue Nov 11 02:00:40 CET 2014


Set up the flex ratio (controls speed versus heat output) and a few other
very early things.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v2: None

 arch/x86/cpu/ivybridge/cpu.c                      | 130 ++++++++++++++++++++++
 arch/x86/include/asm/arch-ivybridge/model_206ax.h |  82 ++++++++++++++
 arch/x86/include/asm/arch-ivybridge/pch.h         |  60 ++++++++++
 arch/x86/include/asm/processor.h                  |   2 +
 4 files changed, 274 insertions(+)
 create mode 100644 arch/x86/include/asm/arch-ivybridge/model_206ax.h

diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c
index 5d7640b..ab708dd 100644
--- a/arch/x86/cpu/ivybridge/cpu.c
+++ b/arch/x86/cpu/ivybridge/cpu.c
@@ -14,13 +14,123 @@
 #include <errno.h>
 #include <fdtdec.h>
 #include <asm/cpu.h>
+#include <asm/io.h>
+#include <asm/msr.h>
+#include <asm/mtrr.h>
 #include <asm/pci.h>
 #include <asm/post.h>
 #include <asm/processor.h>
+#include <asm/arch/model_206ax.h>
 #include <asm/arch/pch.h>
 
 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, &reg8);
+	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)
 {
 	const void *blob = gd->fdt_blob;
@@ -46,6 +156,26 @@ int arch_cpu_init(void)
 	if (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;
 }
 
diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
new file mode 100644
index 0000000..8281d7a
--- /dev/null
+++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h
@@ -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
diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
index 26ddeab..c572f76 100644
--- a/arch/x86/include/asm/arch-ivybridge/pch.h
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -35,6 +35,66 @@
 #define LPC_GEN4_DEC		0x90 /* LPC IF Generic Decode Range 4 */
 #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
  *
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index b2854a9..b9317cb 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -32,6 +32,8 @@ enum {
 
 #ifndef __ASSEMBLY__
 
+#define PORT_RESET		0xcf9
+
 static inline __attribute__((always_inline)) void cpu_hlt(void)
 {
 	asm("hlt");
-- 
2.1.0.rc2.206.gedb03e5



More information about the U-Boot mailing list