xref: /freebsd/sys/x86/cpufreq/powernow.c (revision 3494f7c0)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2004-2005 Bruno Ducrot
5  * Copyright (c) 2004 FUKUDA Nobuhiko <nfukuda@spa.is.uec.ac.jp>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 /*
29  * Many thanks to Nate Lawson for his helpful comments on this driver and
30  * to Jung-uk Kim for testing.
31  */
32 
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/cpu.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/pcpu.h>
40 #include <sys/systm.h>
41 
42 #include <machine/pc/bios.h>
43 #include <machine/md_var.h>
44 #include <machine/specialreg.h>
45 #include <machine/cputypes.h>
46 #include <machine/vmparam.h>
47 #include <sys/rman.h>
48 
49 #include <vm/vm.h>
50 #include <vm/pmap.h>
51 
52 #include "cpufreq_if.h"
53 
54 #define PN7_TYPE	0
55 #define PN8_TYPE	1
56 
57 /* Flags for some hardware bugs. */
58 #define A0_ERRATA	0x1	/* Bugs for the rev. A0 of Athlon (K7):
59 				 * Interrupts must be disabled and no half
60 				 * multipliers are allowed */
61 #define PENDING_STUCK	0x2	/* With some buggy chipset and some newer AMD64
62 				 * processor (Rev. G?):
63 				 * the pending bit from the msr FIDVID_STATUS
64 				 * is set forever.  No workaround :( */
65 
66 /* Legacy configuration via BIOS table PSB. */
67 #define PSB_START	0
68 #define PSB_STEP	0x10
69 #define PSB_SIG		"AMDK7PNOW!"
70 #define PSB_LEN		10
71 #define PSB_OFF		0
72 
73 struct psb_header {
74 	char		 signature[10];
75 	uint8_t		 version;
76 	uint8_t		 flags;
77 	uint16_t	 settlingtime;
78 	uint8_t		 res1;
79 	uint8_t		 numpst;
80 } __packed;
81 
82 struct pst_header {
83 	uint32_t	 cpuid;
84 	uint8_t		 fsb;
85 	uint8_t		 maxfid;
86 	uint8_t		 startvid;
87 	uint8_t		 numpstates;
88 } __packed;
89 
90 /*
91  * MSRs and bits used by Powernow technology
92  */
93 #define MSR_AMDK7_FIDVID_CTL		0xc0010041
94 #define MSR_AMDK7_FIDVID_STATUS		0xc0010042
95 
96 /* Bitfields used by K7 */
97 
98 #define PN7_CTR_FID(x)			((x) & 0x1f)
99 #define PN7_CTR_VID(x)			(((x) & 0x1f) << 8)
100 #define PN7_CTR_FIDC			0x00010000
101 #define PN7_CTR_VIDC			0x00020000
102 #define PN7_CTR_FIDCHRATIO		0x00100000
103 #define PN7_CTR_SGTC(x)			(((uint64_t)(x) & 0x000fffff) << 32)
104 
105 #define PN7_STA_CFID(x)			((x) & 0x1f)
106 #define PN7_STA_SFID(x)			(((x) >> 8) & 0x1f)
107 #define PN7_STA_MFID(x)			(((x) >> 16) & 0x1f)
108 #define PN7_STA_CVID(x)			(((x) >> 32) & 0x1f)
109 #define PN7_STA_SVID(x)			(((x) >> 40) & 0x1f)
110 #define PN7_STA_MVID(x)			(((x) >> 48) & 0x1f)
111 
112 /* ACPI ctr_val status register to powernow k7 configuration */
113 #define ACPI_PN7_CTRL_TO_FID(x)		((x) & 0x1f)
114 #define ACPI_PN7_CTRL_TO_VID(x)		(((x) >> 5) & 0x1f)
115 #define ACPI_PN7_CTRL_TO_SGTC(x)	(((x) >> 10) & 0xffff)
116 
117 /* Bitfields used by K8 */
118 
119 #define PN8_CTR_FID(x)			((x) & 0x3f)
120 #define PN8_CTR_VID(x)			(((x) & 0x1f) << 8)
121 #define PN8_CTR_PENDING(x)		(((x) & 1) << 32)
122 
123 #define PN8_STA_CFID(x)			((x) & 0x3f)
124 #define PN8_STA_SFID(x)			(((x) >> 8) & 0x3f)
125 #define PN8_STA_MFID(x)			(((x) >> 16) & 0x3f)
126 #define PN8_STA_PENDING(x)		(((x) >> 31) & 0x01)
127 #define PN8_STA_CVID(x)			(((x) >> 32) & 0x1f)
128 #define PN8_STA_SVID(x)			(((x) >> 40) & 0x1f)
129 #define PN8_STA_MVID(x)			(((x) >> 48) & 0x1f)
130 
131 /* Reserved1 to powernow k8 configuration */
132 #define PN8_PSB_TO_RVO(x)		((x) & 0x03)
133 #define PN8_PSB_TO_IRT(x)		(((x) >> 2) & 0x03)
134 #define PN8_PSB_TO_MVS(x)		(((x) >> 4) & 0x03)
135 #define PN8_PSB_TO_BATT(x)		(((x) >> 6) & 0x03)
136 
137 /* ACPI ctr_val status register to powernow k8 configuration */
138 #define ACPI_PN8_CTRL_TO_FID(x)		((x) & 0x3f)
139 #define ACPI_PN8_CTRL_TO_VID(x)		(((x) >> 6) & 0x1f)
140 #define ACPI_PN8_CTRL_TO_VST(x)		(((x) >> 11) & 0x1f)
141 #define ACPI_PN8_CTRL_TO_MVS(x)		(((x) >> 18) & 0x03)
142 #define ACPI_PN8_CTRL_TO_PLL(x)		(((x) >> 20) & 0x7f)
143 #define ACPI_PN8_CTRL_TO_RVO(x)		(((x) >> 28) & 0x03)
144 #define ACPI_PN8_CTRL_TO_IRT(x)		(((x) >> 30) & 0x03)
145 
146 #define WRITE_FIDVID(fid, vid, ctrl)	\
147 	wrmsr(MSR_AMDK7_FIDVID_CTL,	\
148 	    (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
149 
150 #define COUNT_OFF_IRT(irt)	DELAY(10 * (1 << (irt)))
151 #define COUNT_OFF_VST(vst)	DELAY(20 * (vst))
152 
153 #define FID_TO_VCO_FID(fid)	\
154 	(((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
155 
156 /*
157  * Divide each value by 10 to get the processor multiplier.
158  * Some of those tables are the same as the Linux powernow-k7
159  * implementation by Dave Jones.
160  */
161 static int pn7_fid_to_mult[32] = {
162 	110, 115, 120, 125, 50, 55, 60, 65,
163 	70, 75, 80, 85, 90, 95, 100, 105,
164 	30, 190, 40, 200, 130, 135, 140, 210,
165 	150, 225, 160, 165, 170, 180, 0, 0,
166 };
167 
168 static int pn8_fid_to_mult[64] = {
169 	40, 45, 50, 55, 60, 65, 70, 75,
170 	80, 85, 90, 95, 100, 105, 110, 115,
171 	120, 125, 130, 135, 140, 145, 150, 155,
172 	160, 165, 170, 175, 180, 185, 190, 195,
173 	200, 205, 210, 215, 220, 225, 230, 235,
174 	240, 245, 250, 255, 260, 265, 270, 275,
175 	280, 285, 290, 295, 300, 305, 310, 315,
176 	320, 325, 330, 335, 340, 345, 350, 355,
177 };
178 
179 /*
180  * Units are in mV.
181  */
182 /* Mobile VRM (K7) */
183 static int pn7_mobile_vid_to_volts[] = {
184 	2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
185 	1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
186 	1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
187 	1075, 1050, 1025, 1000, 975, 950, 925, 0,
188 };
189 /* Desktop VRM (K7) */
190 static int pn7_desktop_vid_to_volts[] = {
191 	2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
192 	1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
193 	1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
194 	1075, 1050, 1025, 1000, 975, 950, 925, 0,
195 };
196 /* Desktop and Mobile VRM (K8) */
197 static int pn8_vid_to_volts[] = {
198 	1550, 1525, 1500, 1475, 1450, 1425, 1400, 1375,
199 	1350, 1325, 1300, 1275, 1250, 1225, 1200, 1175,
200 	1150, 1125, 1100, 1075, 1050, 1025, 1000, 975,
201 	950, 925, 900, 875, 850, 825, 800, 0,
202 };
203 
204 #define POWERNOW_MAX_STATES		16
205 
206 struct powernow_state {
207 	int freq;
208 	int power;
209 	int fid;
210 	int vid;
211 };
212 
213 struct pn_softc {
214 	device_t		 dev;
215 	int			 pn_type;
216 	struct powernow_state	 powernow_states[POWERNOW_MAX_STATES];
217 	u_int			 fsb;
218 	u_int			 sgtc;
219 	u_int			 vst;
220 	u_int			 mvs;
221 	u_int			 pll;
222 	u_int			 rvo;
223 	u_int			 irt;
224 	int			 low;
225 	int			 powernow_max_states;
226 	u_int			 powernow_state;
227 	u_int			 errata;
228 	int			*vid_to_volts;
229 };
230 
231 /*
232  * Offsets in struct cf_setting array for private values given by
233  * acpi_perf driver.
234  */
235 #define PX_SPEC_CONTROL		0
236 #define PX_SPEC_STATUS		1
237 
238 static void	pn_identify(driver_t *driver, device_t parent);
239 static int	pn_probe(device_t dev);
240 static int	pn_attach(device_t dev);
241 static int	pn_detach(device_t dev);
242 static int	pn_set(device_t dev, const struct cf_setting *cf);
243 static int	pn_get(device_t dev, struct cf_setting *cf);
244 static int	pn_settings(device_t dev, struct cf_setting *sets,
245 		    int *count);
246 static int	pn_type(device_t dev, int *type);
247 
248 static device_method_t pn_methods[] = {
249 	/* Device interface */
250 	DEVMETHOD(device_identify, pn_identify),
251 	DEVMETHOD(device_probe, pn_probe),
252 	DEVMETHOD(device_attach, pn_attach),
253 	DEVMETHOD(device_detach, pn_detach),
254 
255 	/* cpufreq interface */
256 	DEVMETHOD(cpufreq_drv_set, pn_set),
257 	DEVMETHOD(cpufreq_drv_get, pn_get),
258 	DEVMETHOD(cpufreq_drv_settings, pn_settings),
259 	DEVMETHOD(cpufreq_drv_type, pn_type),
260 	{0, 0}
261 };
262 
263 static driver_t pn_driver = {
264 	"powernow",
265 	pn_methods,
266 	sizeof(struct pn_softc),
267 };
268 
269 DRIVER_MODULE(powernow, cpu, pn_driver, 0, 0);
270 
271 static int
272 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
273 {
274 	int cfid, cvid;
275 	uint64_t status, ctl;
276 
277 	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
278 	cfid = PN7_STA_CFID(status);
279 	cvid = PN7_STA_CVID(status);
280 
281 	/* We're already at the requested level. */
282 	if (fid == cfid && vid == cvid)
283 		return (0);
284 
285 	ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
286 
287 	ctl |= PN7_CTR_FID(fid);
288 	ctl |= PN7_CTR_VID(vid);
289 	ctl |= PN7_CTR_SGTC(sc->sgtc);
290 
291 	if (sc->errata & A0_ERRATA)
292 		disable_intr();
293 
294 	if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
295 		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
296 		if (vid != cvid)
297 			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
298 	} else {
299 		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
300 		if (fid != cfid)
301 			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
302 	}
303 
304 	if (sc->errata & A0_ERRATA)
305 		enable_intr();
306 
307 	return (0);
308 }
309 
310 static int
311 pn8_read_pending_wait(uint64_t *status)
312 {
313 	int i = 10000;
314 
315 	do
316 		*status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
317 	while (PN8_STA_PENDING(*status) && --i);
318 
319 	return (i == 0 ? ENXIO : 0);
320 }
321 
322 static int
323 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
324 {
325 	int i = 100;
326 
327 	do
328 		WRITE_FIDVID(fid, vid, ctrl);
329 	while (pn8_read_pending_wait(status) && --i);
330 
331 	return (i == 0 ? ENXIO : 0);
332 }
333 
334 static int
335 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
336 {
337 	uint64_t status;
338 	int cfid, cvid;
339 	int rvo;
340 	int rv;
341 	u_int val;
342 
343 	rv = pn8_read_pending_wait(&status);
344 	if (rv)
345 		return (rv);
346 
347 	cfid = PN8_STA_CFID(status);
348 	cvid = PN8_STA_CVID(status);
349 
350 	if (fid == cfid && vid == cvid)
351 		return (0);
352 
353 	/*
354 	 * Phase 1: Raise core voltage to requested VID if frequency is
355 	 * going up.
356 	 */
357 	while (cvid > vid) {
358 		val = cvid - (1 << sc->mvs);
359 		rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
360 		if (rv) {
361 			sc->errata |= PENDING_STUCK;
362 			return (rv);
363 		}
364 		cvid = PN8_STA_CVID(status);
365 		COUNT_OFF_VST(sc->vst);
366 	}
367 
368 	/* ... then raise to voltage + RVO (if required) */
369 	for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
370 		/* XXX It's not clear from spec if we have to do that
371 		 * in 0.25 step or in MVS.  Therefore do it as it's done
372 		 * under Linux */
373 		rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
374 		if (rv) {
375 			sc->errata |= PENDING_STUCK;
376 			return (rv);
377 		}
378 		cvid = PN8_STA_CVID(status);
379 		COUNT_OFF_VST(sc->vst);
380 	}
381 
382 	/* Phase 2: change to requested core frequency */
383 	if (cfid != fid) {
384 		u_int vco_fid, vco_cfid, fid_delta;
385 
386 		vco_fid = FID_TO_VCO_FID(fid);
387 		vco_cfid = FID_TO_VCO_FID(cfid);
388 
389 		while (abs(vco_fid - vco_cfid) > 2) {
390 			fid_delta = (vco_cfid & 1) ? 1 : 2;
391 			if (fid > cfid) {
392 				if (cfid > 7)
393 					val = cfid + fid_delta;
394 				else
395 					val = FID_TO_VCO_FID(cfid) + fid_delta;
396 			} else
397 				val = cfid - fid_delta;
398 			rv = pn8_write_fidvid(val, cvid,
399 			    sc->pll * (uint64_t) sc->fsb,
400 			    &status);
401 			if (rv) {
402 				sc->errata |= PENDING_STUCK;
403 				return (rv);
404 			}
405 			cfid = PN8_STA_CFID(status);
406 			COUNT_OFF_IRT(sc->irt);
407 
408 			vco_cfid = FID_TO_VCO_FID(cfid);
409 		}
410 
411 		rv = pn8_write_fidvid(fid, cvid,
412 		    sc->pll * (uint64_t) sc->fsb,
413 		    &status);
414 		if (rv) {
415 			sc->errata |= PENDING_STUCK;
416 			return (rv);
417 		}
418 		cfid = PN8_STA_CFID(status);
419 		COUNT_OFF_IRT(sc->irt);
420 	}
421 
422 	/* Phase 3: change to requested voltage */
423 	if (cvid != vid) {
424 		rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
425 		cvid = PN8_STA_CVID(status);
426 		COUNT_OFF_VST(sc->vst);
427 	}
428 
429 	/* Check if transition failed. */
430 	if (cfid != fid || cvid != vid)
431 		rv = ENXIO;
432 
433 	return (rv);
434 }
435 
436 static int
437 pn_set(device_t dev, const struct cf_setting *cf)
438 {
439 	struct pn_softc *sc;
440 	int fid, vid;
441 	int i;
442 	int rv;
443 
444 	if (cf == NULL)
445 		return (EINVAL);
446 	sc = device_get_softc(dev);
447 
448 	if (sc->errata & PENDING_STUCK)
449 		return (ENXIO);
450 
451 	for (i = 0; i < sc->powernow_max_states; ++i)
452 		if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
453 			break;
454 
455 	fid = sc->powernow_states[i].fid;
456 	vid = sc->powernow_states[i].vid;
457 
458 	rv = ENODEV;
459 
460 	switch (sc->pn_type) {
461 	case PN7_TYPE:
462 		rv = pn7_setfidvid(sc, fid, vid);
463 		break;
464 	case PN8_TYPE:
465 		rv = pn8_setfidvid(sc, fid, vid);
466 		break;
467 	}
468 
469 	return (rv);
470 }
471 
472 static int
473 pn_get(device_t dev, struct cf_setting *cf)
474 {
475 	struct pn_softc *sc;
476 	u_int cfid = 0, cvid = 0;
477 	int i;
478 	uint64_t status;
479 
480 	if (cf == NULL)
481 		return (EINVAL);
482 	sc = device_get_softc(dev);
483 	if (sc->errata & PENDING_STUCK)
484 		return (ENXIO);
485 
486 	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
487 
488 	switch (sc->pn_type) {
489 	case PN7_TYPE:
490 		cfid = PN7_STA_CFID(status);
491 		cvid = PN7_STA_CVID(status);
492 		break;
493 	case PN8_TYPE:
494 		cfid = PN8_STA_CFID(status);
495 		cvid = PN8_STA_CVID(status);
496 		break;
497 	}
498 	for (i = 0; i < sc->powernow_max_states; ++i)
499 		if (cfid == sc->powernow_states[i].fid &&
500 		    cvid == sc->powernow_states[i].vid)
501 			break;
502 
503 	if (i < sc->powernow_max_states) {
504 		cf->freq = sc->powernow_states[i].freq / 1000;
505 		cf->power = sc->powernow_states[i].power;
506 		cf->lat = 200;
507 		cf->volts = sc->vid_to_volts[cvid];
508 		cf->dev = dev;
509 	} else {
510 		memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
511 		cf->dev = NULL;
512 	}
513 
514 	return (0);
515 }
516 
517 static int
518 pn_settings(device_t dev, struct cf_setting *sets, int *count)
519 {
520 	struct pn_softc *sc;
521 	int i;
522 
523 	if (sets == NULL|| count == NULL)
524 		return (EINVAL);
525 	sc = device_get_softc(dev);
526 	if (*count < sc->powernow_max_states)
527 		return (E2BIG);
528 	for (i = 0; i < sc->powernow_max_states; ++i) {
529 		sets[i].freq = sc->powernow_states[i].freq / 1000;
530 		sets[i].power = sc->powernow_states[i].power;
531 		sets[i].lat = 200;
532 		sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
533 		sets[i].dev = dev;
534 	}
535 	*count = sc->powernow_max_states;
536 
537 	return (0);
538 }
539 
540 static int
541 pn_type(device_t dev, int *type)
542 {
543 	if (type == NULL)
544 		return (EINVAL);
545 
546 	*type = CPUFREQ_TYPE_ABSOLUTE;
547 
548 	return (0);
549 }
550 
551 /*
552  * Given a set of pair of fid/vid, and number of performance states,
553  * compute powernow_states via an insertion sort.
554  */
555 static int
556 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
557 {
558 	int i, j, n;
559 	struct powernow_state state;
560 
561 	for (i = 0; i < POWERNOW_MAX_STATES; ++i)
562 		sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
563 
564 	for (n = 0, i = 0; i < npstates; ++i) {
565 		state.fid = *p++;
566 		state.vid = *p++;
567 		state.power = CPUFREQ_VAL_UNKNOWN;
568 
569 		switch (sc->pn_type) {
570 		case PN7_TYPE:
571 			state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
572 			if ((sc->errata & A0_ERRATA) &&
573 			    (pn7_fid_to_mult[state.fid] % 10) == 5)
574 				continue;
575 			break;
576 		case PN8_TYPE:
577 			state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
578 			break;
579 		}
580 
581 		j = n;
582 		while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
583 			memcpy(&sc->powernow_states[j],
584 			    &sc->powernow_states[j - 1],
585 			    sizeof(struct powernow_state));
586 			--j;
587 		}
588 		memcpy(&sc->powernow_states[j], &state,
589 		    sizeof(struct powernow_state));
590 		++n;
591 	}
592 
593 	/*
594 	 * Fix powernow_max_states, if errata a0 give us less states
595 	 * than expected.
596 	 */
597 	sc->powernow_max_states = n;
598 
599 	if (bootverbose)
600 		for (i = 0; i < sc->powernow_max_states; ++i) {
601 			int fid = sc->powernow_states[i].fid;
602 			int vid = sc->powernow_states[i].vid;
603 
604 			printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
605 			    i,
606 			    sc->powernow_states[i].freq,
607 			    fid,
608 			    vid);
609 		}
610 
611 	return (0);
612 }
613 
614 static int
615 cpuid_is_k7(u_int cpuid)
616 {
617 
618 	switch (cpuid) {
619 	case 0x760:
620 	case 0x761:
621 	case 0x762:
622 	case 0x770:
623 	case 0x771:
624 	case 0x780:
625 	case 0x781:
626 	case 0x7a0:
627 		return (TRUE);
628 	}
629 	return (FALSE);
630 }
631 
632 static int
633 pn_decode_pst(device_t dev)
634 {
635 	int maxpst;
636 	struct pn_softc *sc;
637 	u_int cpuid, maxfid, startvid;
638 	u_long sig;
639 	struct psb_header *psb;
640 	uint8_t *p;
641 	u_int regs[4];
642 	uint64_t status;
643 
644 	sc = device_get_softc(dev);
645 
646 	do_cpuid(0x80000001, regs);
647 	cpuid = regs[0];
648 
649 	if ((cpuid & 0xfff) == 0x760)
650 		sc->errata |= A0_ERRATA;
651 
652 	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
653 
654 	switch (sc->pn_type) {
655 	case PN7_TYPE:
656 		maxfid = PN7_STA_MFID(status);
657 		startvid = PN7_STA_SVID(status);
658 		break;
659 	case PN8_TYPE:
660 		maxfid = PN8_STA_MFID(status);
661 		/*
662 		 * we should actually use a variable named 'maxvid' if K8,
663 		 * but why introducing a new variable for that?
664 		 */
665 		startvid = PN8_STA_MVID(status);
666 		break;
667 	default:
668 		return (ENODEV);
669 	}
670 
671 	if (bootverbose) {
672 		device_printf(dev, "STATUS: 0x%jx\n", status);
673 		device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
674 		device_printf(dev, "STATUS: %s: 0x%02x\n",
675 		    sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
676 		    startvid);
677 	}
678 
679 	sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
680 	if (sig) {
681 		struct pst_header *pst;
682 
683 		psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
684 
685 		switch (psb->version) {
686 		default:
687 			return (ENODEV);
688 		case 0x14:
689 			/*
690 			 * We can't be picky about numpst since at least
691 			 * some systems have a value of 1 and some have 2.
692 			 * We trust that cpuid_is_k7() will be better at
693 			 * catching that we're on a K8 anyway.
694 			 */
695 			if (sc->pn_type != PN8_TYPE)
696 				return (EINVAL);
697 			sc->vst = psb->settlingtime;
698 			sc->rvo = PN8_PSB_TO_RVO(psb->res1);
699 			sc->irt = PN8_PSB_TO_IRT(psb->res1);
700 			sc->mvs = PN8_PSB_TO_MVS(psb->res1);
701 			sc->low = PN8_PSB_TO_BATT(psb->res1);
702 			if (bootverbose) {
703 				device_printf(dev, "PSB: VST: %d\n",
704 				    psb->settlingtime);
705 				device_printf(dev, "PSB: RVO %x IRT %d "
706 				    "MVS %d BATT %d\n",
707 				    sc->rvo,
708 				    sc->irt,
709 				    sc->mvs,
710 				    sc->low);
711 			}
712 			break;
713 		case 0x12:
714 			if (sc->pn_type != PN7_TYPE)
715 				return (EINVAL);
716 			sc->sgtc = psb->settlingtime * sc->fsb;
717 			if (sc->sgtc < 100 * sc->fsb)
718 				sc->sgtc = 100 * sc->fsb;
719 			break;
720 		}
721 
722 		p = ((uint8_t *) psb) + sizeof(struct psb_header);
723 		pst = (struct pst_header*) p;
724 
725 		maxpst = 200;
726 
727 		do {
728 			struct pst_header *pst = (struct pst_header*) p;
729 
730 			if (cpuid == pst->cpuid &&
731 			    maxfid == pst->maxfid &&
732 			    startvid == pst->startvid) {
733 				sc->powernow_max_states = pst->numpstates;
734 				switch (sc->pn_type) {
735 				case PN7_TYPE:
736 					if (abs(sc->fsb - pst->fsb) > 5)
737 						continue;
738 					break;
739 				case PN8_TYPE:
740 					break;
741 				}
742 				return (decode_pst(sc,
743 				    p + sizeof(struct pst_header),
744 				    sc->powernow_max_states));
745 			}
746 
747 			p += sizeof(struct pst_header) + (2 * pst->numpstates);
748 		} while (cpuid_is_k7(pst->cpuid) && maxpst--);
749 
750 		device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
751 	}
752 
753 	return (ENODEV);
754 }
755 
756 static int
757 pn_decode_acpi(device_t dev, device_t perf_dev)
758 {
759 	int i, j, n;
760 	uint64_t status;
761 	uint32_t ctrl;
762 	u_int cpuid;
763 	u_int regs[4];
764 	struct pn_softc *sc;
765 	struct powernow_state state;
766 	struct cf_setting sets[POWERNOW_MAX_STATES];
767 	int count = POWERNOW_MAX_STATES;
768 	int type;
769 	int rv;
770 
771 	if (perf_dev == NULL)
772 		return (ENXIO);
773 
774 	rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
775 	if (rv)
776 		return (ENXIO);
777 	rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
778 	if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
779 		return (ENXIO);
780 
781 	sc = device_get_softc(dev);
782 
783 	do_cpuid(0x80000001, regs);
784 	cpuid = regs[0];
785 	if ((cpuid & 0xfff) == 0x760)
786 		sc->errata |= A0_ERRATA;
787 
788 	ctrl = 0;
789 	sc->sgtc = 0;
790 	for (n = 0, i = 0; i < count; ++i) {
791 		ctrl = sets[i].spec[PX_SPEC_CONTROL];
792 		switch (sc->pn_type) {
793 		case PN7_TYPE:
794 			state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
795 			state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
796 			if ((sc->errata & A0_ERRATA) &&
797 			    (pn7_fid_to_mult[state.fid] % 10) == 5)
798 				continue;
799 			break;
800 		case PN8_TYPE:
801 			state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
802 			state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
803 			break;
804 		}
805 		state.freq = sets[i].freq * 1000;
806 		state.power = sets[i].power;
807 
808 		j = n;
809 		while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
810 			memcpy(&sc->powernow_states[j],
811 			    &sc->powernow_states[j - 1],
812 			    sizeof(struct powernow_state));
813 			--j;
814 		}
815 		memcpy(&sc->powernow_states[j], &state,
816 		    sizeof(struct powernow_state));
817 		++n;
818 	}
819 
820 	sc->powernow_max_states = n;
821 	state = sc->powernow_states[0];
822 	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
823 
824 	switch (sc->pn_type) {
825 	case PN7_TYPE:
826 		sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
827 		/*
828 		 * XXX Some bios forget the max frequency!
829 		 * This maybe indicates we have the wrong tables.  Therefore,
830 		 * don't implement a quirk, but fallback to BIOS legacy
831 		 * tables instead.
832 		 */
833 		if (PN7_STA_MFID(status) != state.fid) {
834 			device_printf(dev, "ACPI MAX frequency not found\n");
835 			return (EINVAL);
836 		}
837 		sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
838 		break;
839 	case PN8_TYPE:
840 		sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
841 		sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
842 		sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
843 		sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
844 		sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
845 		sc->low = 0; /* XXX */
846 
847 		/*
848 		 * powernow k8 supports only one low frequency.
849 		 */
850 		if (sc->powernow_max_states >= 2 &&
851 		    (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
852 			return (EINVAL);
853 		sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
854 		break;
855 	}
856 
857 	return (0);
858 }
859 
860 static void
861 pn_identify(driver_t *driver, device_t parent)
862 {
863 
864 	if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
865 		return;
866 	switch (cpu_id & 0xf00) {
867 	case 0x600:
868 	case 0xf00:
869 		break;
870 	default:
871 		return;
872 	}
873 	if (device_find_child(parent, "powernow", -1) != NULL)
874 		return;
875 	if (BUS_ADD_CHILD(parent, 10, "powernow", device_get_unit(parent))
876 	    == NULL)
877 		device_printf(parent, "powernow: add child failed\n");
878 }
879 
880 static int
881 pn_probe(device_t dev)
882 {
883 	struct pn_softc *sc;
884 	uint64_t status;
885 	uint64_t rate;
886 	struct pcpu *pc;
887 	u_int sfid, mfid, cfid;
888 
889 	sc = device_get_softc(dev);
890 	sc->errata = 0;
891 	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
892 
893 	pc = cpu_get_pcpu(dev);
894 	if (pc == NULL)
895 		return (ENODEV);
896 
897 	cpu_est_clockrate(pc->pc_cpuid, &rate);
898 
899 	switch (cpu_id & 0xf00) {
900 	case 0x600:
901 		sfid = PN7_STA_SFID(status);
902 		mfid = PN7_STA_MFID(status);
903 		cfid = PN7_STA_CFID(status);
904 		sc->pn_type = PN7_TYPE;
905 		sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];
906 
907 		/*
908 		 * If start FID is different to max FID, then it is a
909 		 * mobile processor.  If not, it is a low powered desktop
910 		 * processor.
911 		 */
912 		if (sfid != mfid) {
913 			sc->vid_to_volts = pn7_mobile_vid_to_volts;
914 			device_set_desc(dev, "PowerNow! K7");
915 		} else {
916 			sc->vid_to_volts = pn7_desktop_vid_to_volts;
917 			device_set_desc(dev, "Cool`n'Quiet K7");
918 		}
919 		break;
920 
921 	case 0xf00:
922 		sfid = PN8_STA_SFID(status);
923 		mfid = PN8_STA_MFID(status);
924 		cfid = PN8_STA_CFID(status);
925 		sc->pn_type = PN8_TYPE;
926 		sc->vid_to_volts = pn8_vid_to_volts;
927 		sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid];
928 
929 		if (sfid != mfid)
930 			device_set_desc(dev, "PowerNow! K8");
931 		else
932 			device_set_desc(dev, "Cool`n'Quiet K8");
933 		break;
934 	default:
935 		return (ENODEV);
936 	}
937 
938 	return (0);
939 }
940 
941 static int
942 pn_attach(device_t dev)
943 {
944 	int rv;
945 	device_t child;
946 
947 	child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
948 	if (child) {
949 		rv = pn_decode_acpi(dev, child);
950 		if (rv)
951 			rv = pn_decode_pst(dev);
952 	} else
953 		rv = pn_decode_pst(dev);
954 
955 	if (rv != 0)
956 		return (ENXIO);
957 	cpufreq_register(dev);
958 	return (0);
959 }
960 
961 static int
962 pn_detach(device_t dev)
963 {
964 
965 	return (cpufreq_unregister(dev));
966 }
967