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