Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / x86 / cpu / ivybridge / model_206ax.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * From Coreboot file of same name
4  *
5  * Copyright (C) 2007-2009 coresystems GmbH
6  * Copyright (C) 2011 The Chromium Authors
7  */
8
9 #include <common.h>
10 #include <cpu.h>
11 #include <dm.h>
12 #include <fdtdec.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <asm/cpu.h>
16 #include <asm/cpu_common.h>
17 #include <asm/cpu_x86.h>
18 #include <asm/msr.h>
19 #include <asm/msr-index.h>
20 #include <asm/mtrr.h>
21 #include <asm/processor.h>
22 #include <asm/speedstep.h>
23 #include <asm/turbo.h>
24 #include <asm/arch/model_206ax.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 static void enable_vmx(void)
29 {
30         struct cpuid_result regs;
31 #ifdef CONFIG_ENABLE_VMX
32         int enable = true;
33 #else
34         int enable = false;
35 #endif
36         msr_t msr;
37
38         regs = cpuid(1);
39         /* Check that the VMX is supported before reading or writing the MSR. */
40         if (!((regs.ecx & CPUID_VMX) || (regs.ecx & CPUID_SMX)))
41                 return;
42
43         msr = msr_read(MSR_IA32_FEATURE_CONTROL);
44
45         if (msr.lo & (1 << 0)) {
46                 debug("VMX is locked, so %s will do nothing\n", __func__);
47                 /* VMX locked. If we set it again we get an illegal
48                  * instruction
49                  */
50                 return;
51         }
52
53         /* The IA32_FEATURE_CONTROL MSR may initialize with random values.
54          * It must be cleared regardless of VMX config setting.
55          */
56         msr.hi = 0;
57         msr.lo = 0;
58
59         debug("%s VMX\n", enable ? "Enabling" : "Disabling");
60
61         /*
62          * Even though the Intel manual says you must set the lock bit in
63          * addition to the VMX bit in order for VMX to work, it is incorrect.
64          * Thus we leave it unlocked for the OS to manage things itself.
65          * This is good for a few reasons:
66          * - No need to reflash the bios just to toggle the lock bit.
67          * - The VMX bits really really should match each other across cores,
68          *   so hard locking it on one while another has the opposite setting
69          *   can easily lead to crashes as code using VMX migrates between
70          *   them.
71          * - Vendors that want to "upsell" from a bios that disables+locks to
72          *   one that doesn't is sleazy.
73          * By leaving this to the OS (e.g. Linux), people can do exactly what
74          * they want on the fly, and do it correctly (e.g. across multiple
75          * cores).
76          */
77         if (enable) {
78                 msr.lo |= (1 << 2);
79                 if (regs.ecx & CPUID_SMX)
80                         msr.lo |= (1 << 1);
81         }
82
83         msr_write(MSR_IA32_FEATURE_CONTROL, msr);
84 }
85
86 /* Convert time in seconds to POWER_LIMIT_1_TIME MSR value */
87 static const u8 power_limit_time_sec_to_msr[] = {
88         [0]   = 0x00,
89         [1]   = 0x0a,
90         [2]   = 0x0b,
91         [3]   = 0x4b,
92         [4]   = 0x0c,
93         [5]   = 0x2c,
94         [6]   = 0x4c,
95         [7]   = 0x6c,
96         [8]   = 0x0d,
97         [10]  = 0x2d,
98         [12]  = 0x4d,
99         [14]  = 0x6d,
100         [16]  = 0x0e,
101         [20]  = 0x2e,
102         [24]  = 0x4e,
103         [28]  = 0x6e,
104         [32]  = 0x0f,
105         [40]  = 0x2f,
106         [48]  = 0x4f,
107         [56]  = 0x6f,
108         [64]  = 0x10,
109         [80]  = 0x30,
110         [96]  = 0x50,
111         [112] = 0x70,
112         [128] = 0x11,
113 };
114
115 /* Convert POWER_LIMIT_1_TIME MSR value to seconds */
116 static const u8 power_limit_time_msr_to_sec[] = {
117         [0x00] = 0,
118         [0x0a] = 1,
119         [0x0b] = 2,
120         [0x4b] = 3,
121         [0x0c] = 4,
122         [0x2c] = 5,
123         [0x4c] = 6,
124         [0x6c] = 7,
125         [0x0d] = 8,
126         [0x2d] = 10,
127         [0x4d] = 12,
128         [0x6d] = 14,
129         [0x0e] = 16,
130         [0x2e] = 20,
131         [0x4e] = 24,
132         [0x6e] = 28,
133         [0x0f] = 32,
134         [0x2f] = 40,
135         [0x4f] = 48,
136         [0x6f] = 56,
137         [0x10] = 64,
138         [0x30] = 80,
139         [0x50] = 96,
140         [0x70] = 112,
141         [0x11] = 128,
142 };
143
144 bool cpu_ivybridge_config_tdp_levels(void)
145 {
146         struct cpuid_result result;
147
148         /* Minimum CPU revision */
149         result = cpuid(1);
150         if (result.eax < IVB_CONFIG_TDP_MIN_CPUID)
151                 return false;
152
153         return cpu_config_tdp_levels();
154 }
155
156 /*
157  * Configure processor power limits if possible
158  * This must be done AFTER set of BIOS_RESET_CPL
159  */
160 void set_power_limits(u8 power_limit_1_time)
161 {
162         msr_t msr = msr_read(MSR_PLATFORM_INFO);
163         msr_t limit;
164         unsigned power_unit;
165         unsigned tdp, min_power, max_power, max_time;
166         u8 power_limit_1_val;
167
168         if (power_limit_1_time > ARRAY_SIZE(power_limit_time_sec_to_msr))
169                 return;
170
171         if (!(msr.lo & PLATFORM_INFO_SET_TDP))
172                 return;
173
174         /* Get units */
175         msr = msr_read(MSR_PKG_POWER_SKU_UNIT);
176         power_unit = 2 << ((msr.lo & 0xf) - 1);
177
178         /* Get power defaults for this SKU */
179         msr = msr_read(MSR_PKG_POWER_SKU);
180         tdp = msr.lo & 0x7fff;
181         min_power = (msr.lo >> 16) & 0x7fff;
182         max_power = msr.hi & 0x7fff;
183         max_time = (msr.hi >> 16) & 0x7f;
184
185         debug("CPU TDP: %u Watts\n", tdp / power_unit);
186
187         if (power_limit_time_msr_to_sec[max_time] > power_limit_1_time)
188                 power_limit_1_time = power_limit_time_msr_to_sec[max_time];
189
190         if (min_power > 0 && tdp < min_power)
191                 tdp = min_power;
192
193         if (max_power > 0 && tdp > max_power)
194                 tdp = max_power;
195
196         power_limit_1_val = power_limit_time_sec_to_msr[power_limit_1_time];
197
198         /* Set long term power limit to TDP */
199         limit.lo = 0;
200         limit.lo |= tdp & PKG_POWER_LIMIT_MASK;
201         limit.lo |= PKG_POWER_LIMIT_EN;
202         limit.lo |= (power_limit_1_val & PKG_POWER_LIMIT_TIME_MASK) <<
203                 PKG_POWER_LIMIT_TIME_SHIFT;
204
205         /* Set short term power limit to 1.25 * TDP */
206         limit.hi = 0;
207         limit.hi |= ((tdp * 125) / 100) & PKG_POWER_LIMIT_MASK;
208         limit.hi |= PKG_POWER_LIMIT_EN;
209         /* Power limit 2 time is only programmable on SNB EP/EX */
210
211         msr_write(MSR_PKG_POWER_LIMIT, limit);
212
213         /* Use nominal TDP values for CPUs with configurable TDP */
214         if (cpu_ivybridge_config_tdp_levels()) {
215                 msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
216                 limit.hi = 0;
217                 limit.lo = msr.lo & 0xff;
218                 msr_write(MSR_TURBO_ACTIVATION_RATIO, limit);
219         }
220 }
221
222 static void configure_c_states(void)
223 {
224         struct cpuid_result result;
225         msr_t msr;
226
227         msr = msr_read(MSR_PMG_CST_CONFIG_CTL);
228         msr.lo |= (1 << 28);    /* C1 Auto Undemotion Enable */
229         msr.lo |= (1 << 27);    /* C3 Auto Undemotion Enable */
230         msr.lo |= (1 << 26);    /* C1 Auto Demotion Enable */
231         msr.lo |= (1 << 25);    /* C3 Auto Demotion Enable */
232         msr.lo &= ~(1 << 10);   /* Disable IO MWAIT redirection */
233         msr.lo |= 7;            /* No package C-state limit */
234         msr_write(MSR_PMG_CST_CONFIG_CTL, msr);
235
236         msr = msr_read(MSR_PMG_IO_CAPTURE_ADR);
237         msr.lo &= ~0x7ffff;
238         msr.lo |= (PMB0_BASE + 4);      /* LVL_2 base address */
239         msr.lo |= (2 << 16);            /* CST Range: C7 is max C-state */
240         msr_write(MSR_PMG_IO_CAPTURE_ADR, msr);
241
242         msr = msr_read(MSR_MISC_PWR_MGMT);
243         msr.lo &= ~(1 << 0);    /* Enable P-state HW_ALL coordination */
244         msr_write(MSR_MISC_PWR_MGMT, msr);
245
246         msr = msr_read(MSR_POWER_CTL);
247         msr.lo |= (1 << 18);    /* Enable Energy Perf Bias MSR 0x1b0 */
248         msr.lo |= (1 << 1);     /* C1E Enable */
249         msr.lo |= (1 << 0);     /* Bi-directional PROCHOT# */
250         msr_write(MSR_POWER_CTL, msr);
251
252         /* C3 Interrupt Response Time Limit */
253         msr.hi = 0;
254         msr.lo = IRTL_VALID | IRTL_1024_NS | 0x50;
255         msr_write(MSR_PKGC3_IRTL, msr);
256
257         /* C6 Interrupt Response Time Limit */
258         msr.hi = 0;
259         msr.lo = IRTL_VALID | IRTL_1024_NS | 0x68;
260         msr_write(MSR_PKGC6_IRTL, msr);
261
262         /* C7 Interrupt Response Time Limit */
263         msr.hi = 0;
264         msr.lo = IRTL_VALID | IRTL_1024_NS | 0x6D;
265         msr_write(MSR_PKGC7_IRTL, msr);
266
267         /* Primary Plane Current Limit */
268         msr = msr_read(MSR_PP0_CURRENT_CONFIG);
269         msr.lo &= ~0x1fff;
270         msr.lo |= PP0_CURRENT_LIMIT;
271         msr_write(MSR_PP0_CURRENT_CONFIG, msr);
272
273         /* Secondary Plane Current Limit */
274         msr = msr_read(MSR_PP1_CURRENT_CONFIG);
275         msr.lo &= ~0x1fff;
276         result = cpuid(1);
277         if (result.eax >= 0x30600)
278                 msr.lo |= PP1_CURRENT_LIMIT_IVB;
279         else
280                 msr.lo |= PP1_CURRENT_LIMIT_SNB;
281         msr_write(MSR_PP1_CURRENT_CONFIG, msr);
282 }
283
284 static void configure_misc(void)
285 {
286         msr_t msr;
287
288         msr = msr_read(IA32_MISC_ENABLE);
289         msr.lo |= (1 << 0);       /* Fast String enable */
290         msr.lo |= (1 << 3);       /* TM1/TM2/EMTTM enable */
291         msr.lo |= (1 << 16);      /* Enhanced SpeedStep Enable */
292         msr_write(IA32_MISC_ENABLE, msr);
293
294         /* Disable Thermal interrupts */
295         msr.lo = 0;
296         msr.hi = 0;
297         msr_write(IA32_THERM_INTERRUPT, msr);
298
299         /* Enable package critical interrupt only */
300         msr.lo = 1 << 4;
301         msr.hi = 0;
302         msr_write(IA32_PACKAGE_THERM_INTERRUPT, msr);
303 }
304
305 static void enable_lapic_tpr(void)
306 {
307         msr_t msr;
308
309         msr = msr_read(MSR_PIC_MSG_CONTROL);
310         msr.lo &= ~(1 << 10);   /* Enable APIC TPR updates */
311         msr_write(MSR_PIC_MSG_CONTROL, msr);
312 }
313
314 static void configure_dca_cap(void)
315 {
316         struct cpuid_result cpuid_regs;
317         msr_t msr;
318
319         /* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
320         cpuid_regs = cpuid(1);
321         if (cpuid_regs.ecx & (1 << 18)) {
322                 msr = msr_read(IA32_PLATFORM_DCA_CAP);
323                 msr.lo |= 1;
324                 msr_write(IA32_PLATFORM_DCA_CAP, msr);
325         }
326 }
327
328 static void set_max_ratio(void)
329 {
330         msr_t msr;
331         uint ratio;
332
333         /* Check for configurable TDP option */
334         if (cpu_ivybridge_config_tdp_levels()) {
335                 /* Set to nominal TDP ratio */
336                 msr = msr_read(MSR_CONFIG_TDP_NOMINAL);
337                 ratio = msr.lo & 0xff;
338         } else {
339                 /* Platform Info bits 15:8 give max ratio */
340                 msr = msr_read(MSR_PLATFORM_INFO);
341                 ratio = (msr.lo & 0xff00) >> 8;
342         }
343         cpu_set_perf_control(ratio);
344 }
345
346 static void set_energy_perf_bias(u8 policy)
347 {
348         msr_t msr;
349
350         /* Energy Policy is bits 3:0 */
351         msr = msr_read(IA32_ENERGY_PERFORMANCE_BIAS);
352         msr.lo &= ~0xf;
353         msr.lo |= policy & 0xf;
354         msr_write(IA32_ENERGY_PERFORMANCE_BIAS, msr);
355
356         debug("model_x06ax: energy policy set to %u\n", policy);
357 }
358
359 static void configure_mca(void)
360 {
361         msr_t msr;
362         int i;
363
364         msr.lo = 0;
365         msr.hi = 0;
366         /* This should only be done on a cold boot */
367         for (i = 0; i < 7; i++)
368                 msr_write(IA32_MC0_STATUS + (i * 4), msr);
369 }
370
371 static int model_206ax_init(struct udevice *dev)
372 {
373         int ret;
374
375         /* Clear out pending MCEs */
376         configure_mca();
377
378         /* Enable the local cpu apics */
379         enable_lapic_tpr();
380
381         /* Enable virtualization if enabled in CMOS */
382         enable_vmx();
383
384         /* Configure C States */
385         configure_c_states();
386
387         /* Configure Enhanced SpeedStep and Thermal Sensors */
388         configure_misc();
389
390         /* Thermal throttle activation offset */
391         ret = cpu_configure_thermal_target(dev);
392         if (ret) {
393                 debug("Cannot set thermal target\n");
394                 if (ret != -ENOENT)
395                         return ret;
396         }
397
398         /* Enable Direct Cache Access */
399         configure_dca_cap();
400
401         /* Set energy policy */
402         set_energy_perf_bias(ENERGY_POLICY_NORMAL);
403
404         /* Set Max Ratio */
405         set_max_ratio();
406
407         /* Enable Turbo */
408         turbo_enable();
409
410         return 0;
411 }
412
413 static int model_206ax_get_info(struct udevice *dev, struct cpu_info *info)
414 {
415         return cpu_intel_get_info(info, INTEL_BCLK_MHZ);
416
417         return 0;
418 }
419
420 static int model_206ax_get_count(struct udevice *dev)
421 {
422         return 4;
423 }
424
425 static int cpu_x86_model_206ax_probe(struct udevice *dev)
426 {
427         if (dev->seq == 0)
428                 model_206ax_init(dev);
429
430         return 0;
431 }
432
433 static const struct cpu_ops cpu_x86_model_206ax_ops = {
434         .get_desc       = cpu_x86_get_desc,
435         .get_info       = model_206ax_get_info,
436         .get_count      = model_206ax_get_count,
437         .get_vendor     = cpu_x86_get_vendor,
438 };
439
440 static const struct udevice_id cpu_x86_model_206ax_ids[] = {
441         { .compatible = "intel,core-gen3" },
442         { }
443 };
444
445 U_BOOT_DRIVER(cpu_x86_model_206ax_drv) = {
446         .name           = "cpu_x86_model_206ax",
447         .id             = UCLASS_CPU,
448         .of_match       = cpu_x86_model_206ax_ids,
449         .bind           = cpu_x86_bind,
450         .probe          = cpu_x86_model_206ax_probe,
451         .ops            = &cpu_x86_model_206ax_ops,
452         .flags          = DM_FLAG_PRE_RELOC,
453 };