]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
x86: apl: Add core init for the SoC
authorSimon Glass <sjg@chromium.org>
Wed, 4 Nov 2020 16:57:15 +0000 (09:57 -0700)
committerBin Meng <bmeng.cn@gmail.com>
Thu, 5 Nov 2020 06:58:45 +0000 (14:58 +0800)
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>
arch/x86/cpu/apollolake/cpu.c
arch/x86/cpu/apollolake/cpu_common.c
arch/x86/cpu/apollolake/cpu_spl.c
arch/x86/cpu/intel_common/cpu.c
arch/x86/include/asm/arch-apollolake/cpu.h
arch/x86/include/asm/cpu_common.h
arch/x86/include/asm/msr-index.h

index a4c9c96cfdca5c8d59c976bdbe2d64bfeaef9f07..d37f91d1ce1420e4db9a8130c05a6aefc3583dc3 100644 (file)
@@ -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,
index ba6bda37bc538a573897b0bb72e66a008d8e52f9..63f6999b02472639d1373b67585855db667c2fd0 100644 (file)
@@ -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);
+}
index 9f32f2e27e125e2d69a6a8b8fa820c00c571f1dd..fafe4dbc0a04e153b8d4ff8ccbc6410e956e135b 100644 (file)
@@ -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;
index 39aa0f63c65b75b687abd77125a3556f12a14440..a51bf86f7abc9c7f6d21cd215aef2e01442f0867 100644 (file)
@@ -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});
+       }
+}
index 5e906c5e7d7b8f79752845c25124f0a6a14f873e..67d48c610988601725f7103b41804dadd9fcfa3c 100644 (file)
 #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 */
index 48f56c2aad9c3cb5f93cce41df464030d44020f3..2a5779a8e1a7ae8577e078459ab66b0c6cdfcf0b 100644 (file)
@@ -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
index 94e6b18e21cd9c8f65b6a1555566cc01a79d10de..c49b4225ac26ea5e080e791de00bd0fedd26a291 100644 (file)
 #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
 #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
 #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