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