FreeBSD/Linux Kernel Cross Reference
sys/i386/cpufreq/est.c
1 /*-
2 * Copyright (c) 2004 Colin Percival
3 * Copyright (c) 2005 Nate Lawson
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted providing that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: releng/6.0/sys/i386/cpufreq/est.c 144881 2005-04-10 19:57:47Z njl $");
30
31 #include <sys/param.h>
32 #include <sys/bus.h>
33 #include <sys/cpu.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/module.h>
37 #include <sys/smp.h>
38 #include <sys/systm.h>
39
40 #include "cpufreq_if.h"
41 #include <machine/md_var.h>
42
43 #include <contrib/dev/acpica/acpi.h>
44 #include <dev/acpica/acpivar.h>
45 #include "acpi_if.h"
46
47 /* Status/control registers (from the IA-32 System Programming Guide). */
48 #define MSR_PERF_STATUS 0x198
49 #define MSR_PERF_CTL 0x199
50
51 /* Register and bit for enabling SpeedStep. */
52 #define MSR_MISC_ENABLE 0x1a0
53 #define MSR_SS_ENABLE (1<<16)
54
55 /* Frequency and MSR control values. */
56 typedef struct {
57 uint16_t freq;
58 uint16_t volts;
59 uint16_t id16;
60 int power;
61 } freq_info;
62
63 /* Identifying characteristics of a processor and supported frequencies. */
64 typedef struct {
65 const char *vendor;
66 uint32_t id32;
67 uint32_t bus_clk;
68 freq_info *freqtab;
69 } cpu_info;
70
71 struct est_softc {
72 device_t dev;
73 int acpi_settings;
74 freq_info *freq_list;
75 };
76
77 /* Convert MHz and mV into IDs for passing to the MSR. */
78 #define ID16(MHz, mV, bus_clk) \
79 (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
80 #define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk) \
81 ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
82
83 /* Format for storing IDs in our table. */
84 #define FREQ_INFO(MHz, mV, bus_clk) \
85 { MHz, mV, ID16(MHz, mV, bus_clk), CPUFREQ_VAL_UNKNOWN }
86 #define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \
87 { GenuineIntel, ID32(zhi, vhi, zlo, vlo, bus_clk), bus_clk, tab }
88
89 const char GenuineIntel[] = "GenuineIntel";
90
91 /* Default bus clock value for Centrino processors. */
92 #define INTEL_BUS_CLK 100
93
94 /* XXX Update this if new CPUs have more settings. */
95 #define EST_MAX_SETTINGS 10
96 CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
97
98 /* Estimate in microseconds of latency for performing a transition. */
99 #define EST_TRANS_LAT 10
100
101 /*
102 * Frequency (MHz) and voltage (mV) settings. Data from the
103 * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
104 *
105 * Dothan processors have multiple VID#s with different settings for
106 * each VID#. Since we can't uniquely identify this info
107 * without undisclosed methods from Intel, we can't support newer
108 * processors with this table method. If ACPI Px states are supported,
109 * we get info from them.
110 */
111 static freq_info PM17_130[] = {
112 /* 130nm 1.70GHz Pentium M */
113 FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
114 FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
115 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
116 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
117 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
118 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
119 FREQ_INFO( 0, 0, 1),
120 };
121 static freq_info PM16_130[] = {
122 /* 130nm 1.60GHz Pentium M */
123 FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
124 FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
125 FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
126 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
127 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
128 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
129 FREQ_INFO( 0, 0, 1),
130 };
131 static freq_info PM15_130[] = {
132 /* 130nm 1.50GHz Pentium M */
133 FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
134 FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
135 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
136 FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
137 FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
138 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
139 FREQ_INFO( 0, 0, 1),
140 };
141 static freq_info PM14_130[] = {
142 /* 130nm 1.40GHz Pentium M */
143 FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
144 FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
145 FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
146 FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
147 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
148 FREQ_INFO( 0, 0, 1),
149 };
150 static freq_info PM13_130[] = {
151 /* 130nm 1.30GHz Pentium M */
152 FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
153 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
154 FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
155 FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
156 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
157 FREQ_INFO( 0, 0, 1),
158 };
159 static freq_info PM13_LV_130[] = {
160 /* 130nm 1.30GHz Low Voltage Pentium M */
161 FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
162 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
163 FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
164 FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
165 FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
166 FREQ_INFO( 800, 988, INTEL_BUS_CLK),
167 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
168 FREQ_INFO( 0, 0, 1),
169 };
170 static freq_info PM12_LV_130[] = {
171 /* 130 nm 1.20GHz Low Voltage Pentium M */
172 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
173 FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
174 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
175 FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
176 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
177 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
178 FREQ_INFO( 0, 0, 1),
179 };
180 static freq_info PM11_LV_130[] = {
181 /* 130 nm 1.10GHz Low Voltage Pentium M */
182 FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
183 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
184 FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
185 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
186 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
187 FREQ_INFO( 0, 0, 1),
188 };
189 static freq_info PM11_ULV_130[] = {
190 /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
191 FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
192 FREQ_INFO(1000, 988, INTEL_BUS_CLK),
193 FREQ_INFO( 900, 972, INTEL_BUS_CLK),
194 FREQ_INFO( 800, 956, INTEL_BUS_CLK),
195 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
196 FREQ_INFO( 0, 0, 1),
197 };
198 static freq_info PM10_ULV_130[] = {
199 /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
200 FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
201 FREQ_INFO( 900, 988, INTEL_BUS_CLK),
202 FREQ_INFO( 800, 972, INTEL_BUS_CLK),
203 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
204 FREQ_INFO( 0, 0, 1),
205 };
206
207 /*
208 * Data from "Intel Pentium M Processor on 90nm Process with
209 * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
210 */
211 static freq_info PM_765A_90[] = {
212 /* 90 nm 2.10GHz Pentium M, VID #A */
213 FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
214 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
215 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
216 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
217 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
218 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
219 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
220 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
221 FREQ_INFO( 0, 0, 1),
222 };
223 static freq_info PM_765B_90[] = {
224 /* 90 nm 2.10GHz Pentium M, VID #B */
225 FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
226 FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
227 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
228 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
229 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
230 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
231 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
232 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
233 FREQ_INFO( 0, 0, 1),
234 };
235 static freq_info PM_765C_90[] = {
236 /* 90 nm 2.10GHz Pentium M, VID #C */
237 FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
238 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
239 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
240 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
241 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
242 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
243 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
244 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
245 FREQ_INFO( 0, 0, 1),
246 };
247 static freq_info PM_765E_90[] = {
248 /* 90 nm 2.10GHz Pentium M, VID #E */
249 FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
250 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
251 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
252 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
253 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
254 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
255 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
256 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
257 FREQ_INFO( 0, 0, 1),
258 };
259 static freq_info PM_755A_90[] = {
260 /* 90 nm 2.00GHz Pentium M, VID #A */
261 FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
262 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
263 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
264 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
265 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
266 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
267 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
268 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
269 FREQ_INFO( 0, 0, 1),
270 };
271 static freq_info PM_755B_90[] = {
272 /* 90 nm 2.00GHz Pentium M, VID #B */
273 FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
274 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
275 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
276 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
277 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
278 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
279 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
280 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
281 FREQ_INFO( 0, 0, 1),
282 };
283 static freq_info PM_755C_90[] = {
284 /* 90 nm 2.00GHz Pentium M, VID #C */
285 FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
286 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
287 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
288 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
289 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
290 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
291 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
292 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
293 FREQ_INFO( 0, 0, 1),
294 };
295 static freq_info PM_755D_90[] = {
296 /* 90 nm 2.00GHz Pentium M, VID #D */
297 FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
298 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
299 FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
300 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
301 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
302 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
303 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
304 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
305 FREQ_INFO( 0, 0, 1),
306 };
307 static freq_info PM_745A_90[] = {
308 /* 90 nm 1.80GHz Pentium M, VID #A */
309 FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
310 FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
311 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
312 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
313 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
314 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
315 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
316 FREQ_INFO( 0, 0, 1),
317 };
318 static freq_info PM_745B_90[] = {
319 /* 90 nm 1.80GHz Pentium M, VID #B */
320 FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
321 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
322 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
323 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
324 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
325 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
326 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
327 FREQ_INFO( 0, 0, 1),
328 };
329 static freq_info PM_745C_90[] = {
330 /* 90 nm 1.80GHz Pentium M, VID #C */
331 FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
332 FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
333 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
334 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
335 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
336 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
337 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
338 FREQ_INFO( 0, 0, 1),
339 };
340 static freq_info PM_745D_90[] = {
341 /* 90 nm 1.80GHz Pentium M, VID #D */
342 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
343 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
344 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
345 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
346 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
347 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
348 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
349 FREQ_INFO( 0, 0, 1),
350 };
351 static freq_info PM_735A_90[] = {
352 /* 90 nm 1.70GHz Pentium M, VID #A */
353 FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
354 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
355 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
356 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
357 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
358 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
359 FREQ_INFO( 0, 0, 1),
360 };
361 static freq_info PM_735B_90[] = {
362 /* 90 nm 1.70GHz Pentium M, VID #B */
363 FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
364 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
365 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
366 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
367 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
368 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
369 FREQ_INFO( 0, 0, 1),
370 };
371 static freq_info PM_735C_90[] = {
372 /* 90 nm 1.70GHz Pentium M, VID #C */
373 FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
374 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
375 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
376 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
377 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
378 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
379 FREQ_INFO( 0, 0, 1),
380 };
381 static freq_info PM_735D_90[] = {
382 /* 90 nm 1.70GHz Pentium M, VID #D */
383 FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
384 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
385 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
386 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
387 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
388 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
389 FREQ_INFO( 0, 0, 1),
390 };
391 static freq_info PM_725A_90[] = {
392 /* 90 nm 1.60GHz Pentium M, VID #A */
393 FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
394 FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
395 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
396 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
397 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
398 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
399 FREQ_INFO( 0, 0, 1),
400 };
401 static freq_info PM_725B_90[] = {
402 /* 90 nm 1.60GHz Pentium M, VID #B */
403 FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
404 FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
405 FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
406 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
407 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
408 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
409 FREQ_INFO( 0, 0, 1),
410 };
411 static freq_info PM_725C_90[] = {
412 /* 90 nm 1.60GHz Pentium M, VID #C */
413 FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
414 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
415 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
416 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
417 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
418 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
419 FREQ_INFO( 0, 0, 1),
420 };
421 static freq_info PM_725D_90[] = {
422 /* 90 nm 1.60GHz Pentium M, VID #D */
423 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
424 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
425 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
426 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
427 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
428 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
429 FREQ_INFO( 0, 0, 1),
430 };
431 static freq_info PM_715A_90[] = {
432 /* 90 nm 1.50GHz Pentium M, VID #A */
433 FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
434 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
435 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
436 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
437 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
438 FREQ_INFO( 0, 0, 1),
439 };
440 static freq_info PM_715B_90[] = {
441 /* 90 nm 1.50GHz Pentium M, VID #B */
442 FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
443 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
444 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
445 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
446 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
447 FREQ_INFO( 0, 0, 1),
448 };
449 static freq_info PM_715C_90[] = {
450 /* 90 nm 1.50GHz Pentium M, VID #C */
451 FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
452 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
453 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
454 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
455 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
456 FREQ_INFO( 0, 0, 1),
457 };
458 static freq_info PM_715D_90[] = {
459 /* 90 nm 1.50GHz Pentium M, VID #D */
460 FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
461 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
462 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
463 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
464 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
465 FREQ_INFO( 0, 0, 1),
466 };
467 static freq_info PM_738_90[] = {
468 /* 90 nm 1.40GHz Low Voltage Pentium M */
469 FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
470 FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
471 FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
472 FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
473 FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
474 FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
475 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
476 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
477 FREQ_INFO( 0, 0, 1),
478 };
479 static freq_info PM_733_90[] = {
480 /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
481 FREQ_INFO(1100, 940, INTEL_BUS_CLK),
482 FREQ_INFO(1000, 924, INTEL_BUS_CLK),
483 FREQ_INFO( 900, 892, INTEL_BUS_CLK),
484 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
485 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
486 FREQ_INFO( 0, 0, 1),
487 };
488 static freq_info PM_723_90[] = {
489 /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
490 FREQ_INFO(1000, 940, INTEL_BUS_CLK),
491 FREQ_INFO( 900, 908, INTEL_BUS_CLK),
492 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
493 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
494 FREQ_INFO( 0, 0, 1),
495 };
496
497 static cpu_info ESTprocs[] = {
498 INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK),
499 INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK),
500 INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK),
501 INTEL(PM14_130, 1400, 1484, 600, 956, INTEL_BUS_CLK),
502 INTEL(PM13_130, 1300, 1388, 600, 956, INTEL_BUS_CLK),
503 INTEL(PM13_LV_130, 1300, 1180, 600, 956, INTEL_BUS_CLK),
504 INTEL(PM12_LV_130, 1200, 1180, 600, 956, INTEL_BUS_CLK),
505 INTEL(PM11_LV_130, 1100, 1180, 600, 956, INTEL_BUS_CLK),
506 INTEL(PM11_ULV_130, 1100, 1004, 600, 844, INTEL_BUS_CLK),
507 INTEL(PM10_ULV_130, 1000, 1004, 600, 844, INTEL_BUS_CLK),
508 INTEL(PM_765A_90, 2100, 1340, 600, 988, INTEL_BUS_CLK),
509 INTEL(PM_765B_90, 2100, 1324, 600, 988, INTEL_BUS_CLK),
510 INTEL(PM_765C_90, 2100, 1308, 600, 988, INTEL_BUS_CLK),
511 INTEL(PM_765E_90, 2100, 1356, 600, 988, INTEL_BUS_CLK),
512 INTEL(PM_755A_90, 2000, 1340, 600, 988, INTEL_BUS_CLK),
513 INTEL(PM_755B_90, 2000, 1324, 600, 988, INTEL_BUS_CLK),
514 INTEL(PM_755C_90, 2000, 1308, 600, 988, INTEL_BUS_CLK),
515 INTEL(PM_755D_90, 2000, 1276, 600, 988, INTEL_BUS_CLK),
516 INTEL(PM_745A_90, 1800, 1340, 600, 988, INTEL_BUS_CLK),
517 INTEL(PM_745B_90, 1800, 1324, 600, 988, INTEL_BUS_CLK),
518 INTEL(PM_745C_90, 1800, 1308, 600, 988, INTEL_BUS_CLK),
519 INTEL(PM_745D_90, 1800, 1276, 600, 988, INTEL_BUS_CLK),
520 INTEL(PM_735A_90, 1700, 1340, 600, 988, INTEL_BUS_CLK),
521 INTEL(PM_735B_90, 1700, 1324, 600, 988, INTEL_BUS_CLK),
522 INTEL(PM_735C_90, 1700, 1308, 600, 988, INTEL_BUS_CLK),
523 INTEL(PM_735D_90, 1700, 1276, 600, 988, INTEL_BUS_CLK),
524 INTEL(PM_725A_90, 1600, 1340, 600, 988, INTEL_BUS_CLK),
525 INTEL(PM_725B_90, 1600, 1324, 600, 988, INTEL_BUS_CLK),
526 INTEL(PM_725C_90, 1600, 1308, 600, 988, INTEL_BUS_CLK),
527 INTEL(PM_725D_90, 1600, 1276, 600, 988, INTEL_BUS_CLK),
528 INTEL(PM_715A_90, 1500, 1340, 600, 988, INTEL_BUS_CLK),
529 INTEL(PM_715B_90, 1500, 1324, 600, 988, INTEL_BUS_CLK),
530 INTEL(PM_715C_90, 1500, 1308, 600, 988, INTEL_BUS_CLK),
531 INTEL(PM_715D_90, 1500, 1276, 600, 988, INTEL_BUS_CLK),
532 INTEL(PM_738_90, 1400, 1116, 600, 988, INTEL_BUS_CLK),
533 INTEL(PM_733_90, 1100, 940, 600, 812, INTEL_BUS_CLK),
534 INTEL(PM_723_90, 1000, 940, 600, 812, INTEL_BUS_CLK),
535 { NULL, 0, 0, NULL },
536 };
537
538 static void est_identify(driver_t *driver, device_t parent);
539 static int est_features(driver_t *driver, u_int *features);
540 static int est_probe(device_t parent);
541 static int est_attach(device_t parent);
542 static int est_detach(device_t parent);
543 static int est_get_info(device_t dev);
544 static int est_acpi_info(device_t dev, freq_info **freqs);
545 static int est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk,
546 freq_info **freqs);
547 static freq_info *est_get_current(freq_info *freq_list);
548 static int est_settings(device_t dev, struct cf_setting *sets, int *count);
549 static int est_set(device_t dev, const struct cf_setting *set);
550 static int est_get(device_t dev, struct cf_setting *set);
551 static int est_type(device_t dev, int *type);
552
553 static device_method_t est_methods[] = {
554 /* Device interface */
555 DEVMETHOD(device_identify, est_identify),
556 DEVMETHOD(device_probe, est_probe),
557 DEVMETHOD(device_attach, est_attach),
558 DEVMETHOD(device_detach, est_detach),
559
560 /* cpufreq interface */
561 DEVMETHOD(cpufreq_drv_set, est_set),
562 DEVMETHOD(cpufreq_drv_get, est_get),
563 DEVMETHOD(cpufreq_drv_type, est_type),
564 DEVMETHOD(cpufreq_drv_settings, est_settings),
565
566 /* ACPI interface */
567 DEVMETHOD(acpi_get_features, est_features),
568
569 {0, 0}
570 };
571
572 static driver_t est_driver = {
573 "est",
574 est_methods,
575 sizeof(struct est_softc),
576 };
577
578 static devclass_t est_devclass;
579 DRIVER_MODULE(est, cpu, est_driver, est_devclass, 0, 0);
580
581 static int
582 est_features(driver_t *driver, u_int *features)
583 {
584
585 /* Notify the ACPI CPU that we support direct access to MSRs */
586 *features = ACPI_CAP_PERF_MSRS;
587 return (0);
588 }
589
590 static void
591 est_identify(driver_t *driver, device_t parent)
592 {
593 device_t child;
594 u_int p[4];
595
596 /* Make sure we're not being doubly invoked. */
597 if (device_find_child(parent, "est", -1) != NULL)
598 return;
599
600 /* Check that CPUID is supported and the vendor is Intel.*/
601 if (cpu_high == 0 || strcmp(cpu_vendor, GenuineIntel) != 0)
602 return;
603
604 /* Read capability bits and check if the CPU supports EST. */
605 do_cpuid(1, p);
606 if ((p[2] & 0x80) == 0)
607 return;
608
609 /*
610 * We add a child for each CPU since settings must be performed
611 * on each CPU in the SMP case.
612 */
613 child = BUS_ADD_CHILD(parent, 0, "est", -1);
614 if (child == NULL)
615 device_printf(parent, "add est child failed\n");
616 }
617
618 static int
619 est_probe(device_t dev)
620 {
621 device_t perf_dev;
622 uint64_t msr;
623 int error, type;
624
625 if (resource_disabled("est", 0))
626 return (ENXIO);
627
628 /*
629 * If the ACPI perf driver has attached and is not just offering
630 * info, let it manage things.
631 */
632 perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
633 if (perf_dev && device_is_attached(perf_dev)) {
634 error = CPUFREQ_DRV_TYPE(perf_dev, &type);
635 if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
636 return (ENXIO);
637 }
638
639 /* Attempt to enable SpeedStep if not currently enabled. */
640 msr = rdmsr(MSR_MISC_ENABLE);
641 if ((msr & MSR_SS_ENABLE) == 0) {
642 wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
643 if (bootverbose)
644 device_printf(dev, "enabling SpeedStep\n");
645
646 /* Check if the enable failed. */
647 msr = rdmsr(MSR_MISC_ENABLE);
648 if ((msr & MSR_SS_ENABLE) == 0) {
649 device_printf(dev, "failed to enable SpeedStep\n");
650 return (ENXIO);
651 }
652 }
653
654 device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
655 return (0);
656 }
657
658 static int
659 est_attach(device_t dev)
660 {
661 struct est_softc *sc;
662
663 sc = device_get_softc(dev);
664 sc->dev = dev;
665
666 /* Check CPU for supported settings. */
667 if (est_get_info(dev))
668 return (ENXIO);
669
670 cpufreq_register(dev);
671 return (0);
672 }
673
674 static int
675 est_detach(device_t dev)
676 {
677 struct est_softc *sc;
678
679 sc = device_get_softc(dev);
680 if (sc->acpi_settings)
681 free(sc->freq_list, M_DEVBUF);
682 return (ENXIO);
683 }
684
685 /*
686 * Probe for supported CPU settings. First, check our static table of
687 * settings. If no match, try using the ones offered by acpi_perf
688 * (i.e., _PSS). We use ACPI second because some systems (IBM R/T40
689 * series) export both legacy SMM IO-based access and direct MSR access
690 * but the direct access specifies invalid values for _PSS.
691 */
692 static int
693 est_get_info(device_t dev)
694 {
695 struct est_softc *sc;
696 uint64_t msr;
697 int error;
698
699 sc = device_get_softc(dev);
700 msr = rdmsr(MSR_PERF_STATUS);
701 error = est_table_info(dev, msr, INTEL_BUS_CLK, &sc->freq_list);
702 if (error)
703 error = est_acpi_info(dev, &sc->freq_list);
704
705 if (error) {
706 printf(
707 "est: CPU supports Enhanced Speedstep, but is not recognized.\n"
708 "est: Please update driver or contact the maintainer.\n"
709 "est: cpu_vendor %s, msr %0jx, bus_clk, %x\n",
710 cpu_vendor, msr, INTEL_BUS_CLK);
711 return (ENXIO);
712 }
713
714 return (0);
715 }
716
717 static int
718 est_acpi_info(device_t dev, freq_info **freqs)
719 {
720 struct est_softc *sc;
721 struct cf_setting *sets;
722 freq_info *table;
723 device_t perf_dev;
724 int count, error, i;
725
726 perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
727 if (perf_dev == NULL || !device_is_attached(perf_dev))
728 return (ENXIO);
729
730 /* Fetch settings from acpi_perf. */
731 sc = device_get_softc(dev);
732 table = NULL;
733 sets = malloc(MAX_SETTINGS * sizeof(*sets), M_TEMP, M_NOWAIT);
734 if (sets == NULL)
735 return (ENOMEM);
736 error = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
737 if (error)
738 goto out;
739
740 /* Parse settings into our local table format. */
741 table = malloc((count + 1) * sizeof(freq_info), M_DEVBUF, M_NOWAIT);
742 if (table == NULL) {
743 error = ENOMEM;
744 goto out;
745 }
746 for (i = 0; i < count; i++) {
747 /*
748 * TODO: Figure out validity checks for id16. Linux checks
749 * that the control and status values match.
750 */
751 table[i].freq = sets[i].freq;
752 table[i].volts = sets[i].volts;
753 table[i].id16 = sets[i].spec[0];
754 table[i].power = sets[i].power;
755 }
756
757 /* Mark end of table with a terminator. */
758 bzero(&table[i], sizeof(freq_info));
759
760 sc->acpi_settings = TRUE;
761 *freqs = table;
762 error = 0;
763
764 out:
765 if (sets)
766 free(sets, M_TEMP);
767 if (error && table)
768 free(table, M_DEVBUF);
769 return (error);
770 }
771
772 static int
773 est_table_info(device_t dev, uint64_t msr, uint32_t bus_clk, freq_info **freqs)
774 {
775 cpu_info *p;
776 uint32_t id;
777
778 /* Find a table which matches (vendor, id, bus_clk). */
779 id = msr >> 32;
780 for (p = ESTprocs; p->id32 != 0; p++) {
781 if (strcmp(p->vendor, cpu_vendor) == 0 && p->id32 == id &&
782 p->bus_clk == bus_clk)
783 break;
784 }
785 if (p->id32 == 0)
786 return (EOPNOTSUPP);
787
788 /* Make sure the current setpoint is valid. */
789 if (est_get_current(p->freqtab) == NULL) {
790 device_printf(dev, "current setting not found in table\n");
791 return (EOPNOTSUPP);
792 }
793
794 *freqs = p->freqtab;
795 return (0);
796 }
797
798 static freq_info *
799 est_get_current(freq_info *freq_list)
800 {
801 freq_info *f;
802 int i;
803 uint16_t id16;
804
805 /*
806 * Try a few times to get a valid value. Sometimes, if the CPU
807 * is in the middle of an asynchronous transition (i.e., P4TCC),
808 * we get a temporary invalid result.
809 */
810 for (i = 0; i < 5; i++) {
811 id16 = rdmsr(MSR_PERF_STATUS) & 0xffff;
812 for (f = freq_list; f->id16 != 0; f++) {
813 if (f->id16 == id16)
814 return (f);
815 }
816 DELAY(100);
817 }
818 return (NULL);
819 }
820
821 static int
822 est_settings(device_t dev, struct cf_setting *sets, int *count)
823 {
824 struct est_softc *sc;
825 freq_info *f;
826 int i;
827
828 sc = device_get_softc(dev);
829 if (*count < EST_MAX_SETTINGS)
830 return (E2BIG);
831
832 i = 0;
833 for (f = sc->freq_list; f->freq != 0; f++, i++) {
834 sets[i].freq = f->freq;
835 sets[i].volts = f->volts;
836 sets[i].power = f->power;
837 sets[i].lat = EST_TRANS_LAT;
838 sets[i].dev = dev;
839 }
840 *count = i;
841
842 return (0);
843 }
844
845 static int
846 est_set(device_t dev, const struct cf_setting *set)
847 {
848 struct est_softc *sc;
849 freq_info *f;
850 uint64_t msr;
851
852 /* Find the setting matching the requested one. */
853 sc = device_get_softc(dev);
854 for (f = sc->freq_list; f->freq != 0; f++) {
855 if (f->freq == set->freq)
856 break;
857 }
858 if (f->freq == 0)
859 return (EINVAL);
860
861 /* Read the current register, mask out the old, set the new id. */
862 msr = rdmsr(MSR_PERF_CTL);
863 msr = (msr & ~0xffff) | f->id16;
864 wrmsr(MSR_PERF_CTL, msr);
865
866 /* Wait a short while for the new setting. XXX Is this necessary? */
867 DELAY(EST_TRANS_LAT);
868
869 return (0);
870 }
871
872 static int
873 est_get(device_t dev, struct cf_setting *set)
874 {
875 struct est_softc *sc;
876 freq_info *f;
877
878 sc = device_get_softc(dev);
879 f = est_get_current(sc->freq_list);
880 if (f == NULL)
881 return (ENXIO);
882
883 set->freq = f->freq;
884 set->volts = f->volts;
885 set->power = f->power;
886 set->lat = EST_TRANS_LAT;
887 set->dev = dev;
888 return (0);
889 }
890
891 static int
892 est_type(device_t dev, int *type)
893 {
894
895 if (type == NULL)
896 return (EINVAL);
897
898 *type = CPUFREQ_TYPE_ABSOLUTE;
899 return (0);
900 }
Cache object: 0893ad7dfd3c3a81fe064b66c401c3b7
|