2 * Copyright (C) 2015 Google, Inc
4 * SPDX-License-Identifier: GPL-2.0+
6 * Based on code from coreboot
13 #include <asm/lapic.h>
16 #include <asm/turbo.h>
19 static int enable_smis(struct udevice *cpu, void *unused)
24 static struct mp_flight_record mp_steps[] = {
25 MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL),
26 /* Wait for APs to finish initialization before proceeding. */
27 MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL),
30 static int detect_num_cpus(void)
35 * Use the algorithm described in Intel 64 and IA-32 Architectures
36 * Software Developer's Manual Volume 3 (3A, 3B & 3C): System
37 * Programming Guide, Jan-2015. Section 8.9.2: Hierarchical Mapping
38 * of CPUID Extended Topology Leaf.
41 struct cpuid_result leaf_b;
43 leaf_b = cpuid_ext(0xb, ecx);
46 * Bay Trail doesn't have hyperthreading so just determine the
47 * number of cores by from level type (ecx[15:8] == * 2)
49 if ((leaf_b.ecx & 0xff00) == 0x0200)
50 return leaf_b.ebx & 0xffff;
55 static int baytrail_init_cpus(void)
57 struct mp_params mp_params;
61 mp_params.num_cpus = detect_num_cpus();
62 mp_params.parallel_microcode_load = 0,
63 mp_params.flight_plan = &mp_steps[0];
64 mp_params.num_records = ARRAY_SIZE(mp_steps);
65 mp_params.microcode_pointer = 0;
67 if (mp_init(&mp_params)) {
68 printf("Warning: MP init failure\n");
76 int x86_init_cpus(void)
79 debug("Init additional CPUs\n");
86 static void set_max_freq(void)
91 /* Enable speed step */
92 msr = msr_read(MSR_IA32_MISC_ENABLES);
94 msr_write(MSR_IA32_MISC_ENABLES, msr);
97 * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
100 msr = msr_read(MSR_IACORE_RATIOS);
101 perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
104 * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
107 msr = msr_read(MSR_IACORE_VIDS);
108 perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
111 msr_write(MSR_IA32_PERF_CTL, perf_ctl);
114 static int cpu_x86_baytrail_probe(struct udevice *dev)
116 debug("Init BayTrail core\n");
119 * On BayTrail the turbo disable bit is actually scoped at the
120 * building-block level, not package. For non-BSP cores that are
121 * within a building block, enable turbo. The cores within the BSP's
122 * building block will just see it already enabled and move on.
127 /* Dynamic L2 shrink enable and threshold */
128 msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
131 msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
132 msr_setbits_64(MSR_POWER_MISC, 0x44);
134 /* Set this core to max frequency ratio */
140 static unsigned bus_freq(void)
142 msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
143 switch (clk_info.lo & 0x3) {
157 static unsigned long tsc_freq(void)
160 ulong bclk = bus_freq();
165 platform_info = msr_read(MSR_PLATFORM_INFO);
167 return bclk * ((platform_info.lo >> 8) & 0xff);
170 static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
172 info->cpu_freq = tsc_freq();
173 info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
178 static int cpu_x86_baytrail_bind(struct udevice *dev)
180 struct cpu_platdata *plat = dev_get_parent_platdata(dev);
182 plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
183 "intel,apic-id", -1);
188 static const struct cpu_ops cpu_x86_baytrail_ops = {
189 .get_desc = x86_cpu_get_desc,
190 .get_info = baytrail_get_info,
193 static const struct udevice_id cpu_x86_baytrail_ids[] = {
194 { .compatible = "intel,baytrail-cpu" },
198 U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
199 .name = "cpu_x86_baytrail",
201 .of_match = cpu_x86_baytrail_ids,
202 .bind = cpu_x86_baytrail_bind,
203 .probe = cpu_x86_baytrail_probe,
204 .ops = &cpu_x86_baytrail_ops,