blob: 02e60322653256b3edba45768e7c5e056844af2a [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Thomas Jourdan1a692d82009-07-01 17:01:17 +00002
3#include <console/console.h>
4#include <device/device.h>
Thomas Jourdan1a692d82009-07-01 17:01:17 +00005#include <cpu/cpu.h>
Thomas Jourdan1a692d82009-07-01 17:01:17 +00006#include <cpu/x86/msr.h>
Stefan Reinauer2a27b202010-12-11 22:14:44 +00007#include <cpu/intel/speedstep.h>
Thomas Jourdan1a692d82009-07-01 17:01:17 +00008#include <cpu/x86/cache.h>
Uwe Hermannaac8f662010-09-29 09:54:16 +00009#include <cpu/x86/name.h>
Kyösti Mälkkif091f4d2019-08-14 03:49:21 +030010#include <cpu/intel/smm_reloc.h>
Elyes HAOUAS273c3482020-06-15 18:29:43 +020011
Nico Huber68d7c7a2012-10-02 11:46:11 +020012#include "chip.h"
13
Nico Huber68d7c7a2012-10-02 11:46:11 +020014#define MSR_BBL_CR_CTL3 0x11e
Thomas Jourdan1a692d82009-07-01 17:01:17 +000015
Nico Huber68d7c7a2012-10-02 11:46:11 +020016static void configure_c_states(const int quad)
Thomas Jourdan1a692d82009-07-01 17:01:17 +000017{
18 msr_t msr;
19
Nico Huber68d7c7a2012-10-02 11:46:11 +020020 /* Find pointer to CPU configuration. */
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110021 const struct device *lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
Nico Huber68d7c7a2012-10-02 11:46:11 +020022 const struct cpu_intel_model_1067x_config *const conf =
23 (lapic && lapic->chip_info) ? lapic->chip_info : NULL;
24
25 /* Is C5 requested and supported? */
26 const int c5 = conf && conf->c5 &&
27 (rdmsr(MSR_BBL_CR_CTL3).lo & (3 << 30)) &&
28 !(rdmsr(MSR_FSB_FREQ).lo & (1 << 31));
29 /* Is C6 requested and supported? */
30 const int c6 = conf && conf->c6 &&
31 ((cpuid_edx(5) >> (6 * 4)) & 0xf) && c5;
32
33 const int cst_range = (c6 ? 6 : (c5 ? 5 : 4)) - 2; /* zero means lvl2 */
34
Elyes HAOUAS4e6b7902018-10-02 08:44:47 +020035 msr = rdmsr(MSR_PKG_CST_CONFIG_CONTROL);
Thomas Jourdan1a692d82009-07-01 17:01:17 +000036 msr.lo &= ~(1 << 9); // Issue a single stop grant cycle upon stpclk
Nico Huber68d7c7a2012-10-02 11:46:11 +020037 msr.lo |= (1 << 8);
Lee Leahy26eeb0f2017-03-15 18:08:50 -070038 if (quad)
Nico Huber68d7c7a2012-10-02 11:46:11 +020039 msr.lo = (msr.lo & ~(7 << 0)) | (4 << 0);
Nico Huber68d7c7a2012-10-02 11:46:11 +020040 if (c5) {
41 msr.lo &= ~(1 << 13);
42 msr.lo &= ~(7 << 0);
43 msr.lo |= (1 << 3); /* Enable dynamic L2. */
44 msr.lo |= (1 << 14); /* Enable deeper sleep */
45 }
46 /* Next two fields seem to be mutually exclusive: */
47 msr.lo &= ~(7 << 4);
48 msr.lo |= (1 << 10); /* Enable IO MWAIT redirection. */
49 if (c6)
50 msr.lo |= (1 << 25);
Elyes HAOUAS4e6b7902018-10-02 08:44:47 +020051 wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);
Thomas Jourdan1a692d82009-07-01 17:01:17 +000052
53 /* Set Processor MWAIT IO BASE */
54 msr.hi = 0;
Lee Leahycdc50482017-03-15 18:26:18 -070055 msr.lo = ((PMB0_BASE + 4) & 0xffff) | (((PMB1_BASE + 9) & 0xffff)
56 << 16);
Patrick Georgi644e83b2013-02-09 15:35:30 +010057 wrmsr(MSR_PMG_IO_BASE_ADDR, msr);
Thomas Jourdan1a692d82009-07-01 17:01:17 +000058
59 /* Set IO Capture Address */
60 msr.hi = 0;
Nico Huber68d7c7a2012-10-02 11:46:11 +020061 msr.lo = ((PMB0_BASE + 4) & 0xffff) | ((cst_range & 0xffff) << 16);
Patrick Georgi644e83b2013-02-09 15:35:30 +010062 wrmsr(MSR_PMG_IO_CAPTURE_ADDR, msr);
Nico Huber68d7c7a2012-10-02 11:46:11 +020063
64 if (c5) {
65 msr = rdmsr(MSR_BBL_CR_CTL3);
66 msr.lo &= ~(7 << 25);
67 msr.lo |= (2 << 25);
68 msr.lo &= ~(3 << 30);
69 msr.lo |= (1 << 30);
70 wrmsr(MSR_BBL_CR_CTL3, msr);
71 }
Thomas Jourdan1a692d82009-07-01 17:01:17 +000072}
73
Nico Huber68d7c7a2012-10-02 11:46:11 +020074static void configure_p_states(const char stepping, const char cores)
Thomas Jourdan1a692d82009-07-01 17:01:17 +000075{
76 msr_t msr;
77
Nico Huber68d7c7a2012-10-02 11:46:11 +020078 /* Find pointer to CPU configuration. */
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110079 const struct device *lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
Nico Huber68d7c7a2012-10-02 11:46:11 +020080 struct cpu_intel_model_1067x_config *const conf =
81 (lapic && lapic->chip_info) ? lapic->chip_info : NULL;
82
83 msr = rdmsr(MSR_EXTENDED_CONFIG);
Patrick Georgif17c58b2014-08-09 20:48:12 +020084 /* Super LFM supported? */
85 if (conf && conf->slfm && (msr.lo & (1 << 27)))
Nico Huber68d7c7a2012-10-02 11:46:11 +020086 msr.lo |= (1 << 28); /* Enable Super LFM. */
87 wrmsr(MSR_EXTENDED_CONFIG, msr);
88
89 if (rdmsr(MSR_FSB_CLOCK_VCC).hi & (1 << (63 - 32))) {
90 /* Turbo supported? */
91 if ((stepping == 0xa) && (cores < 4)) {
92 msr = rdmsr(MSR_FSB_FREQ);
93 msr.lo |= (1 << 3); /* Enable hysteresis. */
94 wrmsr(MSR_FSB_FREQ, msr);
95 }
96 msr = rdmsr(IA32_PERF_CTL);
97 msr.hi &= ~(1 << (32 - 32)); /* Clear turbo disable. */
98 wrmsr(IA32_PERF_CTL, msr);
99 }
100
Elyes HAOUAS4e6b7902018-10-02 08:44:47 +0200101 msr = rdmsr(MSR_PKG_CST_CONFIG_CONTROL);
Nico Huber68d7c7a2012-10-02 11:46:11 +0200102 msr.lo &= ~(1 << 11); /* Enable hw coordination. */
103 msr.lo |= (1 << 15); /* Lock config until next reset. */
Elyes HAOUAS4e6b7902018-10-02 08:44:47 +0200104 wrmsr(MSR_PKG_CST_CONFIG_CONTROL, msr);
Nico Huber68d7c7a2012-10-02 11:46:11 +0200105}
106
107#define MSR_EMTTM_CR_TABLE(x) (0xa8 + (x))
108#define MSR_EMTTM_TABLE_NUM 6
109static void configure_emttm_tables(void)
110{
111 int i;
112 int num_states, pstate_idx;
113 msr_t msr;
114 sst_table_t pstates;
115
116 /* Gather p-state information. */
117 speedstep_gen_pstates(&pstates);
118
119 /* Never turbo mode or Super LFM. */
120 num_states = pstates.num_states;
121 if (pstates.states[0].is_turbo)
122 --num_states;
123 if (pstates.states[pstates.num_states - 1].is_slfm)
124 --num_states;
125 /* Repeat lowest p-state if we haven't enough states. */
126 const int num_lowest_pstate =
127 (num_states < MSR_EMTTM_TABLE_NUM)
128 ? (MSR_EMTTM_TABLE_NUM - num_states) + 1
129 : 1;
130 /* Start from the lowest entry but skip Super LFM. */
131 if (pstates.states[pstates.num_states - 1].is_slfm)
132 pstate_idx = pstates.num_states - 2;
133 else
134 pstate_idx = pstates.num_states - 1;
135 for (i = 0; i < MSR_EMTTM_TABLE_NUM; ++i) {
136 if (i >= num_lowest_pstate)
137 --pstate_idx;
138 const sst_state_t *const pstate = &pstates.states[pstate_idx];
139 printk(BIOS_DEBUG, "writing P-State %d: %d, %d, "
140 "%2d, 0x%02x, %d; encoded: 0x%04x\n",
141 pstate_idx, pstate->dynfsb, pstate->nonint,
142 pstate->ratio, pstate->vid, pstate->power,
143 SPEEDSTEP_ENCODE_STATE(*pstate));
144 msr.hi = 0;
145 msr.lo = SPEEDSTEP_ENCODE_STATE(pstates.states[pstate_idx]) &
146 /* Don't set half ratios. */
147 ~SPEEDSTEP_RATIO_NONINT;
148 wrmsr(MSR_EMTTM_CR_TABLE(i), msr);
149 }
150
151 msr = rdmsr(MSR_EMTTM_CR_TABLE(5));
152 msr.lo |= (1 << 31); /* lock tables */
153 wrmsr(MSR_EMTTM_CR_TABLE(5), msr);
154}
155
Michael Büchler70fea012020-09-09 01:04:27 +0200156#define IA32_PECI_CTL 0x5a0
157
Nico Huber68d7c7a2012-10-02 11:46:11 +0200158static void configure_misc(const int eist, const int tm2, const int emttm)
159{
160 msr_t msr;
161
162 const u32 sub_cstates = cpuid_edx(5);
163
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200164 msr = rdmsr(IA32_MISC_ENABLE);
Nico Huber68d7c7a2012-10-02 11:46:11 +0200165 msr.lo |= (1 << 3); /* TM1 enable */
166 if (tm2)
167 msr.lo |= (1 << 13); /* TM2 enable */
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000168 msr.lo |= (1 << 17); /* Bidirectional PROCHOT# */
Nico Huber68d7c7a2012-10-02 11:46:11 +0200169 msr.lo |= (1 << 18); /* MONITOR/MWAIT enable */
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000170
171 msr.lo |= (1 << 10); /* FERR# multiplexing */
172
Nico Huber68d7c7a2012-10-02 11:46:11 +0200173 if (eist)
174 msr.lo |= (1 << 16); /* Enhanced SpeedStep Enable */
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000175
176 /* Enable C2E */
Lee Leahy26eeb0f2017-03-15 18:08:50 -0700177 if (((sub_cstates >> (2 * 4)) & 0xf) >= 2)
Nico Huber68d7c7a2012-10-02 11:46:11 +0200178 msr.lo |= (1 << 26);
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000179
180 /* Enable C4E */
Nico Huber68d7c7a2012-10-02 11:46:11 +0200181 if (((sub_cstates >> (4 * 4)) & 0xf) >= 2) {
182 msr.hi |= (1 << (32 - 32)); // C4E
183 msr.hi |= (1 << (33 - 32)); // Hard C4E
184 }
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000185
Nico Huber68d7c7a2012-10-02 11:46:11 +0200186 /* Enable EMTTM */
187 if (emttm)
188 msr.hi |= (1 << (36 - 32));
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000189
Nico Huber68d7c7a2012-10-02 11:46:11 +0200190 /* Enable turbo mode */
191 if (rdmsr(MSR_FSB_CLOCK_VCC).hi & (1 << (63 - 32)))
192 msr.hi &= ~(1 << (38 - 32));
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000193
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200194 wrmsr(IA32_MISC_ENABLE, msr);
Nico Huber68d7c7a2012-10-02 11:46:11 +0200195
196 if (eist) {
197 msr.lo |= (1 << 20); /* Lock Enhanced SpeedStep Enable */
Elyes HAOUAS419bfbc2018-10-01 08:47:51 +0200198 wrmsr(IA32_MISC_ENABLE, msr);
Nico Huber68d7c7a2012-10-02 11:46:11 +0200199 }
Michael Büchler70fea012020-09-09 01:04:27 +0200200
201 /* Enable PECI
202 WARNING: due to Erratum AW67 described in Intel document #318733
203 the microcode must be updated before this MSR is written to. */
204 msr = rdmsr(IA32_PECI_CTL);
205 msr.lo |= 1;
206 wrmsr(IA32_PECI_CTL, msr);
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000207}
208
209#define PIC_SENS_CFG 0x1aa
Nico Huber68d7c7a2012-10-02 11:46:11 +0200210static void configure_pic_thermal_sensors(const int tm2, const int quad)
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000211{
212 msr_t msr;
213
214 msr = rdmsr(PIC_SENS_CFG);
215
Nico Huber68d7c7a2012-10-02 11:46:11 +0200216 if (quad)
217 msr.lo |= (1 << 31);
218 else
219 msr.lo &= ~(1 << 31);
220 if (tm2)
221 msr.lo |= (1 << 20); /* Enable TM1 if TM2 fails. */
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000222 msr.lo |= (1 << 21); // inter-core lock TM1
Nico Huber68d7c7a2012-10-02 11:46:11 +0200223 msr.lo |= (1 << 4); // Enable bypass filter /* What does it do? */
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000224
225 wrmsr(PIC_SENS_CFG, msr);
226}
227
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +1100228static void model_1067x_init(struct device *cpu)
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000229{
230 char processor_name[49];
231
Nico Huber68d7c7a2012-10-02 11:46:11 +0200232 /* Gather some information: */
233
234 const struct cpuid_result cpuid1 = cpuid(1);
235
236 /* Read stepping. */
237 const char stepping = cpuid1.eax & 0xf;
238 /* Read number of cores. */
239 const char cores = (cpuid1.ebx >> 16) & 0xf;
240 /* Is this a quad core? */
241 const char quad = cores > 2;
242 /* Is this even a multiprocessor? */
243 const char mp = cores > 1;
244
245 /* Enable EMTTM on uni- and on multi-processors if it's not disabled. */
246 const char emttm = !mp || !(rdmsr(MSR_EXTENDED_CONFIG).lo & 4);
247
248 /* Is enhanced speedstep supported? */
249 const char eist = (cpuid1.ecx & (1 << 7)) &&
250 !(rdmsr(IA32_PLATFORM_ID).lo & (1 << 17));
251 /* Test for TM2 only if EIST is available. */
252 const char tm2 = eist && (cpuid1.ecx & (1 << 8));
253
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000254 /* Print processor name */
255 fill_processor_name(processor_name);
Stefan Reinauerc02b4fc2010-03-22 11:42:32 +0000256 printk(BIOS_INFO, "CPU: %s.\n", processor_name);
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000257
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000258 /* Configure C States */
Nico Huber68d7c7a2012-10-02 11:46:11 +0200259 configure_c_states(quad);
260
261 /* Configure P States */
262 configure_p_states(stepping, cores);
263
264 /* EMTTM */
265 if (emttm)
266 configure_emttm_tables();
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000267
268 /* Configure Enhanced SpeedStep and Thermal Sensors */
Nico Huber68d7c7a2012-10-02 11:46:11 +0200269 configure_misc(eist, tm2, emttm);
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000270
271 /* PIC thermal sensor control */
Nico Huber68d7c7a2012-10-02 11:46:11 +0200272 configure_pic_thermal_sensors(tm2, quad);
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000273}
274
275static struct device_operations cpu_dev_ops = {
276 .init = model_1067x_init,
277};
278
Jonathan Neuschäfer8f06ce32017-11-20 01:56:44 +0100279static const struct cpu_device_id cpu_table[] = {
Angel Pons10857062020-08-05 23:40:00 +0200280 { X86_VENDOR_INTEL, 0x10676 },
Stefan Reinauerc104cb02010-10-18 00:21:39 +0000281 { X86_VENDOR_INTEL, 0x10677 },
282 { X86_VENDOR_INTEL, 0x1067A },
Thomas Jourdan1a692d82009-07-01 17:01:17 +0000283 { 0, 0 },
284};
285
286static const struct cpu_driver driver __cpu_driver = {
287 .ops = &cpu_dev_ops,
288 .id_table = cpu_table,
289};
290
Nico Huber68d7c7a2012-10-02 11:46:11 +0200291struct chip_operations cpu_intel_model_1067x_ops = {
292 CHIP_NAME("Intel Penryn CPU")
293};