blob: f08a058a57e0513116f979b5f6d4a2af2237bd41 [file] [log] [blame]
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2007-2009 coresystems GmbH
5 * Copyright (C) 2011 The ChromiumOS Authors. All rights reserved.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; version 2 of
10 * the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020016 */
17
18#include <console/console.h>
19#include <device/device.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020020#include <arch/acpi.h>
21#include <cpu/cpu.h>
22#include <cpu/x86/mtrr.h>
23#include <cpu/x86/msr.h>
24#include <cpu/x86/lapic.h>
25#include <cpu/intel/microcode.h>
26#include <cpu/intel/speedstep.h>
27#include <cpu/intel/turbo.h>
28#include <cpu/x86/cache.h>
29#include <cpu/x86/name.h>
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +020030#include "model_2065x.h"
31#include "chip.h"
Vladimir Serbinenko0f9aa1c2015-05-29 16:52:50 +020032#include <cpu/intel/smm/gen1/smi.h>
Matt DeVilliered6fe2f2016-12-14 16:12:43 -060033#include <cpu/intel/common/common.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 Serbinenko0f9aa1c2015-05-29 16:52:50 +0200112int cpu_get_apic_id_map(int *apic_id_map)
113{
114 int i;
115 struct cpuid_result result;
Lee Leahy73a28942017-03-15 17:52:06 -0700116 unsigned int threads_per_package, threads_per_core;
Vladimir Serbinenko0f9aa1c2015-05-29 16:52:50 +0200117
118 /* Logical processors (threads) per core */
119 result = cpuid_ext(0xb, 0);
120 threads_per_core = result.ebx & 0xffff;
121
122 /* Logical processors (threads) per package */
123 result = cpuid_ext(0xb, 1);
124 threads_per_package = result.ebx & 0xffff;
125
126 for (i = 0; i < threads_per_package && i < CONFIG_MAX_CPUS; ++i) {
127 apic_id_map[i] = (i % threads_per_core)
128 + ((i / threads_per_core) << 2);
129 }
130
131 return threads_per_package;
132}
133
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200134
135int cpu_config_tdp_levels(void)
136{
137 msr_t platform_info;
138
139 /* Minimum CPU revision */
140 if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID)
141 return 0;
142
143 /* Bits 34:33 indicate how many levels supported */
144 platform_info = rdmsr(MSR_PLATFORM_INFO);
145 return (platform_info.hi >> 1) & 3;
146}
147
148
149static void configure_thermal_target(void)
150{
151 struct cpu_intel_model_2065x_config *conf;
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100152 struct device *lapic;
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200153 msr_t msr;
154
155 /* Find pointer to CPU configuration */
156 lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
157 if (!lapic || !lapic->chip_info)
158 return;
159 conf = lapic->chip_info;
160
Martin Roth4c3ab732013-07-08 16:23:54 -0600161 /* Set TCC activation offset if supported */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200162 msr = rdmsr(MSR_PLATFORM_INFO);
163 if ((msr.lo & (1 << 30)) && conf->tcc_offset) {
164 msr = rdmsr(MSR_TEMPERATURE_TARGET);
165 msr.lo &= ~(0xf << 24); /* Bits 27:24 */
166 msr.lo |= (conf->tcc_offset & 0xf) << 24;
167 wrmsr(MSR_TEMPERATURE_TARGET, msr);
168 }
169}
170
171static void configure_misc(void)
172{
173 msr_t msr;
174
175 msr = rdmsr(IA32_MISC_ENABLE);
176 msr.lo |= (1 << 0); /* Fast String enable */
Lee Leahy7b5f12b92017-03-15 17:16:59 -0700177 msr.lo |= (1 << 3); /* TM1/TM2/EMTTM enable */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200178 msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
179 wrmsr(IA32_MISC_ENABLE, msr);
180
181 /* Disable Thermal interrupts */
182 msr.lo = 0;
183 msr.hi = 0;
184 wrmsr(IA32_THERM_INTERRUPT, msr);
185
186#ifdef DISABLED
187 /* Enable package critical interrupt only */
188 msr.lo = 1 << 4;
189 msr.hi = 0;
190 wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
191#endif
192}
193
194static void enable_lapic_tpr(void)
195{
196 msr_t msr;
197
198 msr = rdmsr(MSR_PIC_MSG_CONTROL);
199 msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
200 wrmsr(MSR_PIC_MSG_CONTROL, msr);
201}
202
203
204static void set_max_ratio(void)
205{
206 msr_t msr, perf_ctl;
207
208 perf_ctl.hi = 0;
209
210 /* Check for configurable TDP option */
211 if (cpu_config_tdp_levels()) {
212 /* Set to nominal TDP ratio */
213 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
214 perf_ctl.lo = (msr.lo & 0xff) << 8;
215 } else {
216 /* Platform Info bits 15:8 give max ratio */
217 msr = rdmsr(MSR_PLATFORM_INFO);
218 perf_ctl.lo = msr.lo & 0xff00;
219 }
220 wrmsr(IA32_PERF_CTL, perf_ctl);
221
222 printk(BIOS_DEBUG, "model_x06ax: frequency set to %d\n",
Vladimir Serbinenko71f35eb2013-11-12 23:32:52 +0100223 ((perf_ctl.lo >> 8) & 0xff) * NEHALEM_BCLK);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200224}
225
226static void set_energy_perf_bias(u8 policy)
227{
228#ifdef DISABLED
229 msr_t msr;
230
231 /* Energy Policy is bits 3:0 */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200232 msr = rdmsr(IA32_ENERGY_PERF_BIAS);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200233 msr.lo &= ~0xf;
234 msr.lo |= policy & 0xf;
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200235 wrmsr(IA32_ENERGY_PERF_BIAS, msr);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200236
237 printk(BIOS_DEBUG, "model_x06ax: energy policy set to %u\n",
238 policy);
239#endif
240}
241
242static void configure_mca(void)
243{
244 msr_t msr;
245 int i;
246
247 msr.lo = msr.hi = 0;
248 /* This should only be done on a cold boot */
249 for (i = 0; i < 7; i++)
250 wrmsr(IA32_MC0_STATUS + (i * 4), msr);
251}
252
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200253/*
254 * Initialize any extra cores/threads in this package.
255 */
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100256static void intel_cores_init(struct device *cpu)
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200257{
258 struct cpuid_result result;
Lee Leahy73a28942017-03-15 17:52:06 -0700259 unsigned int threads_per_package, threads_per_core, i;
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200260
261 /* Logical processors (threads) per core */
262 result = cpuid_ext(0xb, 0);
263 threads_per_core = result.ebx & 0xffff;
264
265 /* Logical processors (threads) per package */
266 result = cpuid_ext(0xb, 1);
267 threads_per_package = result.ebx & 0xffff;
268
269 /* Only initialize extra cores from BSP */
270 if (cpu->path.apic.apic_id)
271 return;
272
273 printk(BIOS_DEBUG, "CPU: %u has %u cores, %u threads per core\n",
274 cpu->path.apic.apic_id, threads_per_package/threads_per_core,
275 threads_per_core);
276
277 for (i = 1; i < threads_per_package; ++i) {
278 struct device_path cpu_path;
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100279 struct device *new;
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200280
Elyes HAOUASd82be922016-07-28 18:58:27 +0200281 /* Build the CPU device path */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200282 cpu_path.type = DEVICE_PATH_APIC;
283 cpu_path.apic.apic_id =
Vladimir Serbinenko10b39742014-02-19 22:00:00 +0100284 cpu->path.apic.apic_id + (i % threads_per_core)
285 + ((i / threads_per_core) << 2);
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200286
Elyes HAOUASd82be922016-07-28 18:58:27 +0200287 /* Allocate the new CPU device structure */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200288 new = alloc_dev(cpu->bus, &cpu_path);
289 if (!new)
290 continue;
291
292 printk(BIOS_DEBUG, "CPU: %u has core %u\n",
293 cpu->path.apic.apic_id,
294 new->path.apic.apic_id);
295
Elyes HAOUASd82be922016-07-28 18:58:27 +0200296 /* Start the new CPU */
Kyösti Mälkki0cc2ce42017-08-18 11:46:32 +0300297 if (is_smp_boot() && !start_cpu(new)) {
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200298 /* Record the error in cpu? */
299 printk(BIOS_ERR, "CPU %u would not start!\n",
300 new->path.apic.apic_id);
301 }
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200302 }
303}
304
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100305static void model_2065x_init(struct device *cpu)
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200306{
307 char processor_name[49];
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200308
309 /* Turn on caching if we haven't already */
310 x86_enable_cache();
311
312 intel_update_microcode_from_cbfs();
313
314 /* Clear out pending MCEs */
315 configure_mca();
316
317 /* Print processor name */
318 fill_processor_name(processor_name);
319 printk(BIOS_INFO, "CPU: %s.\n", processor_name);
Lee Leahy9d62e7e2017-03-15 17:40:50 -0700320 printk(BIOS_INFO, "CPU:lapic=%ld, boot_cpu=%d\n", lapicid(),
321 boot_cpu());
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200322
323 /* Setup MTRRs based on physical address size */
Aaron Durbin2a081372016-03-07 16:23:47 -0600324 x86_setup_mtrrs_with_detect();
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200325 x86_mtrr_check();
326
327 /* Setup Page Attribute Tables (PAT) */
328 // TODO set up PAT
329
Elyes HAOUASd6e96862016-08-21 10:12:15 +0200330 /* Enable the local CPU APICs */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200331 enable_lapic_tpr();
332 setup_lapic();
333
Matt DeVilliered6fe2f2016-12-14 16:12:43 -0600334 /* Set virtualization based on Kconfig option */
Matt DeVillierf9aed652018-12-15 15:57:33 -0600335 set_vmx_and_lock();
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200336
337 /* Configure Enhanced SpeedStep and Thermal Sensors */
338 configure_misc();
339
340 /* Thermal throttle activation offset */
341 configure_thermal_target();
342
343 /* Set energy policy */
344 set_energy_perf_bias(ENERGY_POLICY_NORMAL);
345
346 /* Set Max Ratio */
347 set_max_ratio();
348
349 /* Enable Turbo */
350 enable_turbo();
351
352 /* Start up extra cores */
353 intel_cores_init(cpu);
354}
355
356static struct device_operations cpu_dev_ops = {
357 .init = model_2065x_init,
358};
359
Jonathan Neuschäfer8f06ce32017-11-20 01:56:44 +0100360static const struct cpu_device_id cpu_table[] = {
Vladimir Serbinenko5ef42202014-02-01 16:24:22 +0100361 { X86_VENDOR_INTEL, 0x20652 }, /* Intel Nehalem */
Vladimir Serbinenko22dcdd92013-06-06 22:10:45 +0200362 { X86_VENDOR_INTEL, 0x20655 }, /* Intel Nehalem */
363 { 0, 0 },
364};
365
366static const struct cpu_driver driver __cpu_driver = {
367 .ops = &cpu_dev_ops,
368 .id_table = cpu_table,
369 .cstates = cstate_map,
370};