x86: Add a CPU driver for baytrail
authorSimon Glass <sjg@chromium.org>
Thu, 30 Apr 2015 04:26:02 +0000 (22:26 -0600)
committerSimon Glass <sjg@chromium.org>
Thu, 30 Apr 2015 22:13:50 +0000 (16:13 -0600)
This driver supports multi-core init and sets up the CPU frequencies
correctly.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
arch/x86/cpu/baytrail/Makefile
arch/x86/cpu/baytrail/cpu.c [new file with mode: 0644]
arch/x86/include/asm/arch-ivybridge/model_206ax.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/turbo.h

index 8914e8b6d5a4463db384dcd1e577bab07b5a2c5c..c78b644eb718314bf4af8cd7c2162c11ea2331f2 100644 (file)
@@ -4,6 +4,7 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
+obj-y += cpu.o
 obj-y += early_uart.o
 obj-y += fsp_configs.o
 obj-y += pci.o
diff --git a/arch/x86/cpu/baytrail/cpu.c b/arch/x86/cpu/baytrail/cpu.c
new file mode 100644 (file)
index 0000000..1d48206
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Based on code from coreboot
+ */
+
+#include <common.h>
+#include <cpu.h>
+#include <dm.h>
+#include <asm/cpu.h>
+#include <asm/lapic.h>
+#include <asm/mp.h>
+#include <asm/msr.h>
+#include <asm/turbo.h>
+
+#ifdef CONFIG_SMP
+static int enable_smis(struct udevice *cpu, void *unused)
+{
+       return 0;
+}
+
+static struct mp_flight_record mp_steps[] = {
+       MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
+       /* Wait for APs to finish initialization before proceeding. */
+       MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
+};
+
+static int detect_num_cpus(void)
+{
+       int ecx = 0;
+
+       /*
+        * Use the algorithm described in Intel 64 and IA-32 Architectures
+        * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
+        * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
+        * of CPUID Extended Topology Leaf.
+        */
+       while (1) {
+               struct cpuid_result leaf_b;
+
+               leaf_b = cpuid_ext(0xb, ecx);
+
+               /*
+                * Bay Trail doesn't have hyperthreading so just determine the
+                * number of cores by from level type (ecx[15:8] == * 2)
+                */
+               if ((leaf_b.ecx & 0xff00) == 0x0200)
+                       return leaf_b.ebx & 0xffff;
+               ecx++;
+       }
+}
+
+static int baytrail_init_cpus(void)
+{
+       struct mp_params mp_params;
+
+       lapic_setup();
+
+       mp_params.num_cpus = detect_num_cpus();
+       mp_params.parallel_microcode_load = 0,
+       mp_params.flight_plan = &mp_steps[0];
+       mp_params.num_records = ARRAY_SIZE(mp_steps);
+       mp_params.microcode_pointer = 0;
+
+       if (mp_init(&mp_params)) {
+               printf("Warning: MP init failure\n");
+               return -EIO;
+       }
+
+       return 0;
+}
+#endif
+
+int x86_init_cpus(void)
+{
+#ifdef CONFIG_SMP
+       debug("Init additional CPUs\n");
+       baytrail_init_cpus();
+#endif
+
+       return 0;
+}
+
+static void set_max_freq(void)
+{
+       msr_t perf_ctl;
+       msr_t msr;
+
+       /* Enable speed step */
+       msr = msr_read(MSR_IA32_MISC_ENABLES);
+       msr.lo |= (1 << 16);
+       msr_write(MSR_IA32_MISC_ENABLES, msr);
+
+       /*
+        * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
+        * the PERF_CTL
+        */
+       msr = msr_read(MSR_IACORE_RATIOS);
+       perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
+
+       /*
+        * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
+        * the PERF_CTL
+        */
+       msr = msr_read(MSR_IACORE_VIDS);
+       perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
+       perf_ctl.hi = 0;
+
+       msr_write(MSR_IA32_PERF_CTL, perf_ctl);
+}
+
+static int cpu_x86_baytrail_probe(struct udevice *dev)
+{
+       debug("Init BayTrail core\n");
+
+       /*
+        * On BayTrail the turbo disable bit is actually scoped at the
+        * building-block level, not package. For non-BSP cores that are
+        * within a building block, enable turbo. The cores within the BSP's
+        * building block will just see it already enabled and move on.
+        */
+       if (lapicid())
+               turbo_enable();
+
+       /* Dynamic L2 shrink enable and threshold */
+       msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
+
+       /* Disable C1E */
+       msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
+       msr_setbits_64(MSR_POWER_MISC, 0x44);
+
+       /* Set this core to max frequency ratio */
+       set_max_freq();
+
+       return 0;
+}
+
+static unsigned bus_freq(void)
+{
+       msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
+       switch (clk_info.lo & 0x3) {
+       case 0:
+               return 83333333;
+       case 1:
+               return 100000000;
+       case 2:
+               return 133333333;
+       case 3:
+               return 116666666;
+       default:
+               return 0;
+       }
+}
+
+static unsigned long tsc_freq(void)
+{
+       msr_t platform_info;
+       ulong bclk = bus_freq();
+
+       if (!bclk)
+               return 0;
+
+       platform_info = msr_read(MSR_PLATFORM_INFO);
+
+       return bclk * ((platform_info.lo >> 8) & 0xff);
+}
+
+static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
+{
+       info->cpu_freq = tsc_freq();
+       info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
+
+       return 0;
+}
+
+static int cpu_x86_baytrail_bind(struct udevice *dev)
+{
+       struct cpu_platdata *plat = dev_get_parent_platdata(dev);
+
+       plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                     "intel,apic-id", -1);
+
+       return 0;
+}
+
+static const struct cpu_ops cpu_x86_baytrail_ops = {
+       .get_desc       = x86_cpu_get_desc,
+       .get_info       = baytrail_get_info,
+};
+
+static const struct udevice_id cpu_x86_baytrail_ids[] = {
+       { .compatible = "intel,baytrail-cpu" },
+       { }
+};
+
+U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
+       .name           = "cpu_x86_baytrail",
+       .id             = UCLASS_CPU,
+       .of_match       = cpu_x86_baytrail_ids,
+       .bind           = cpu_x86_baytrail_bind,
+       .probe          = cpu_x86_baytrail_probe,
+       .ops            = &cpu_x86_baytrail_ops,
+};
index 7b4f2e790b40f2a6581a31b798e88bbb09827f03..d2f9006093240fd6f39029654e6b0dbb053a4a92 100644 (file)
@@ -37,7 +37,6 @@
 #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
