xref: /openbmc/u-boot/arch/x86/cpu/baytrail/cpu.c (revision 60570df1)
1 /*
2  * Copyright (C) 2015 Google, Inc
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  *
6  * Based on code from coreboot
7  */
8 
9 #include <common.h>
10 #include <cpu.h>
11 #include <dm.h>
12 #include <asm/cpu.h>
13 #include <asm/lapic.h>
14 #include <asm/mp.h>
15 #include <asm/msr.h>
16 #include <asm/turbo.h>
17 
18 #ifdef CONFIG_SMP
19 static int enable_smis(struct udevice *cpu, void *unused)
20 {
21 	return 0;
22 }
23 
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),
28 };
29 
30 static int detect_num_cpus(void)
31 {
32 	int ecx = 0;
33 
34 	/*
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.
39 	 */
40 	while (1) {
41 		struct cpuid_result leaf_b;
42 
43 		leaf_b = cpuid_ext(0xb, ecx);
44 
45 		/*
46 		 * Bay Trail doesn't have hyperthreading so just determine the
47 		 * number of cores by from level type (ecx[15:8] == * 2)
48 		 */
49 		if ((leaf_b.ecx & 0xff00) == 0x0200)
50 			return leaf_b.ebx & 0xffff;
51 		ecx++;
52 	}
53 }
54 
55 static int baytrail_init_cpus(void)
56 {
57 	struct mp_params mp_params;
58 
59 	lapic_setup();
60 
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;
66 
67 	if (mp_init(&mp_params)) {
68 		printf("Warning: MP init failure\n");
69 		return -EIO;
70 	}
71 
72 	return 0;
73 }
74 #endif
75 
76 int x86_init_cpus(void)
77 {
78 #ifdef CONFIG_SMP
79 	debug("Init additional CPUs\n");
80 	baytrail_init_cpus();
81 #endif
82 
83 	return 0;
84 }
85 
86 static void set_max_freq(void)
87 {
88 	msr_t perf_ctl;
89 	msr_t msr;
90 
91 	/* Enable speed step */
92 	msr = msr_read(MSR_IA32_MISC_ENABLES);
93 	msr.lo |= (1 << 16);
94 	msr_write(MSR_IA32_MISC_ENABLES, msr);
95 
96 	/*
97 	 * Set guaranteed ratio [21:16] from IACORE_RATIOS to bits [15:8] of
98 	 * the PERF_CTL
99 	 */
100 	msr = msr_read(MSR_IACORE_RATIOS);
101 	perf_ctl.lo = (msr.lo & 0x3f0000) >> 8;
102 
103 	/*
104 	 * Set guaranteed vid [21:16] from IACORE_VIDS to bits [7:0] of
105 	 * the PERF_CTL
106 	 */
107 	msr = msr_read(MSR_IACORE_VIDS);
108 	perf_ctl.lo |= (msr.lo & 0x7f0000) >> 16;
109 	perf_ctl.hi = 0;
110 
111 	msr_write(MSR_IA32_PERF_CTL, perf_ctl);
112 }
113 
114 static int cpu_x86_baytrail_probe(struct udevice *dev)
115 {
116 	debug("Init BayTrail core\n");
117 
118 	/*
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.
123 	 */
124 	if (lapicid())
125 		turbo_enable();
126 
127 	/* Dynamic L2 shrink enable and threshold */
128 	msr_clrsetbits_64(MSR_PMG_CST_CONFIG_CONTROL, 0x3f000f, 0xe0008),
129 
130 	/* Disable C1E */
131 	msr_clrsetbits_64(MSR_POWER_CTL, 2, 0);
132 	msr_setbits_64(MSR_POWER_MISC, 0x44);
133 
134 	/* Set this core to max frequency ratio */
135 	set_max_freq();
136 
137 	return 0;
138 }
139 
140 static unsigned bus_freq(void)
141 {
142 	msr_t clk_info = msr_read(MSR_BSEL_CR_OVERCLOCK_CONTROL);
143 	switch (clk_info.lo & 0x3) {
144 	case 0:
145 		return 83333333;
146 	case 1:
147 		return 100000000;
148 	case 2:
149 		return 133333333;
150 	case 3:
151 		return 116666666;
152 	default:
153 		return 0;
154 	}
155 }
156 
157 static unsigned long tsc_freq(void)
158 {
159 	msr_t platform_info;
160 	ulong bclk = bus_freq();
161 
162 	if (!bclk)
163 		return 0;
164 
165 	platform_info = msr_read(MSR_PLATFORM_INFO);
166 
167 	return bclk * ((platform_info.lo >> 8) & 0xff);
168 }
169 
170 static int baytrail_get_info(struct udevice *dev, struct cpu_info *info)
171 {
172 	info->cpu_freq = tsc_freq();
173 	info->features = 1 << CPU_FEAT_L1_CACHE | 1 << CPU_FEAT_MMU;
174 
175 	return 0;
176 }
177 
178 static int cpu_x86_baytrail_bind(struct udevice *dev)
179 {
180 	struct cpu_platdata *plat = dev_get_parent_platdata(dev);
181 
182 	plat->cpu_id = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
183 				      "intel,apic-id", -1);
184 
185 	return 0;
186 }
187 
188 static const struct cpu_ops cpu_x86_baytrail_ops = {
189 	.get_desc	= x86_cpu_get_desc,
190 	.get_info	= baytrail_get_info,
191 };
192 
193 static const struct udevice_id cpu_x86_baytrail_ids[] = {
194 	{ .compatible = "intel,baytrail-cpu" },
195 	{ }
196 };
197 
198 U_BOOT_DRIVER(cpu_x86_baytrail_drv) = {
199 	.name		= "cpu_x86_baytrail",
200 	.id		= UCLASS_CPU,
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,
205 };
206