Deleted Added
full compact
est.c (142140) est.c (142203)
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>
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: head/sys/i386/cpufreq/est.c 142140 2005-02-20 20:27:59Z njl $");
29__FBSDID("$FreeBSD: head/sys/i386/cpufreq/est.c 142203 2005-02-22 06:31:45Z 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/module.h>
36#include <sys/smp.h>
37#include <sys/systm.h>
38
39#include "cpufreq_if.h"
40#include <machine/md_var.h>
41
42/* Status/control registers (from the IA-32 System Programming Guide). */
43#define MSR_PERF_STATUS 0x198
44#define MSR_PERF_CTL 0x199
45
46/* Register and bit for enabling SpeedStep. */
47#define MSR_MISC_ENABLE 0x1a0
48#define MSR_SS_ENABLE (1<<16)
49
50/* Frequency and MSR control values. */
51typedef struct {
52 uint16_t freq;
53 uint16_t volts;
54 uint16_t id16;
55} freq_info;
56
57/* Identifying characteristics of a processor and supported frequencies. */
58typedef struct {
59 const char *vendor;
60 uint32_t id32;
61 uint32_t bus_clk;
62 const freq_info *freqtab;
63} cpu_info;
64
65struct est_softc {
66 device_t dev;
67 const freq_info *freq_list;
68};
69
70/* Convert MHz and mV into IDs for passing to the MSR. */
71#define ID16(MHz, mV, bus_clk) \
72 (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
73#define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk) \
74 ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
75
76/* Format for storing IDs in our table. */
77#define FREQ_INFO(MHz, mV, bus_clk) \
78 { MHz, mV, ID16(MHz, mV, bus_clk) }
79#define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \
80 { GenuineIntel, ID32(zhi, vhi, zlo, vlo, bus_clk), bus_clk, tab }
81
82const char GenuineIntel[] = "GenuineIntel";
83
84/* Default bus clock value for Centrino processors. */
85#define INTEL_BUS_CLK 100
86
87/* XXX Update this if new CPUs have more settings. */
88#define EST_MAX_SETTINGS 10
89CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
90
91/* Estimate in microseconds of latency for performing a transition. */
92#define EST_TRANS_LAT 10
93
94/*
95 * Frequency (MHz) and voltage (mV) settings. Data from the
96 * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
97 *
98 * XXX New Dothan processors have multiple VID# with different
99 * settings for each VID#. Since we can't uniquely identify this info
100 * without undisclosed methods from Intel, we can't support newer
101 * processors with this table method. If ACPI Px states are supported,
102 * we can get info from them.
103 */
104const freq_info PM17_130[] = {
105 /* 130nm 1.70GHz Pentium M */
106 FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
107 FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
108 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
109 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
110 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
111 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
112 FREQ_INFO( 0, 0, 1),
113};
114const freq_info PM16_130[] = {
115 /* 130nm 1.60GHz Pentium M */
116 FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
117 FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
118 FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
119 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
120 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
121 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
122 FREQ_INFO( 0, 0, 1),
123};
124const freq_info PM15_130[] = {
125 /* 130nm 1.50GHz Pentium M */
126 FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
127 FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
128 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
129 FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
130 FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
131 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
132 FREQ_INFO( 0, 0, 1),
133};
134const freq_info PM14_130[] = {
135 /* 130nm 1.40GHz Pentium M */
136 FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
137 FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
138 FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
139 FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
140 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
141 FREQ_INFO( 0, 0, 1),
142};
143const freq_info PM13_130[] = {
144 /* 130nm 1.30GHz Pentium M */
145 FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
146 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
147 FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
148 FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
149 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
150 FREQ_INFO( 0, 0, 1),
151};
152const freq_info PM13_LV_130[] = {
153 /* 130nm 1.30GHz Low Voltage Pentium M */
154 FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
155 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
156 FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
157 FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
158 FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
159 FREQ_INFO( 800, 988, INTEL_BUS_CLK),
160 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
161 FREQ_INFO( 0, 0, 1),
162};
163const freq_info PM12_LV_130[] = {
164 /* 130 nm 1.20GHz Low Voltage Pentium M */
165 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
166 FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
167 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
168 FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
169 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
170 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
171 FREQ_INFO( 0, 0, 1),
172};
173const freq_info PM11_LV_130[] = {
174 /* 130 nm 1.10GHz Low Voltage Pentium M */
175 FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
176 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
177 FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
178 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
179 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
180 FREQ_INFO( 0, 0, 1),
181};
182const freq_info PM11_ULV_130[] = {
183 /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
184 FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
185 FREQ_INFO(1000, 988, INTEL_BUS_CLK),
186 FREQ_INFO( 900, 972, INTEL_BUS_CLK),
187 FREQ_INFO( 800, 956, INTEL_BUS_CLK),
188 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
189 FREQ_INFO( 0, 0, 1),
190};
191const freq_info PM10_ULV_130[] = {
192 /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
193 FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
194 FREQ_INFO( 900, 988, INTEL_BUS_CLK),
195 FREQ_INFO( 800, 972, INTEL_BUS_CLK),
196 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
197 FREQ_INFO( 0, 0, 1),
198};
199
200/*
201 * Data from "Intel Pentium M Processor on 90nm Process with
202 * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
203 */
204const freq_info PM_765A_90[] = {
205 /* 90 nm 2.10GHz Pentium M, VID #A */
206 FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
207 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
208 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
209 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
210 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
211 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
212 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
213 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
214 FREQ_INFO( 0, 0, 1),
215};
216const freq_info PM_765B_90[] = {
217 /* 90 nm 2.10GHz Pentium M, VID #B */
218 FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
219 FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
220 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
221 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
222 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
223 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
224 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
225 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
226 FREQ_INFO( 0, 0, 1),
227};
228const freq_info PM_765C_90[] = {
229 /* 90 nm 2.10GHz Pentium M, VID #C */
230 FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
231 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
232 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
233 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
234 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
235 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
236 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
237 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
238 FREQ_INFO( 0, 0, 1),
239};
240const freq_info PM_765E_90[] = {
241 /* 90 nm 2.10GHz Pentium M, VID #E */
242 FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
243 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
244 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
245 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
246 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
247 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
248 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
249 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
250 FREQ_INFO( 0, 0, 1),
251};
252const freq_info PM_755A_90[] = {
253 /* 90 nm 2.00GHz Pentium M, VID #A */
254 FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
255 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
256 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
257 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
258 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
259 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
260 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
261 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
262 FREQ_INFO( 0, 0, 1),
263};
264const freq_info PM_755B_90[] = {
265 /* 90 nm 2.00GHz Pentium M, VID #B */
266 FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
267 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
268 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
269 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
270 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
271 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
272 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
273 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
274 FREQ_INFO( 0, 0, 1),
275};
276const freq_info PM_755C_90[] = {
277 /* 90 nm 2.00GHz Pentium M, VID #C */
278 FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
279 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
280 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
281 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
282 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
283 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
284 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
285 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
286 FREQ_INFO( 0, 0, 1),
287};
288const freq_info PM_755D_90[] = {
289 /* 90 nm 2.00GHz Pentium M, VID #D */
290 FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
291 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
292 FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
293 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
294 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
295 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
296 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
297 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
298 FREQ_INFO( 0, 0, 1),
299};
300const freq_info PM_745A_90[] = {
301 /* 90 nm 1.80GHz Pentium M, VID #A */
302 FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
303 FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
304 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
305 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
306 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
307 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
308 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
309 FREQ_INFO( 0, 0, 1),
310};
311const freq_info PM_745B_90[] = {
312 /* 90 nm 1.80GHz Pentium M, VID #B */
313 FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
314 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
315 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
316 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
317 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
318 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
319 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
320 FREQ_INFO( 0, 0, 1),
321};
322const freq_info PM_745C_90[] = {
323 /* 90 nm 1.80GHz Pentium M, VID #C */
324 FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
325 FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
326 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
327 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
328 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
329 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
330 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
331 FREQ_INFO( 0, 0, 1),
332};
333const freq_info PM_745D_90[] = {
334 /* 90 nm 1.80GHz Pentium M, VID #D */
335 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
336 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
337 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
338 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
339 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
340 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
341 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
342 FREQ_INFO( 0, 0, 1),
343};
344const freq_info PM_735A_90[] = {
345 /* 90 nm 1.70GHz Pentium M, VID #A */
346 FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
347 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
348 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
349 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
350 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
351 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
352 FREQ_INFO( 0, 0, 1),
353};
354const freq_info PM_735B_90[] = {
355 /* 90 nm 1.70GHz Pentium M, VID #B */
356 FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
357 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
358 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
359 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
360 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
361 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
362 FREQ_INFO( 0, 0, 1),
363};
364const freq_info PM_735C_90[] = {
365 /* 90 nm 1.70GHz Pentium M, VID #C */
366 FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
367 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
368 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
369 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
370 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
371 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
372 FREQ_INFO( 0, 0, 1),
373};
374const freq_info PM_735D_90[] = {
375 /* 90 nm 1.70GHz Pentium M, VID #D */
376 FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
377 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
378 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
379 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
380 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
381 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
382 FREQ_INFO( 0, 0, 1),
383};
384const freq_info PM_725A_90[] = {
385 /* 90 nm 1.60GHz Pentium M, VID #A */
386 FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
387 FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
388 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
389 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
390 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
391 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
392 FREQ_INFO( 0, 0, 1),
393};
394const freq_info PM_725B_90[] = {
395 /* 90 nm 1.60GHz Pentium M, VID #B */
396 FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
397 FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
398 FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
399 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
400 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
401 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
402 FREQ_INFO( 0, 0, 1),
403};
404const freq_info PM_725C_90[] = {
405 /* 90 nm 1.60GHz Pentium M, VID #C */
406 FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
407 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
408 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
409 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
410 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
411 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
412 FREQ_INFO( 0, 0, 1),
413};
414const freq_info PM_725D_90[] = {
415 /* 90 nm 1.60GHz Pentium M, VID #D */
416 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
417 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
418 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
419 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
420 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
421 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
422 FREQ_INFO( 0, 0, 1),
423};
424const freq_info PM_715A_90[] = {
425 /* 90 nm 1.50GHz Pentium M, VID #A */
426 FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
427 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
428 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
429 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
430 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
431 FREQ_INFO( 0, 0, 1),
432};
433const freq_info PM_715B_90[] = {
434 /* 90 nm 1.50GHz Pentium M, VID #B */
435 FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
436 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
437 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
438 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
439 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
440 FREQ_INFO( 0, 0, 1),
441};
442const freq_info PM_715C_90[] = {
443 /* 90 nm 1.50GHz Pentium M, VID #C */
444 FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
445 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
446 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
447 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
448 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
449 FREQ_INFO( 0, 0, 1),
450};
451const freq_info PM_715D_90[] = {
452 /* 90 nm 1.50GHz Pentium M, VID #D */
453 FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
454 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
455 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
456 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
457 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
458 FREQ_INFO( 0, 0, 1),
459};
460const freq_info PM_738_90[] = {
461 /* 90 nm 1.40GHz Low Voltage Pentium M */
462 FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
463 FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
464 FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
465 FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
466 FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
467 FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
468 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
469 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
470 FREQ_INFO( 0, 0, 1),
471};
472const freq_info PM_733_90[] = {
473 /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
474 FREQ_INFO(1100, 940, INTEL_BUS_CLK),
475 FREQ_INFO(1000, 924, INTEL_BUS_CLK),
476 FREQ_INFO( 900, 892, INTEL_BUS_CLK),
477 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
478 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
479 FREQ_INFO( 0, 0, 1),
480};
481const freq_info PM_723_90[] = {
482 /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
483 FREQ_INFO(1000, 940, INTEL_BUS_CLK),
484 FREQ_INFO( 900, 908, INTEL_BUS_CLK),
485 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
486 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
487 FREQ_INFO( 0, 0, 1),
488};
489
490const cpu_info ESTprocs[] = {
491 INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK),
492 INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK),
493 INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK),
494 INTEL(PM14_130, 1400, 1484, 600, 956, INTEL_BUS_CLK),
495 INTEL(PM13_130, 1300, 1388, 600, 956, INTEL_BUS_CLK),
496 INTEL(PM13_LV_130, 1300, 1180, 600, 956, INTEL_BUS_CLK),
497 INTEL(PM12_LV_130, 1200, 1180, 600, 956, INTEL_BUS_CLK),
498 INTEL(PM11_LV_130, 1100, 1180, 600, 956, INTEL_BUS_CLK),
499 INTEL(PM11_ULV_130, 1100, 1004, 600, 844, INTEL_BUS_CLK),
500 INTEL(PM10_ULV_130, 1000, 1004, 600, 844, INTEL_BUS_CLK),
501 INTEL(PM_765A_90, 2100, 1340, 600, 988, INTEL_BUS_CLK),
502 INTEL(PM_765B_90, 2100, 1324, 600, 988, INTEL_BUS_CLK),
503 INTEL(PM_765C_90, 2100, 1308, 600, 988, INTEL_BUS_CLK),
504 INTEL(PM_765E_90, 2100, 1356, 600, 988, INTEL_BUS_CLK),
505 INTEL(PM_755A_90, 2000, 1340, 600, 988, INTEL_BUS_CLK),
506 INTEL(PM_755B_90, 2000, 1324, 600, 988, INTEL_BUS_CLK),
507 INTEL(PM_755C_90, 2000, 1308, 600, 988, INTEL_BUS_CLK),
508 INTEL(PM_755D_90, 2000, 1276, 600, 988, INTEL_BUS_CLK),
509 INTEL(PM_745A_90, 1800, 1340, 600, 988, INTEL_BUS_CLK),
510 INTEL(PM_745B_90, 1800, 1324, 600, 988, INTEL_BUS_CLK),
511 INTEL(PM_745C_90, 1800, 1308, 600, 988, INTEL_BUS_CLK),
512 INTEL(PM_745D_90, 1800, 1276, 600, 988, INTEL_BUS_CLK),
513 INTEL(PM_735A_90, 1700, 1340, 600, 988, INTEL_BUS_CLK),
514 INTEL(PM_735B_90, 1700, 1324, 600, 988, INTEL_BUS_CLK),
515 INTEL(PM_735C_90, 1700, 1308, 600, 988, INTEL_BUS_CLK),
516 INTEL(PM_735D_90, 1700, 1276, 600, 988, INTEL_BUS_CLK),
517 INTEL(PM_725A_90, 1600, 1340, 600, 988, INTEL_BUS_CLK),
518 INTEL(PM_725B_90, 1600, 1324, 600, 988, INTEL_BUS_CLK),
519 INTEL(PM_725C_90, 1600, 1308, 600, 988, INTEL_BUS_CLK),
520 INTEL(PM_725D_90, 1600, 1276, 600, 988, INTEL_BUS_CLK),
521 INTEL(PM_715A_90, 1500, 1340, 600, 988, INTEL_BUS_CLK),
522 INTEL(PM_715B_90, 1500, 1324, 600, 988, INTEL_BUS_CLK),
523 INTEL(PM_715C_90, 1500, 1308, 600, 988, INTEL_BUS_CLK),
524 INTEL(PM_715D_90, 1500, 1276, 600, 988, INTEL_BUS_CLK),
525 INTEL(PM_738_90, 1400, 1116, 600, 988, INTEL_BUS_CLK),
526 INTEL(PM_733_90, 1100, 940, 600, 812, INTEL_BUS_CLK),
527 INTEL(PM_723_90, 1000, 940, 600, 812, INTEL_BUS_CLK),
528 { NULL, 0, 0, NULL },
529};
530
531static void est_identify(driver_t *driver, device_t parent);
532static int est_probe(device_t parent);
533static int est_attach(device_t parent);
534static int est_detach(device_t parent);
535static int est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
536 const freq_info **freqs);
537static const freq_info *est_get_current(const freq_info *freq_list);
538static int est_settings(device_t dev, struct cf_setting *sets, int *count);
539static int est_set(device_t dev, const struct cf_setting *set);
540static int est_get(device_t dev, struct cf_setting *set);
541static int est_type(device_t dev, int *type);
542
543static device_method_t est_methods[] = {
544 /* Device interface */
545 DEVMETHOD(device_identify, est_identify),
546 DEVMETHOD(device_probe, est_probe),
547 DEVMETHOD(device_attach, est_attach),
548 DEVMETHOD(device_detach, est_detach),
549
550 /* cpufreq interface */
551 DEVMETHOD(cpufreq_drv_set, est_set),
552 DEVMETHOD(cpufreq_drv_get, est_get),
553 DEVMETHOD(cpufreq_drv_type, est_type),
554 DEVMETHOD(cpufreq_drv_settings, est_settings),
555 {0, 0}
556};
557
558static driver_t est_driver = {
559 "est",
560 est_methods,
561 sizeof(struct est_softc),
562};
563
564static devclass_t est_devclass;
565DRIVER_MODULE(est, cpu, est_driver, est_devclass, 0, 0);
566
567static void
568est_identify(driver_t *driver, device_t parent)
569{
570 u_int p[4];
571
572 /* Make sure we're not being doubly invoked. */
573 if (device_find_child(parent, "est", -1) != NULL)
574 return;
575
576 /* Check that CPUID is supported and the vendor is Intel.*/
577 if (cpu_high == 0 || strcmp(cpu_vendor, GenuineIntel) != 0)
578 return;
579
580 /* Read capability bits and check if the CPU supports EST. */
581 do_cpuid(1, p);
582 if ((p[2] & 0x80) == 0)
583 return;
584
585 if (BUS_ADD_CHILD(parent, 0, "est", -1) == NULL)
586 device_printf(parent, "add est child failed\n");
587}
588
589static int
590est_probe(device_t dev)
591{
592 const freq_info *f;
593 device_t perf_dev;
594 uint64_t msr;
595 int error, type;
30
31#include <sys/param.h>
32#include <sys/bus.h>
33#include <sys/cpu.h>
34#include <sys/kernel.h>
35#include <sys/module.h>
36#include <sys/smp.h>
37#include <sys/systm.h>
38
39#include "cpufreq_if.h"
40#include <machine/md_var.h>
41
42/* Status/control registers (from the IA-32 System Programming Guide). */
43#define MSR_PERF_STATUS 0x198
44#define MSR_PERF_CTL 0x199
45
46/* Register and bit for enabling SpeedStep. */
47#define MSR_MISC_ENABLE 0x1a0
48#define MSR_SS_ENABLE (1<<16)
49
50/* Frequency and MSR control values. */
51typedef struct {
52 uint16_t freq;
53 uint16_t volts;
54 uint16_t id16;
55} freq_info;
56
57/* Identifying characteristics of a processor and supported frequencies. */
58typedef struct {
59 const char *vendor;
60 uint32_t id32;
61 uint32_t bus_clk;
62 const freq_info *freqtab;
63} cpu_info;
64
65struct est_softc {
66 device_t dev;
67 const freq_info *freq_list;
68};
69
70/* Convert MHz and mV into IDs for passing to the MSR. */
71#define ID16(MHz, mV, bus_clk) \
72 (((MHz / bus_clk) << 8) | ((mV ? mV - 700 : 0) >> 4))
73#define ID32(MHz_hi, mV_hi, MHz_lo, mV_lo, bus_clk) \
74 ((ID16(MHz_lo, mV_lo, bus_clk) << 16) | (ID16(MHz_hi, mV_hi, bus_clk)))
75
76/* Format for storing IDs in our table. */
77#define FREQ_INFO(MHz, mV, bus_clk) \
78 { MHz, mV, ID16(MHz, mV, bus_clk) }
79#define INTEL(tab, zhi, vhi, zlo, vlo, bus_clk) \
80 { GenuineIntel, ID32(zhi, vhi, zlo, vlo, bus_clk), bus_clk, tab }
81
82const char GenuineIntel[] = "GenuineIntel";
83
84/* Default bus clock value for Centrino processors. */
85#define INTEL_BUS_CLK 100
86
87/* XXX Update this if new CPUs have more settings. */
88#define EST_MAX_SETTINGS 10
89CTASSERT(EST_MAX_SETTINGS <= MAX_SETTINGS);
90
91/* Estimate in microseconds of latency for performing a transition. */
92#define EST_TRANS_LAT 10
93
94/*
95 * Frequency (MHz) and voltage (mV) settings. Data from the
96 * Intel Pentium M Processor Datasheet (Order Number 252612), Table 5.
97 *
98 * XXX New Dothan processors have multiple VID# with different
99 * settings for each VID#. Since we can't uniquely identify this info
100 * without undisclosed methods from Intel, we can't support newer
101 * processors with this table method. If ACPI Px states are supported,
102 * we can get info from them.
103 */
104const freq_info PM17_130[] = {
105 /* 130nm 1.70GHz Pentium M */
106 FREQ_INFO(1700, 1484, INTEL_BUS_CLK),
107 FREQ_INFO(1400, 1308, INTEL_BUS_CLK),
108 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
109 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
110 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
111 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
112 FREQ_INFO( 0, 0, 1),
113};
114const freq_info PM16_130[] = {
115 /* 130nm 1.60GHz Pentium M */
116 FREQ_INFO(1600, 1484, INTEL_BUS_CLK),
117 FREQ_INFO(1400, 1420, INTEL_BUS_CLK),
118 FREQ_INFO(1200, 1276, INTEL_BUS_CLK),
119 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
120 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
121 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
122 FREQ_INFO( 0, 0, 1),
123};
124const freq_info PM15_130[] = {
125 /* 130nm 1.50GHz Pentium M */
126 FREQ_INFO(1500, 1484, INTEL_BUS_CLK),
127 FREQ_INFO(1400, 1452, INTEL_BUS_CLK),
128 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
129 FREQ_INFO(1000, 1228, INTEL_BUS_CLK),
130 FREQ_INFO( 800, 1116, INTEL_BUS_CLK),
131 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
132 FREQ_INFO( 0, 0, 1),
133};
134const freq_info PM14_130[] = {
135 /* 130nm 1.40GHz Pentium M */
136 FREQ_INFO(1400, 1484, INTEL_BUS_CLK),
137 FREQ_INFO(1200, 1436, INTEL_BUS_CLK),
138 FREQ_INFO(1000, 1308, INTEL_BUS_CLK),
139 FREQ_INFO( 800, 1180, INTEL_BUS_CLK),
140 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
141 FREQ_INFO( 0, 0, 1),
142};
143const freq_info PM13_130[] = {
144 /* 130nm 1.30GHz Pentium M */
145 FREQ_INFO(1300, 1388, INTEL_BUS_CLK),
146 FREQ_INFO(1200, 1356, INTEL_BUS_CLK),
147 FREQ_INFO(1000, 1292, INTEL_BUS_CLK),
148 FREQ_INFO( 800, 1260, INTEL_BUS_CLK),
149 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
150 FREQ_INFO( 0, 0, 1),
151};
152const freq_info PM13_LV_130[] = {
153 /* 130nm 1.30GHz Low Voltage Pentium M */
154 FREQ_INFO(1300, 1180, INTEL_BUS_CLK),
155 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
156 FREQ_INFO(1100, 1100, INTEL_BUS_CLK),
157 FREQ_INFO(1000, 1020, INTEL_BUS_CLK),
158 FREQ_INFO( 900, 1004, INTEL_BUS_CLK),
159 FREQ_INFO( 800, 988, INTEL_BUS_CLK),
160 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
161 FREQ_INFO( 0, 0, 1),
162};
163const freq_info PM12_LV_130[] = {
164 /* 130 nm 1.20GHz Low Voltage Pentium M */
165 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
166 FREQ_INFO(1100, 1164, INTEL_BUS_CLK),
167 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
168 FREQ_INFO( 900, 1020, INTEL_BUS_CLK),
169 FREQ_INFO( 800, 1004, INTEL_BUS_CLK),
170 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
171 FREQ_INFO( 0, 0, 1),
172};
173const freq_info PM11_LV_130[] = {
174 /* 130 nm 1.10GHz Low Voltage Pentium M */
175 FREQ_INFO(1100, 1180, INTEL_BUS_CLK),
176 FREQ_INFO(1000, 1164, INTEL_BUS_CLK),
177 FREQ_INFO( 900, 1100, INTEL_BUS_CLK),
178 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
179 FREQ_INFO( 600, 956, INTEL_BUS_CLK),
180 FREQ_INFO( 0, 0, 1),
181};
182const freq_info PM11_ULV_130[] = {
183 /* 130 nm 1.10GHz Ultra Low Voltage Pentium M */
184 FREQ_INFO(1100, 1004, INTEL_BUS_CLK),
185 FREQ_INFO(1000, 988, INTEL_BUS_CLK),
186 FREQ_INFO( 900, 972, INTEL_BUS_CLK),
187 FREQ_INFO( 800, 956, INTEL_BUS_CLK),
188 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
189 FREQ_INFO( 0, 0, 1),
190};
191const freq_info PM10_ULV_130[] = {
192 /* 130 nm 1.00GHz Ultra Low Voltage Pentium M */
193 FREQ_INFO(1000, 1004, INTEL_BUS_CLK),
194 FREQ_INFO( 900, 988, INTEL_BUS_CLK),
195 FREQ_INFO( 800, 972, INTEL_BUS_CLK),
196 FREQ_INFO( 600, 844, INTEL_BUS_CLK),
197 FREQ_INFO( 0, 0, 1),
198};
199
200/*
201 * Data from "Intel Pentium M Processor on 90nm Process with
202 * 2-MB L2 Cache Datasheet", Order Number 302189, Table 5.
203 */
204const freq_info PM_765A_90[] = {
205 /* 90 nm 2.10GHz Pentium M, VID #A */
206 FREQ_INFO(2100, 1340, INTEL_BUS_CLK),
207 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
208 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
209 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
210 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
211 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
212 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
213 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
214 FREQ_INFO( 0, 0, 1),
215};
216const freq_info PM_765B_90[] = {
217 /* 90 nm 2.10GHz Pentium M, VID #B */
218 FREQ_INFO(2100, 1324, INTEL_BUS_CLK),
219 FREQ_INFO(1800, 1260, INTEL_BUS_CLK),
220 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
221 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
222 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
223 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
224 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
225 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
226 FREQ_INFO( 0, 0, 1),
227};
228const freq_info PM_765C_90[] = {
229 /* 90 nm 2.10GHz Pentium M, VID #C */
230 FREQ_INFO(2100, 1308, INTEL_BUS_CLK),
231 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
232 FREQ_INFO(1600, 1212, INTEL_BUS_CLK),
233 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
234 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
235 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
236 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
237 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
238 FREQ_INFO( 0, 0, 1),
239};
240const freq_info PM_765E_90[] = {
241 /* 90 nm 2.10GHz Pentium M, VID #E */
242 FREQ_INFO(2100, 1356, INTEL_BUS_CLK),
243 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
244 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
245 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
246 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
247 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
248 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
249 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
250 FREQ_INFO( 0, 0, 1),
251};
252const freq_info PM_755A_90[] = {
253 /* 90 nm 2.00GHz Pentium M, VID #A */
254 FREQ_INFO(2000, 1340, INTEL_BUS_CLK),
255 FREQ_INFO(1800, 1292, INTEL_BUS_CLK),
256 FREQ_INFO(1600, 1244, INTEL_BUS_CLK),
257 FREQ_INFO(1400, 1196, INTEL_BUS_CLK),
258 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
259 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
260 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
261 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
262 FREQ_INFO( 0, 0, 1),
263};
264const freq_info PM_755B_90[] = {
265 /* 90 nm 2.00GHz Pentium M, VID #B */
266 FREQ_INFO(2000, 1324, INTEL_BUS_CLK),
267 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
268 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
269 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
270 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
271 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
272 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
273 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
274 FREQ_INFO( 0, 0, 1),
275};
276const freq_info PM_755C_90[] = {
277 /* 90 nm 2.00GHz Pentium M, VID #C */
278 FREQ_INFO(2000, 1308, INTEL_BUS_CLK),
279 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
280 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
281 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
282 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
283 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
284 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
285 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
286 FREQ_INFO( 0, 0, 1),
287};
288const freq_info PM_755D_90[] = {
289 /* 90 nm 2.00GHz Pentium M, VID #D */
290 FREQ_INFO(2000, 1276, INTEL_BUS_CLK),
291 FREQ_INFO(1800, 1244, INTEL_BUS_CLK),
292 FREQ_INFO(1600, 1196, INTEL_BUS_CLK),
293 FREQ_INFO(1400, 1164, INTEL_BUS_CLK),
294 FREQ_INFO(1200, 1116, INTEL_BUS_CLK),
295 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
296 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
297 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
298 FREQ_INFO( 0, 0, 1),
299};
300const freq_info PM_745A_90[] = {
301 /* 90 nm 1.80GHz Pentium M, VID #A */
302 FREQ_INFO(1800, 1340, INTEL_BUS_CLK),
303 FREQ_INFO(1600, 1292, INTEL_BUS_CLK),
304 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
305 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
306 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
307 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
308 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
309 FREQ_INFO( 0, 0, 1),
310};
311const freq_info PM_745B_90[] = {
312 /* 90 nm 1.80GHz Pentium M, VID #B */
313 FREQ_INFO(1800, 1324, INTEL_BUS_CLK),
314 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
315 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
316 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
317 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
318 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
319 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
320 FREQ_INFO( 0, 0, 1),
321};
322const freq_info PM_745C_90[] = {
323 /* 90 nm 1.80GHz Pentium M, VID #C */
324 FREQ_INFO(1800, 1308, INTEL_BUS_CLK),
325 FREQ_INFO(1600, 1260, INTEL_BUS_CLK),
326 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
327 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
328 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
329 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
330 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
331 FREQ_INFO( 0, 0, 1),
332};
333const freq_info PM_745D_90[] = {
334 /* 90 nm 1.80GHz Pentium M, VID #D */
335 FREQ_INFO(1800, 1276, INTEL_BUS_CLK),
336 FREQ_INFO(1600, 1228, INTEL_BUS_CLK),
337 FREQ_INFO(1400, 1180, INTEL_BUS_CLK),
338 FREQ_INFO(1200, 1132, INTEL_BUS_CLK),
339 FREQ_INFO(1000, 1084, INTEL_BUS_CLK),
340 FREQ_INFO( 800, 1036, INTEL_BUS_CLK),
341 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
342 FREQ_INFO( 0, 0, 1),
343};
344const freq_info PM_735A_90[] = {
345 /* 90 nm 1.70GHz Pentium M, VID #A */
346 FREQ_INFO(1700, 1340, INTEL_BUS_CLK),
347 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
348 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
349 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
350 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
351 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
352 FREQ_INFO( 0, 0, 1),
353};
354const freq_info PM_735B_90[] = {
355 /* 90 nm 1.70GHz Pentium M, VID #B */
356 FREQ_INFO(1700, 1324, INTEL_BUS_CLK),
357 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
358 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
359 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
360 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
361 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
362 FREQ_INFO( 0, 0, 1),
363};
364const freq_info PM_735C_90[] = {
365 /* 90 nm 1.70GHz Pentium M, VID #C */
366 FREQ_INFO(1700, 1308, INTEL_BUS_CLK),
367 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
368 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
369 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
370 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
371 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
372 FREQ_INFO( 0, 0, 1),
373};
374const freq_info PM_735D_90[] = {
375 /* 90 nm 1.70GHz Pentium M, VID #D */
376 FREQ_INFO(1700, 1276, INTEL_BUS_CLK),
377 FREQ_INFO(1400, 1212, INTEL_BUS_CLK),
378 FREQ_INFO(1200, 1148, INTEL_BUS_CLK),
379 FREQ_INFO(1000, 1100, INTEL_BUS_CLK),
380 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
381 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
382 FREQ_INFO( 0, 0, 1),
383};
384const freq_info PM_725A_90[] = {
385 /* 90 nm 1.60GHz Pentium M, VID #A */
386 FREQ_INFO(1600, 1340, INTEL_BUS_CLK),
387 FREQ_INFO(1400, 1276, INTEL_BUS_CLK),
388 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
389 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
390 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
391 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
392 FREQ_INFO( 0, 0, 1),
393};
394const freq_info PM_725B_90[] = {
395 /* 90 nm 1.60GHz Pentium M, VID #B */
396 FREQ_INFO(1600, 1324, INTEL_BUS_CLK),
397 FREQ_INFO(1400, 1260, INTEL_BUS_CLK),
398 FREQ_INFO(1200, 1196, INTEL_BUS_CLK),
399 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
400 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
401 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
402 FREQ_INFO( 0, 0, 1),
403};
404const freq_info PM_725C_90[] = {
405 /* 90 nm 1.60GHz Pentium M, VID #C */
406 FREQ_INFO(1600, 1308, INTEL_BUS_CLK),
407 FREQ_INFO(1400, 1244, INTEL_BUS_CLK),
408 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
409 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
410 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
411 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
412 FREQ_INFO( 0, 0, 1),
413};
414const freq_info PM_725D_90[] = {
415 /* 90 nm 1.60GHz Pentium M, VID #D */
416 FREQ_INFO(1600, 1276, INTEL_BUS_CLK),
417 FREQ_INFO(1400, 1228, INTEL_BUS_CLK),
418 FREQ_INFO(1200, 1164, INTEL_BUS_CLK),
419 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
420 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
421 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
422 FREQ_INFO( 0, 0, 1),
423};
424const freq_info PM_715A_90[] = {
425 /* 90 nm 1.50GHz Pentium M, VID #A */
426 FREQ_INFO(1500, 1340, INTEL_BUS_CLK),
427 FREQ_INFO(1200, 1228, INTEL_BUS_CLK),
428 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
429 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
430 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
431 FREQ_INFO( 0, 0, 1),
432};
433const freq_info PM_715B_90[] = {
434 /* 90 nm 1.50GHz Pentium M, VID #B */
435 FREQ_INFO(1500, 1324, INTEL_BUS_CLK),
436 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
437 FREQ_INFO(1000, 1148, INTEL_BUS_CLK),
438 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
439 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
440 FREQ_INFO( 0, 0, 1),
441};
442const freq_info PM_715C_90[] = {
443 /* 90 nm 1.50GHz Pentium M, VID #C */
444 FREQ_INFO(1500, 1308, INTEL_BUS_CLK),
445 FREQ_INFO(1200, 1212, INTEL_BUS_CLK),
446 FREQ_INFO(1000, 1132, INTEL_BUS_CLK),
447 FREQ_INFO( 800, 1068, INTEL_BUS_CLK),
448 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
449 FREQ_INFO( 0, 0, 1),
450};
451const freq_info PM_715D_90[] = {
452 /* 90 nm 1.50GHz Pentium M, VID #D */
453 FREQ_INFO(1500, 1276, INTEL_BUS_CLK),
454 FREQ_INFO(1200, 1180, INTEL_BUS_CLK),
455 FREQ_INFO(1000, 1116, INTEL_BUS_CLK),
456 FREQ_INFO( 800, 1052, INTEL_BUS_CLK),
457 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
458 FREQ_INFO( 0, 0, 1),
459};
460const freq_info PM_738_90[] = {
461 /* 90 nm 1.40GHz Low Voltage Pentium M */
462 FREQ_INFO(1400, 1116, INTEL_BUS_CLK),
463 FREQ_INFO(1300, 1116, INTEL_BUS_CLK),
464 FREQ_INFO(1200, 1100, INTEL_BUS_CLK),
465 FREQ_INFO(1100, 1068, INTEL_BUS_CLK),
466 FREQ_INFO(1000, 1052, INTEL_BUS_CLK),
467 FREQ_INFO( 900, 1036, INTEL_BUS_CLK),
468 FREQ_INFO( 800, 1020, INTEL_BUS_CLK),
469 FREQ_INFO( 600, 988, INTEL_BUS_CLK),
470 FREQ_INFO( 0, 0, 1),
471};
472const freq_info PM_733_90[] = {
473 /* 90 nm 1.10GHz Ultra Low Voltage Pentium M */
474 FREQ_INFO(1100, 940, INTEL_BUS_CLK),
475 FREQ_INFO(1000, 924, INTEL_BUS_CLK),
476 FREQ_INFO( 900, 892, INTEL_BUS_CLK),
477 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
478 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
479 FREQ_INFO( 0, 0, 1),
480};
481const freq_info PM_723_90[] = {
482 /* 90 nm 1.00GHz Ultra Low Voltage Pentium M */
483 FREQ_INFO(1000, 940, INTEL_BUS_CLK),
484 FREQ_INFO( 900, 908, INTEL_BUS_CLK),
485 FREQ_INFO( 800, 876, INTEL_BUS_CLK),
486 FREQ_INFO( 600, 812, INTEL_BUS_CLK),
487 FREQ_INFO( 0, 0, 1),
488};
489
490const cpu_info ESTprocs[] = {
491 INTEL(PM17_130, 1700, 1484, 600, 956, INTEL_BUS_CLK),
492 INTEL(PM16_130, 1600, 1484, 600, 956, INTEL_BUS_CLK),
493 INTEL(PM15_130, 1500, 1484, 600, 956, INTEL_BUS_CLK),
494 INTEL(PM14_130, 1400, 1484, 600, 956, INTEL_BUS_CLK),
495 INTEL(PM13_130, 1300, 1388, 600, 956, INTEL_BUS_CLK),
496 INTEL(PM13_LV_130, 1300, 1180, 600, 956, INTEL_BUS_CLK),
497 INTEL(PM12_LV_130, 1200, 1180, 600, 956, INTEL_BUS_CLK),
498 INTEL(PM11_LV_130, 1100, 1180, 600, 956, INTEL_BUS_CLK),
499 INTEL(PM11_ULV_130, 1100, 1004, 600, 844, INTEL_BUS_CLK),
500 INTEL(PM10_ULV_130, 1000, 1004, 600, 844, INTEL_BUS_CLK),
501 INTEL(PM_765A_90, 2100, 1340, 600, 988, INTEL_BUS_CLK),
502 INTEL(PM_765B_90, 2100, 1324, 600, 988, INTEL_BUS_CLK),
503 INTEL(PM_765C_90, 2100, 1308, 600, 988, INTEL_BUS_CLK),
504 INTEL(PM_765E_90, 2100, 1356, 600, 988, INTEL_BUS_CLK),
505 INTEL(PM_755A_90, 2000, 1340, 600, 988, INTEL_BUS_CLK),
506 INTEL(PM_755B_90, 2000, 1324, 600, 988, INTEL_BUS_CLK),
507 INTEL(PM_755C_90, 2000, 1308, 600, 988, INTEL_BUS_CLK),
508 INTEL(PM_755D_90, 2000, 1276, 600, 988, INTEL_BUS_CLK),
509 INTEL(PM_745A_90, 1800, 1340, 600, 988, INTEL_BUS_CLK),
510 INTEL(PM_745B_90, 1800, 1324, 600, 988, INTEL_BUS_CLK),
511 INTEL(PM_745C_90, 1800, 1308, 600, 988, INTEL_BUS_CLK),
512 INTEL(PM_745D_90, 1800, 1276, 600, 988, INTEL_BUS_CLK),
513 INTEL(PM_735A_90, 1700, 1340, 600, 988, INTEL_BUS_CLK),
514 INTEL(PM_735B_90, 1700, 1324, 600, 988, INTEL_BUS_CLK),
515 INTEL(PM_735C_90, 1700, 1308, 600, 988, INTEL_BUS_CLK),
516 INTEL(PM_735D_90, 1700, 1276, 600, 988, INTEL_BUS_CLK),
517 INTEL(PM_725A_90, 1600, 1340, 600, 988, INTEL_BUS_CLK),
518 INTEL(PM_725B_90, 1600, 1324, 600, 988, INTEL_BUS_CLK),
519 INTEL(PM_725C_90, 1600, 1308, 600, 988, INTEL_BUS_CLK),
520 INTEL(PM_725D_90, 1600, 1276, 600, 988, INTEL_BUS_CLK),
521 INTEL(PM_715A_90, 1500, 1340, 600, 988, INTEL_BUS_CLK),
522 INTEL(PM_715B_90, 1500, 1324, 600, 988, INTEL_BUS_CLK),
523 INTEL(PM_715C_90, 1500, 1308, 600, 988, INTEL_BUS_CLK),
524 INTEL(PM_715D_90, 1500, 1276, 600, 988, INTEL_BUS_CLK),
525 INTEL(PM_738_90, 1400, 1116, 600, 988, INTEL_BUS_CLK),
526 INTEL(PM_733_90, 1100, 940, 600, 812, INTEL_BUS_CLK),
527 INTEL(PM_723_90, 1000, 940, 600, 812, INTEL_BUS_CLK),
528 { NULL, 0, 0, NULL },
529};
530
531static void est_identify(driver_t *driver, device_t parent);
532static int est_probe(device_t parent);
533static int est_attach(device_t parent);
534static int est_detach(device_t parent);
535static int est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
536 const freq_info **freqs);
537static const freq_info *est_get_current(const freq_info *freq_list);
538static int est_settings(device_t dev, struct cf_setting *sets, int *count);
539static int est_set(device_t dev, const struct cf_setting *set);
540static int est_get(device_t dev, struct cf_setting *set);
541static int est_type(device_t dev, int *type);
542
543static device_method_t est_methods[] = {
544 /* Device interface */
545 DEVMETHOD(device_identify, est_identify),
546 DEVMETHOD(device_probe, est_probe),
547 DEVMETHOD(device_attach, est_attach),
548 DEVMETHOD(device_detach, est_detach),
549
550 /* cpufreq interface */
551 DEVMETHOD(cpufreq_drv_set, est_set),
552 DEVMETHOD(cpufreq_drv_get, est_get),
553 DEVMETHOD(cpufreq_drv_type, est_type),
554 DEVMETHOD(cpufreq_drv_settings, est_settings),
555 {0, 0}
556};
557
558static driver_t est_driver = {
559 "est",
560 est_methods,
561 sizeof(struct est_softc),
562};
563
564static devclass_t est_devclass;
565DRIVER_MODULE(est, cpu, est_driver, est_devclass, 0, 0);
566
567static void
568est_identify(driver_t *driver, device_t parent)
569{
570 u_int p[4];
571
572 /* Make sure we're not being doubly invoked. */
573 if (device_find_child(parent, "est", -1) != NULL)
574 return;
575
576 /* Check that CPUID is supported and the vendor is Intel.*/
577 if (cpu_high == 0 || strcmp(cpu_vendor, GenuineIntel) != 0)
578 return;
579
580 /* Read capability bits and check if the CPU supports EST. */
581 do_cpuid(1, p);
582 if ((p[2] & 0x80) == 0)
583 return;
584
585 if (BUS_ADD_CHILD(parent, 0, "est", -1) == NULL)
586 device_printf(parent, "add est child failed\n");
587}
588
589static int
590est_probe(device_t dev)
591{
592 const freq_info *f;
593 device_t perf_dev;
594 uint64_t msr;
595 int error, type;
596
597 if (resource_disabled("est", 0))
598 return (ENXIO);
596
597 /*
598 * If the ACPI perf driver has attached and is not just offering
599 * info, let it manage things.
600 */
601 perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
602 if (perf_dev && device_is_attached(perf_dev)) {
603 error = CPUFREQ_DRV_TYPE(perf_dev, &type);
604 if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
605 return (ENXIO);
606 }
607
608 /* Attempt to enable SpeedStep if not currently enabled. */
609 msr = rdmsr(MSR_MISC_ENABLE);
610 if ((msr & MSR_SS_ENABLE) == 0) {
611 wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
612
613 /* Check if the enable failed. */
614 msr = rdmsr(MSR_MISC_ENABLE);
615 if ((msr & MSR_SS_ENABLE) == 0) {
616 device_printf(dev, "failed to enable SpeedStep\n");
617 return (ENXIO);
618 }
619 }
620
621 /* Identify the exact CPU model */
622 msr = rdmsr(MSR_PERF_STATUS);
623 if (est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &f) != 0) {
624 printf(
625 "CPU claims to support Enhanced Speedstep, but is not recognized.\n"
626 "Please update driver or contact the maintainer.\n"
627 "cpu_vendor = %s msr = %0jx, bus_clk = %x\n",
628 cpu_vendor, msr, INTEL_BUS_CLK);
629 return (ENXIO);
630 }
631
632 device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
633 return (0);
634}
635
636static int
637est_attach(device_t dev)
638{
639 struct est_softc *sc;
640 uint64_t msr;
641
642 sc = device_get_softc(dev);
643 sc->dev = dev;
644 msr = rdmsr(MSR_PERF_STATUS);
645 est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &sc->freq_list);
646 cpufreq_register(dev);
647
648 return (0);
649}
650
651static int
652est_detach(device_t dev)
653{
654 return (ENXIO);
655}
656
657static int
658est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
659 const freq_info **freqs)
660{
661 const cpu_info *p;
662 uint32_t id;
663
664 /* Find a table which matches (vendor, id, bus_clk). */
665 id = msr >> 32;
666 for (p = ESTprocs; p->id32 != 0; p++) {
667 if (strcmp(p->vendor, vendor) == 0 && p->id32 == id &&
668 p->bus_clk == bus_clk)
669 break;
670 }
671 if (p->id32 == 0)
672 return (EOPNOTSUPP);
673
674 /* Make sure the current setpoint is valid. */
675 if (est_get_current(p->freqtab) == NULL)
676 return (EOPNOTSUPP);
677
678 *freqs = p->freqtab;
679 return (0);
680}
681
682static const freq_info *
683est_get_current(const freq_info *freq_list)
684{
685 const freq_info *f;
686 int i;
687 uint16_t id16;
688
689 /*
690 * Try a few times to get a valid value. Sometimes, if the CPU
691 * is in the middle of an asynchronous transition (i.e., P4TCC),
692 * we get a temporary invalid result.
693 */
694 for (i = 0; i < 5; i++) {
695 id16 = rdmsr(MSR_PERF_STATUS) & 0xffff;
696 for (f = freq_list; f->id16 != 0; f++) {
697 if (f->id16 == id16)
698 return (f);
699 }
700 DELAY(100);
701 }
702 return (NULL);
703}
704
705static int
706est_settings(device_t dev, struct cf_setting *sets, int *count)
707{
708 struct est_softc *sc;
709 const freq_info *f;
710 int i;
711
712 sc = device_get_softc(dev);
713 if (*count < EST_MAX_SETTINGS)
714 return (E2BIG);
715
716 i = 0;
717 for (f = sc->freq_list; f->freq != 0; f++) {
718 sets[i].freq = f->freq;
719 sets[i].volts = f->volts;
720 sets[i].power = CPUFREQ_VAL_UNKNOWN;
721 sets[i].lat = EST_TRANS_LAT;
722 sets[i].dev = dev;
723 i++;
724 }
725 *count = i + 1;
726
727 return (0);
728}
729
730static int
731est_set(device_t dev, const struct cf_setting *set)
732{
733 struct est_softc *sc;
734 const freq_info *f;
735 uint64_t msr;
736
737 /* Find the setting matching the requested one. */
738 sc = device_get_softc(dev);
739 for (f = sc->freq_list; f->freq != 0; f++) {
740 if (f->freq == set->freq)
741 break;
742 }
743 if (f->freq == 0)
744 return (EINVAL);
745
746 /* Read the current register, mask out the old, set the new id. */
747 msr = rdmsr(MSR_PERF_CTL);
748 msr = (msr & ~0xffff) | f->id16;
749 wrmsr(MSR_PERF_CTL, msr);
750
751 /* Wait a short while for the new setting. Is this necessary? */
752 DELAY(EST_TRANS_LAT);
753
754 return (0);
755}
756
757static int
758est_get(device_t dev, struct cf_setting *set)
759{
760 struct est_softc *sc;
761 const freq_info *f;
762
763 sc = device_get_softc(dev);
764 f = est_get_current(sc->freq_list);
765 if (f == NULL)
766 return (ENXIO);
767
768 set->freq = f->freq;
769 set->volts = f->volts;
770 set->power = CPUFREQ_VAL_UNKNOWN;
771 set->lat = EST_TRANS_LAT;
772 set->dev = dev;
773 return (0);
774}
775
776static int
777est_type(device_t dev, int *type)
778{
779
780 if (type == NULL)
781 return (EINVAL);
782
783 *type = CPUFREQ_TYPE_ABSOLUTE;
784 return (0);
785}
599
600 /*
601 * If the ACPI perf driver has attached and is not just offering
602 * info, let it manage things.
603 */
604 perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
605 if (perf_dev && device_is_attached(perf_dev)) {
606 error = CPUFREQ_DRV_TYPE(perf_dev, &type);
607 if (error == 0 && (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
608 return (ENXIO);
609 }
610
611 /* Attempt to enable SpeedStep if not currently enabled. */
612 msr = rdmsr(MSR_MISC_ENABLE);
613 if ((msr & MSR_SS_ENABLE) == 0) {
614 wrmsr(MSR_MISC_ENABLE, msr | MSR_SS_ENABLE);
615
616 /* Check if the enable failed. */
617 msr = rdmsr(MSR_MISC_ENABLE);
618 if ((msr & MSR_SS_ENABLE) == 0) {
619 device_printf(dev, "failed to enable SpeedStep\n");
620 return (ENXIO);
621 }
622 }
623
624 /* Identify the exact CPU model */
625 msr = rdmsr(MSR_PERF_STATUS);
626 if (est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &f) != 0) {
627 printf(
628 "CPU claims to support Enhanced Speedstep, but is not recognized.\n"
629 "Please update driver or contact the maintainer.\n"
630 "cpu_vendor = %s msr = %0jx, bus_clk = %x\n",
631 cpu_vendor, msr, INTEL_BUS_CLK);
632 return (ENXIO);
633 }
634
635 device_set_desc(dev, "Enhanced SpeedStep Frequency Control");
636 return (0);
637}
638
639static int
640est_attach(device_t dev)
641{
642 struct est_softc *sc;
643 uint64_t msr;
644
645 sc = device_get_softc(dev);
646 sc->dev = dev;
647 msr = rdmsr(MSR_PERF_STATUS);
648 est_find_cpu(cpu_vendor, msr, INTEL_BUS_CLK, &sc->freq_list);
649 cpufreq_register(dev);
650
651 return (0);
652}
653
654static int
655est_detach(device_t dev)
656{
657 return (ENXIO);
658}
659
660static int
661est_find_cpu(const char *vendor, uint64_t msr, uint32_t bus_clk,
662 const freq_info **freqs)
663{
664 const cpu_info *p;
665 uint32_t id;
666
667 /* Find a table which matches (vendor, id, bus_clk). */
668 id = msr >> 32;
669 for (p = ESTprocs; p->id32 != 0; p++) {
670 if (strcmp(p->vendor, vendor) == 0 && p->id32 == id &&
671 p->bus_clk == bus_clk)
672 break;
673 }
674 if (p->id32 == 0)
675 return (EOPNOTSUPP);
676
677 /* Make sure the current setpoint is valid. */
678 if (est_get_current(p->freqtab) == NULL)
679 return (EOPNOTSUPP);
680
681 *freqs = p->freqtab;
682 return (0);
683}
684
685static const freq_info *
686est_get_current(const freq_info *freq_list)
687{
688 const freq_info *f;
689 int i;
690 uint16_t id16;
691
692 /*
693 * Try a few times to get a valid value. Sometimes, if the CPU
694 * is in the middle of an asynchronous transition (i.e., P4TCC),
695 * we get a temporary invalid result.
696 */
697 for (i = 0; i < 5; i++) {
698 id16 = rdmsr(MSR_PERF_STATUS) & 0xffff;
699 for (f = freq_list; f->id16 != 0; f++) {
700 if (f->id16 == id16)
701 return (f);
702 }
703 DELAY(100);
704 }
705 return (NULL);
706}
707
708static int
709est_settings(device_t dev, struct cf_setting *sets, int *count)
710{
711 struct est_softc *sc;
712 const freq_info *f;
713 int i;
714
715 sc = device_get_softc(dev);
716 if (*count < EST_MAX_SETTINGS)
717 return (E2BIG);
718
719 i = 0;
720 for (f = sc->freq_list; f->freq != 0; f++) {
721 sets[i].freq = f->freq;
722 sets[i].volts = f->volts;
723 sets[i].power = CPUFREQ_VAL_UNKNOWN;
724 sets[i].lat = EST_TRANS_LAT;
725 sets[i].dev = dev;
726 i++;
727 }
728 *count = i + 1;
729
730 return (0);
731}
732
733static int
734est_set(device_t dev, const struct cf_setting *set)
735{
736 struct est_softc *sc;
737 const freq_info *f;
738 uint64_t msr;
739
740 /* Find the setting matching the requested one. */
741 sc = device_get_softc(dev);
742 for (f = sc->freq_list; f->freq != 0; f++) {
743 if (f->freq == set->freq)
744 break;
745 }
746 if (f->freq == 0)
747 return (EINVAL);
748
749 /* Read the current register, mask out the old, set the new id. */
750 msr = rdmsr(MSR_PERF_CTL);
751 msr = (msr & ~0xffff) | f->id16;
752 wrmsr(MSR_PERF_CTL, msr);
753
754 /* Wait a short while for the new setting. Is this necessary? */
755 DELAY(EST_TRANS_LAT);
756
757 return (0);
758}
759
760static int
761est_get(device_t dev, struct cf_setting *set)
762{
763 struct est_softc *sc;
764 const freq_info *f;
765
766 sc = device_get_softc(dev);
767 f = est_get_current(sc->freq_list);
768 if (f == NULL)
769 return (ENXIO);
770
771 set->freq = f->freq;
772 set->volts = f->volts;
773 set->power = CPUFREQ_VAL_UNKNOWN;
774 set->lat = EST_TRANS_LAT;
775 set->dev = dev;
776 return (0);
777}
778
779static int
780est_type(device_t dev, int *type)
781{
782
783 if (type == NULL)
784 return (EINVAL);
785
786 *type = CPUFREQ_TYPE_ABSOLUTE;
787 return (0);
788}