aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-11-04 09:57:15 -0700
committerBin Meng <bmeng.cn@gmail.com>2020-11-05 14:58:45 +0800
commit6571d873159789ee7caa571eafa5fa641005971c (patch)
treebcb0f59b372597fae7916946cd6be44424a435bf /arch
parent1779b8a96a32706dc8e2e71187889b38d9822443 (diff)
downloadu-boot-6571d873159789ee7caa571eafa5fa641005971c.zip
u-boot-6571d873159789ee7caa571eafa5fa641005971c.tar.gz
u-boot-6571d873159789ee7caa571eafa5fa641005971c.tar.bz2
x86: apl: Add core init for the SoC
Set up MSRs required for Apollo Lake. This enables Linux to use the timers correctly. Also write the fixed MSRs for this platform. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/cpu/apollolake/cpu.c84
-rw-r--r--arch/x86/cpu/apollolake/cpu_common.c25
-rw-r--r--arch/x86/cpu/apollolake/cpu_spl.c20
-rw-r--r--arch/x86/cpu/intel_common/cpu.c19
-rw-r--r--arch/x86/include/asm/arch-apollolake/cpu.h14
-rw-r--r--arch/x86/include/asm/cpu_common.h9
-rw-r--r--arch/x86/include/asm/msr-index.h20
7 files changed, 170 insertions, 21 deletions
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c
index a4c9c96..d37f91d 100644
--- a/arch/x86/cpu/apollolake/cpu.c
+++ b/arch/x86/cpu/apollolake/cpu.c
@@ -13,6 +13,9 @@
#include <asm/cpu_x86.h>
#include <asm/intel_acpi.h>
#include <asm/msr.h>
+#include <asm/mtrr.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
#include <dm/acpi.h>
#define CSTATE_RES(address_space, width, offset, address) \
@@ -86,6 +89,86 @@ static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
return 0;
}
+static void update_fixed_mtrrs(void)
+{
+ native_write_msr(MTRR_FIX_64K_00000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_16K_80000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_E0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_E8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_F0000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+ native_write_msr(MTRR_FIX_4K_F8000_MSR,
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK),
+ MTRR_FIX_TYPE(MTRR_TYPE_WRBACK));
+}
+
+static void setup_core_msrs(void)
+{
+ wrmsrl(MSR_PMG_CST_CONFIG_CONTROL,
+ PKG_C_STATE_LIMIT_C2_MASK | CORE_C_STATE_LIMIT_C10_MASK |
+ IO_MWAIT_REDIRECT_MASK | CST_CFG_LOCK_MASK);
+ /* Power Management I/O base address for I/O trapping to C-states */
+ wrmsrl(MSR_PMG_IO_CAPTURE_ADR, ACPI_PMIO_CST_REG |
+ (PMG_IO_BASE_CST_RNG_BLK_SIZE << 16));
+ /* Disable C1E */
+ msr_clrsetbits_64(MSR_POWER_CTL, 0x2, 0);
+ /* Disable support for MONITOR and MWAIT instructions */
+ msr_clrsetbits_64(MSR_IA32_MISC_ENABLE, MISC_ENABLE_MWAIT, 0);
+ /*
+ * Enable and Lock the Advanced Encryption Standard (AES-NI)
+ * feature register
+ */
+ msr_clrsetbits_64(MSR_FEATURE_CONFIG, FEATURE_CONFIG_RESERVED_MASK,
+ FEATURE_CONFIG_LOCK);
+
+ update_fixed_mtrrs();
+}
+
+static int soc_core_init(void)
+{
+ struct udevice *pmc;
+ int ret;
+
+ /* Clear out pending MCEs */
+ cpu_mca_configure();
+
+ /* Set core MSRs */
+ setup_core_msrs();
+ /*
+ * Enable ACPI PM timer emulation, which also lets microcode know
+ * location of ACPI_BASE_ADDRESS. This also enables other features
+ * implemented in microcode.
+ */
+ ret = uclass_first_device_err(UCLASS_ACPI_PMC, &pmc);
+ if (ret)
+ return log_msg_ret("PMC", ret);
+ enable_pm_timer_emulation(pmc);
+
+ return 0;
+}
+
+static int cpu_apl_probe(struct udevice *dev)
+{
+ if (gd->flags & GD_FLG_RELOC) {
+ int ret;
+
+ ret = soc_core_init();
+ if (ret)
+ return log_ret(ret);
+ }
+
+ return 0;
+}
+
struct acpi_ops apl_cpu_acpi_ops = {
.fill_ssdt = acpi_cpu_fill_ssdt,
};
@@ -107,6 +190,7 @@ U_BOOT_DRIVER(intel_apl_cpu) = {
.id = UCLASS_CPU,
.of_match = cpu_x86_apl_ids,
.bind = cpu_x86_bind,
+ .probe = cpu_apl_probe,
.ops = &cpu_x86_apl_ops,
ACPI_OPS_PTR(&apl_cpu_acpi_ops)
.flags = DM_FLAG_PRE_RELOC,
diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c
index ba6bda3..63f6999 100644
--- a/arch/x86/cpu/apollolake/cpu_common.c
+++ b/arch/x86/cpu/apollolake/cpu_common.c
@@ -4,8 +4,13 @@
*/
#include <common.h>
+#include <dm.h>
+#include <log.h>
#include <asm/cpu_common.h>
#include <asm/msr.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/iomap.h>
+#include <power/acpi_pmc.h>
void cpu_flush_l1d_to_l2(void)
{
@@ -15,3 +20,23 @@ void cpu_flush_l1d_to_l2(void)
msr.lo |= FLUSH_DL1_L2;
msr_write(MSR_POWER_MISC, msr);
}
+
+void enable_pm_timer_emulation(const struct udevice *pmc)
+{
+ struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
+ msr_t msr;
+
+ /*
+ * The derived frequency is calculated as follows:
+ * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
+ *
+ * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
+ * used.
+ */
+ msr.hi = (3579545ULL << 32) / CTC_FREQ;
+
+ /* Set PM1 timer IO port and enable */
+ msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
+ debug("PM timer %x %x\n", msr.hi, msr.lo);
+ msr_write(MSR_EMULATE_PM_TIMER, msr);
+}
diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c
index 9f32f2e..fafe4db 100644
--- a/arch/x86/cpu/apollolake/cpu_spl.c
+++ b/arch/x86/cpu/apollolake/cpu_spl.c
@@ -114,26 +114,6 @@ static int fast_spi_cache_bios_region(void)
return 0;
}
-static void enable_pm_timer_emulation(struct udevice *pmc)
-{
- struct acpi_pmc_upriv *upriv = dev_get_uclass_priv(pmc);
- msr_t msr;
-
- /*
- * The derived frequency is calculated as follows:
- * (CTC_FREQ * msr[63:32]) >> 32 = target frequency.
- *
- * Back-solve the multiplier so the 3.579545MHz ACPI timer frequency is
- * used.
- */
- msr.hi = (3579545ULL << 32) / CTC_FREQ;
-
- /* Set PM1 timer IO port and enable */
- msr.lo = EMULATE_PM_TMR_EN | (upriv->acpi_base + R_ACPI_PM1_TMR);
- debug("PM timer %x %x\n", msr.hi, msr.lo);
- msr_write(MSR_EMULATE_PM_TIMER, msr);
-}
-
static void google_chromeec_ioport_range(uint *out_basep, uint *out_sizep)
{
uint base;
diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c
index 39aa0f6..a51bf86 100644
--- a/arch/x86/cpu/intel_common/cpu.c
+++ b/arch/x86/cpu/intel_common/cpu.c
@@ -306,3 +306,22 @@ int cpu_get_cores_per_package(void)
return cores;
}
+
+void cpu_mca_configure(void)
+{
+ msr_t msr;
+ int i;
+ int num_banks;
+
+ msr = msr_read(MSR_IA32_MCG_CAP);
+ num_banks = msr.lo & 0xff;
+ msr.lo = 0;
+ msr.hi = 0;
+ for (i = 0; i < num_banks; i++) {
+ /* Clear the machine check status */
+ msr_write(MSR_IA32_MC0_STATUS + (i * 4), msr);
+ /* Initialise machine checks */
+ msr_write(MSR_IA32_MC0_CTL + i * 4,
+ (msr_t) {.lo = 0xffffffff, .hi = 0xffffffff});
+ }
+}
diff --git a/arch/x86/include/asm/arch-apollolake/cpu.h b/arch/x86/include/asm/arch-apollolake/cpu.h
index 5e906c5..67d48c6 100644
--- a/arch/x86/include/asm/arch-apollolake/cpu.h
+++ b/arch/x86/include/asm/arch-apollolake/cpu.h
@@ -15,6 +15,20 @@
#ifndef __ASSEMBLY__
/* Flush L1D to L2 */
void cpu_flush_l1d_to_l2(void);
+
+/**
+ * Enable emulation of the PM timer
+ *
+ * Some legacy OSes cannot tolerate the ACPI timer stoping during idle states,
+ * and this results in higher power consumption. ACPI timer emulation allows
+ * disabling of the ACPI Timer (PM1_TMR) to have no impact on the system, with
+ * the exception that TMR_STS will not be set on an overflow condition. All
+ * aligned 32-bit reads from the ACPI Timer port are valid and will behave as if
+ * the ACPI timer remains enabled.
+ *
+ * @pmc: PMC device
+ */
+void enable_pm_timer_emulation(const struct udevice *pmc);
#endif
#endif /* _ASM_ARCH_CPU_H */
diff --git a/arch/x86/include/asm/cpu_common.h b/arch/x86/include/asm/cpu_common.h
index 48f56c2..2a5779a 100644
--- a/arch/x86/include/asm/cpu_common.h
+++ b/arch/x86/include/asm/cpu_common.h
@@ -184,4 +184,13 @@ int cpu_get_max_turbo_ratio(void);
*/
int cpu_get_cores_per_package(void);
+/**
+ * cpu_mca_configure() - Set up machine-check exceptions ready for use
+ *
+ * These allow the SoC to report errors while running. See here for details:
+ *
+ * https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/machine-check-exceptions-debug-paper.pdf
+ */
+void cpu_mca_configure(void);
+
#endif
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 94e6b18..c49b422 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -68,7 +68,18 @@
#define MSR_BSEL_CR_OVERCLOCK_CONTROL 0x000000cd
#define MSR_PLATFORM_INFO 0x000000ce
#define MSR_PMG_CST_CONFIG_CONTROL 0x000000e2
-#define SINGLE_PCTL (1 << 11)
+/* Set MSR_PMG_CST_CONFIG_CONTROL[3:0] for Package C-State limit */
+#define PKG_C_STATE_LIMIT_C2_MASK BIT(1)
+/* Set MSR_PMG_CST_CONFIG_CONTROL[7:4] for Core C-State limit*/
+#define CORE_C_STATE_LIMIT_C10_MASK 0x70
+/* Set MSR_PMG_CST_CONFIG_CONTROL[10] to IO redirect to MWAIT */
+#define IO_MWAIT_REDIRECT_MASK BIT(10)
+/* Set MSR_PMG_CST_CONFIG_CONTROL[15] to lock CST_CFG [0-15] bits */
+#define CST_CFG_LOCK_MASK BIT(15)
+#define SINGLE_PCTL BIT(11)
+
+/* ACPI PMIO Offset to C-state register */
+#define ACPI_PMIO_CST_REG (ACPI_BASE_ADDRESS + 0x14)
#define MSR_MTRRcap 0x000000fe
#define MSR_IA32_BBL_CR_CTL 0x00000119
@@ -83,6 +94,10 @@
#define EMULATE_PM_TMR_EN (1 << 16)
#define EMULATE_DELAY_VALUE 0x13
+#define MSR_FEATURE_CONFIG 0x13c
+#define FEATURE_CONFIG_RESERVED_MASK 0x3ULL
+#define FEATURE_CONFIG_LOCK (1 << 0)
+
#define MSR_IA32_SYSENTER_CS 0x00000174
#define MSR_IA32_SYSENTER_ESP 0x00000175
#define MSR_IA32_SYSENTER_EIP 0x00000176
@@ -453,6 +468,9 @@
#define MSR_AMD_PERF_CTL 0xc0010062
#define MSR_PMG_CST_CONFIG_CTL 0x000000e2
+/* CST Range (R/W) IO port block size */
+#define PMG_IO_BASE_CST_RNG_BLK_SIZE 0x5
+
#define MSR_PMG_IO_CAPTURE_ADR 0x000000e4
#define MSR_IA32_MPERF 0x000000e7
#define MSR_IA32_APERF 0x000000e8