blob: e35d1e748d2cf661089695ba87e66ea6f1134e0c [file] [log] [blame]
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +02001/*
2 * This file is part of the coreboot project.
3 *
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +02004 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; version 2 of
7 * the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020013 */
14
Arthur Heymansb66ee552018-05-15 16:35:45 +020015#include <assert.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020016#include <console/console.h>
17#include <device/device.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020018#include <arch/acpi.h>
19#include <cpu/cpu.h>
20#include <cpu/x86/mtrr.h>
21#include <cpu/x86/msr.h>
22#include <cpu/x86/lapic.h>
Arthur Heymansb66ee552018-05-15 16:35:45 +020023#include <cpu/x86/mp.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020024#include <cpu/intel/microcode.h>
25#include <cpu/intel/speedstep.h>
26#include <cpu/intel/turbo.h>
27#include <cpu/x86/cache.h>
28#include <cpu/x86/name.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020029#include "model_2065x.h"
30#include "chip.h"
Kyösti Mälkkif091f4d2019-08-14 03:49:21 +030031#include <cpu/intel/smm_reloc.h>
Matt DeVilliered6fe2f2016-12-14 16:12:43 -060032#include <cpu/intel/common/common.h>
Elyes HAOUASdda17fa2019-10-27 13:09:37 +010033#include <smp/node.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020034
35/*
Martin Roth4c3ab732013-07-08 16:23:54 -060036 * List of supported C-states in this processor
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020037 *
38 * Latencies are typical worst-case package exit time in uS
39 * taken from the SandyBridge BIOS specification.
40 */
41static acpi_cstate_t cstate_map[] = {
42 { /* 0: C0 */
Lee Leahy9d62e7e2017-03-15 17:40:50 -070043 }, { /* 1: C1 */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020044 .latency = 1,
45 .power = 1000,
46 .resource = {
47 .addrl = 0x00, /* MWAIT State 0 */
48 .space_id = ACPI_ADDRESS_SPACE_FIXED,
49 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
50 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +010051 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020052 }
53 },
54 { /* 2: C1E */
55 .latency = 1,
56 .power = 1000,
57 .resource = {
58 .addrl = 0x01, /* MWAIT State 0 Sub-state 1 */
59 .space_id = ACPI_ADDRESS_SPACE_FIXED,
60 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
61 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +010062 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020063 }
64 },
65 { /* 3: C3 */
66 .latency = 63,
67 .power = 500,
68 .resource = {
69 .addrl = 0x10, /* MWAIT State 1 */
70 .space_id = ACPI_ADDRESS_SPACE_FIXED,
71 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
72 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +010073 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020074 }
75 },
76 { /* 4: C6 */
77 .latency = 87,
78 .power = 350,
79 .resource = {
80 .addrl = 0x20, /* MWAIT State 2 */
81 .space_id = ACPI_ADDRESS_SPACE_FIXED,
82 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
83 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +010084 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020085 }
86 },
87 { /* 5: C7 */
88 .latency = 90,
89 .power = 200,
90 .resource = {
91 .addrl = 0x30, /* MWAIT State 3 */
92 .space_id = ACPI_ADDRESS_SPACE_FIXED,
93 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
94 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +010095 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020096 }
97 },
98 { /* 6: C7S */
99 .latency = 90,
100 .power = 200,
101 .resource = {
102 .addrl = 0x31, /* MWAIT State 3 Sub-state 1 */
103 .space_id = ACPI_ADDRESS_SPACE_FIXED,
104 .bit_width = ACPI_FFIXEDHW_VENDOR_INTEL,
105 .bit_offset = ACPI_FFIXEDHW_CLASS_MWAIT,
Elyes HAOUAS8ee161d2019-03-03 12:49:56 +0100106 .access_size = ACPI_FFIXEDHW_FLAG_HW_COORD,
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200107 }
108 },
109 { 0 }
110};
111
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200112int cpu_config_tdp_levels(void)
113{
114 msr_t platform_info;
115
116 /* Minimum CPU revision */
117 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
118 return 0;
119
120 /* Bits 34:33 indicate how many levels supported */
121 platform_info = rdmsr(MSR_PLATFORM_INFO);
122 return (platform_info.hi >> 1) & 3;
123}
124
125
126static void configure_thermal_target(void)
127{
128 struct cpu_intel_model_2065x_config *conf;
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100129 struct device *lapic;
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200130 msr_t msr;
131
132 /* Find pointer to CPU configuration */
133 lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
134 if (!lapic || !lapic->chip_info)
135 return;
136 conf = lapic->chip_info;
137
Martin Roth4c3ab732013-07-08 16:23:54 -0600138 /* Set TCC activation offset if supported */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200139 msr = rdmsr(MSR_PLATFORM_INFO);
140 if ((msr.lo & (1 << 30)) && conf->tcc_offset) {
141 msr = rdmsr(MSR_TEMPERATURE_TARGET);
142 msr.lo &= ~(0xf << 24); /* Bits 27:24 */
143 msr.lo |= (conf->tcc_offset & 0xf) << 24;
144 wrmsr(MSR_TEMPERATURE_TARGET, msr);
145 }
146}
147
148static void configure_misc(void)
149{
150 msr_t msr;
151
152 msr = rdmsr(IA32_MISC_ENABLE);
153 msr.lo |= (1 << 0); /* Fast String enable */
Lee Leahy7b5f12b92017-03-15 17:16:59 -0700154 msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200155 msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
156 wrmsr(IA32_MISC_ENABLE, msr);
157
158 /* Disable Thermal interrupts */
159 msr.lo = 0;
160 msr.hi = 0;
161 wrmsr(IA32_THERM_INTERRUPT, msr);
162
163#ifdef DISABLED
164 /* Enable package critical interrupt only */
165 msr.lo = 1 << 4;
166 msr.hi = 0;
167 wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
168#endif
169}
170
171static void enable_lapic_tpr(void)
172{
173 msr_t msr;
174
175 msr = rdmsr(MSR_PIC_MSG_CONTROL);
176 msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
177 wrmsr(MSR_PIC_MSG_CONTROL, msr);
178}
179
180
181static void set_max_ratio(void)
182{
183 msr_t msr, perf_ctl;
184
185 perf_ctl.hi = 0;
186
187 /* Check for configurable TDP option */
188 if (cpu_config_tdp_levels()) {
189 /* Set to nominal TDP ratio */
190 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
191 perf_ctl.lo = (msr.lo & 0xff) << 8;
192 } else {
193 /* Platform Info bits 15:8 give max ratio */
194 msr = rdmsr(MSR_PLATFORM_INFO);
195 perf_ctl.lo = msr.lo & 0xff00;
196 }
197 wrmsr(IA32_PERF_CTL, perf_ctl);
198
199 printk(BIOS_DEBUG, "model_x06ax: frequency set to %d\n",
Angel Pons95de2312020-02-17 13:08:53 +0100200 ((perf_ctl.lo >> 8) & 0xff) * IRONLAKE_BCLK);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200201}
202
203static void set_energy_perf_bias(u8 policy)
204{
205#ifdef DISABLED
206 msr_t msr;
207
208 /* Energy Policy is bits 3:0 */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200209 msr = rdmsr(IA32_ENERGY_PERF_BIAS);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200210 msr.lo &= ~0xf;
211 msr.lo |= policy & 0xf;
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200212 wrmsr(IA32_ENERGY_PERF_BIAS, msr);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200213
214 printk(BIOS_DEBUG, "model_x06ax: energy policy set to %u\n",
215 policy);
216#endif
217}
218
219static void configure_mca(void)
220{
221 msr_t msr;
222 int i;
223
224 msr.lo = msr.hi = 0;
225 /* This should only be done on a cold boot */
226 for (i = 0; i < 7; i++)
227 wrmsr(IA32_MC0_STATUS + (i * 4), msr);
228}
229
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100230static void model_2065x_init(struct device *cpu)
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200231{
232 char processor_name[49];
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200233
234 /* Turn on caching if we haven't already */
235 x86_enable_cache();
236
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200237 /* Clear out pending MCEs */
238 configure_mca();
239
240 /* Print processor name */
241 fill_processor_name(processor_name);
242 printk(BIOS_INFO, "CPU: %s.\n", processor_name);
Lee Leahy9d62e7e2017-03-15 17:40:50 -0700243 printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid(),
244 boot_cpu());
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200245
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200246 /* Setup Page Attribute Tables (PAT) */
247 // TODO set up PAT
248
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200249 /* Enable the local CPU APICs */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200250 enable_lapic_tpr();
251 setup_lapic();
252
Matt DeVilliered6fe2f2016-12-14 16:12:43 -0600253 /* Set virtualization based on Kconfig option */
Matt DeVillierf9aed652018-12-15 15:57:33 -0600254 set_vmx_and_lock();
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200255
256 /* Configure Enhanced SpeedStep and Thermal Sensors */
257 configure_misc();
258
259 /* Thermal throttle activation offset */
260 configure_thermal_target();
261
262 /* Set energy policy */
263 set_energy_perf_bias(ENERGY_POLICY_NORMAL);
264
265 /* Set Max Ratio */
266 set_max_ratio();
267
268 /* Enable Turbo */
269 enable_turbo();
Arthur Heymansb66ee552018-05-15 16:35:45 +0200270}
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200271
Arthur Heymansb66ee552018-05-15 16:35:45 +0200272/* MP initialization support. */
273static const void *microcode_patch;
274
275static void pre_mp_init(void)
276{
277 /* Setup MTRRs based on physical address size. */
278 x86_setup_mtrrs_with_detect();
279 x86_mtrr_check();
280}
281
282static int get_cpu_count(void)
283{
284 msr_t msr;
285 int num_threads;
286 int num_cores;
287
Elyes HAOUASa6a396d2019-05-26 13:25:30 +0200288 msr = rdmsr(MSR_CORE_THREAD_COUNT);
Arthur Heymansb66ee552018-05-15 16:35:45 +0200289 num_threads = (msr.lo >> 0) & 0xffff;
290 num_cores = (msr.lo >> 16) & 0xffff;
291 printk(BIOS_DEBUG, "CPU has %u cores, %u threads enabled.\n",
292 num_cores, num_threads);
293
294 return num_threads;
295}
296
297static void get_microcode_info(const void **microcode, int *parallel)
298{
299 microcode_patch = intel_microcode_find();
300 *microcode = microcode_patch;
301 *parallel = 1;
302}
303
304static void per_cpu_smm_trigger(void)
305{
306 /* Relocate the SMM handler. */
307 smm_relocate();
308
309 /* After SMM relocation a 2nd microcode load is required. */
310 intel_microcode_load_unlocked(microcode_patch);
311}
312
313static void post_mp_init(void)
314{
315 /* Now that all APs have been relocated as well as the BSP let SMIs
316 * start flowing. */
Kyösti Mälkkifaf20d32019-08-14 05:41:41 +0300317 smm_southbridge_enable_smi();
Arthur Heymansb66ee552018-05-15 16:35:45 +0200318
319 /* Lock down the SMRAM space. */
320 smm_lock();
321}
322
323
324static const struct mp_ops mp_ops = {
325 .pre_mp_init = pre_mp_init,
326 .get_cpu_count = get_cpu_count,
327 .get_smm_info = smm_info,
328 .get_microcode_info = get_microcode_info,
329 .pre_mp_smm_init = smm_initialize,
330 .per_cpu_smm_trigger = per_cpu_smm_trigger,
331 .relocation_handler = smm_relocation_handler,
332 .post_mp_init = post_mp_init,
333};
334
Kyösti Mälkkib3267e02019-08-13 16:44:04 +0300335void mp_init_cpus(struct bus *cpu_bus)
Arthur Heymansb66ee552018-05-15 16:35:45 +0200336{
337 if (mp_init_with_smm(cpu_bus, &mp_ops))
338 printk(BIOS_ERR, "MP initialization failure.\n");
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200339}
340
341static struct device_operations cpu_dev_ops = {
342 .init = model_2065x_init,
343};
344
Angel Ponsa8305e72020-02-17 14:24:04 +0100345/* Arrandale / Clarkdale CPU IDs */
Jonathan Neuschäfer8f06ce32017-11-20 01:56:44 +0100346static const struct cpu_device_id cpu_table[] = {
Angel Ponsa8305e72020-02-17 14:24:04 +0100347 { X86_VENDOR_INTEL, 0x20650 },
348 { X86_VENDOR_INTEL, 0x20651 },
349 { X86_VENDOR_INTEL, 0x20652 },
350 { X86_VENDOR_INTEL, 0x20654 },
351 { X86_VENDOR_INTEL, 0x20655 },
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200352 { 0, 0 },
353};
354
355static const struct cpu_driver driver __cpu_driver = {
356 .ops = &cpu_dev_ops,
357 .id_table = cpu_table,
358 .cstates = cstate_map,
359};