@@ -63,7 +62,6 @@
 #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
index 2cbb270089a7a0378461e8ac937f5e191d3a8322..38dbb3137aaf49fef5f93259372c539b35522f05 100644 (file)
 #define SNB_C1_AUTO_UNDEMOTE           (1UL << 27)
 #define SNB_C3_AUTO_UNDEMOTE           (1UL << 28)
 
+#define MSR_BSEL_CR_OVERCLOCK_CONTROL  0x000000cd
 #define MSR_PLATFORM_INFO              0x000000ce
+#define MSR_PMG_CST_CONFIG_CONTROL     0x000000e2
+#define SINGLE_PCTL                    (1 << 11)
+
 #define MSR_MTRRcap                    0x000000fe
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
+#define MSR_POWER_MISC                 0x00000120
+#define ENABLE_ULFM_AUTOCM_MASK                (1 << 2)
+#define ENABLE_INDP_AUTOCM_MASK                (1 << 3)
 
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
@@ -66,6 +73,7 @@
 #define MSR_IA32_MCG_STATUS            0x0000017a
 #define MSR_IA32_MCG_CTL               0x0000017b
 
+#define MSR_IA32_MISC_ENABLES          0x000001a0
 #define MSR_OFFCORE_RSP_0              0x000001a6
 #define MSR_OFFCORE_RSP_1              0x000001a7
 #define MSR_NHM_TURBO_RATIO_LIMIT      0x000001ad
@@ -73,6 +81,7 @@
 
 #define MSR_LBR_SELECT                 0x000001c8
 #define MSR_LBR_TOS                    0x000001c9
+#define MSR_POWER_CTL                  0x000001fc
 #define MSR_LBR_NHM_FROM               0x00000680
 #define MSR_LBR_NHM_TO                 0x000006c0
 #define MSR_LBR_CORE_FROM              0x00000040
 
 /* Run Time Average Power Limiting (RAPL) Interface */
 
-#define MSR_RAPL_POWER_UNIT            0x00000606
+#define MSR_PKG_POWER_SKU_UNIT         0x00000606
 
 #define MSR_PKG_POWER_LIMIT            0x00000610
 #define MSR_PKG_ENERGY_STATUS          0x00000611
 #define MSR_PP1_POLICY                 0x00000642
 
 #define MSR_CORE_C1_RES                        0x00000660
+#define MSR_IACORE_RATIOS              0x0000066a
+#define MSR_IACORE_TURBO_RATIOS                0x0000066c
+#define MSR_IACORE_VIDS                        0x0000066b
+#define MSR_IACORE_TURBO_VIDS          0x0000066d
+#define MSR_PKG_TURBO_CFG1             0x00000670
+#define MSR_CPU_TURBO_WKLD_CFG1                0x00000671
+#define MSR_CPU_TURBO_WKLD_CFG2                0x00000672
+#define MSR_CPU_THERM_CFG1             0x00000673
+#define MSR_CPU_THERM_CFG2             0x00000674
+#define MSR_CPU_THERM_SENS_CFG         0x00000675
 
 #define MSR_AMD64_MC0_MASK             0xc0010044
 
 #define MSR_THERM2_CTL_TM_SELECT       (1ULL << 16)
 
 #define MSR_IA32_MISC_ENABLE           0x000001a0
+#define H_MISC_DISABLE_TURBO           (1 << 6)
 
 #define MSR_IA32_TEMPERATURE_TARGET    0x000001a2
 
index bb0d4b43548147d55f367b7af9f7571d8abdc02d..21b910bbf0c6bf38a333ec6b07fe64b5fbd022eb 100644 (file)
@@ -12,9 +12,6 @@
 #define CPUID_LEAF_PM          6
 #define PM_CAP_TURBO_MODE      (1 << 1)
 
-#define MSR_IA32_MISC_ENABLES  0x1a0
-#define H_MISC_DISABLE_TURBO   (1 << 6)
-
 enum {
        TURBO_UNKNOWN,
        TURBO_UNAVAILABLE,