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
76struct 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
85struct 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 */
164static 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
171static 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) */
186static 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) */
193static 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) */
200static 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
209struct powernow_state {
210	int freq;
211	int power;
212	int fid;
213	int vid;
214};
215
216struct 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
241static void	pn_identify(driver_t *driver, device_t parent);
242static int	pn_probe(device_t dev);
243static int	pn_attach(device_t dev);
244static int	pn_detach(device_t dev);
245static int	pn_set(device_t dev, const struct cf_setting *cf);
246static int	pn_get(device_t dev, struct cf_setting *cf);
247static int	pn_settings(device_t dev, struct cf_setting *sets,
248		    int *count);
249static int	pn_type(device_t dev, int *type);
250
251static 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
266static devclass_t pn_devclass;
267static driver_t pn_driver = {
268	"powernow",
269	pn_methods,
270	sizeof(struct pn_softc),
271};
272
273DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
274
275static int
276pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
277{
278	int cfid, cvid;
279	uint64_t status, ctl;
280
281	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
282	cfid = PN7_STA_CFID(status);
283	cvid = PN7_STA_CVID(status);
284
285	/* We're already at the requested level. */
286	if (fid == cfid && vid == cvid)
287		return (0);
288
289	ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
290
291	ctl |= PN7_CTR_FID(fid);
292	ctl |= PN7_CTR_VID(vid);
293	ctl |= PN7_CTR_SGTC(sc->sgtc);
294
295	if (sc->errata & A0_ERRATA)
296		disable_intr();
297
298	if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
299		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
300		if (vid != cvid)
301			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
302	} else {
303		wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
304		if (fid != cfid)
305			wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
306	}
307
308	if (sc->errata & A0_ERRATA)
309		enable_intr();
310
311	return (0);
312}
313
314static int
315pn8_read_pending_wait(uint64_t *status)
316{
317	int i = 10000;
318
319	do
320		*status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
321	while (PN8_STA_PENDING(*status) && --i);
322
323	return (i == 0 ? ENXIO : 0);
324}
325
326static int
327pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
328{
329	int i = 100;
330
331	do
332		WRITE_FIDVID(fid, vid, ctrl);
333	while (pn8_read_pending_wait(status) && --i);
334
335	return (i == 0 ? ENXIO : 0);
336}
337
338static int
339pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
340{
341	uint64_t status;
342	int cfid, cvid;
343	int rvo;
344	int rv;
345	u_int val;
346
347	rv = pn8_read_pending_wait(&status);
348	if (rv)
349		return (rv);
350
351	cfid = PN8_STA_CFID(status);
352	cvid = PN8_STA_CVID(status);
353
354	if (fid == cfid && vid == cvid)
355		return (0);
356
357	/*
358	 * Phase 1: Raise core voltage to requested VID if frequency is
359	 * going up.
360	 */
361	while (cvid > vid) {
362		val = cvid - (1 << sc->mvs);
363		rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
364		if (rv) {
365			sc->errata |= PENDING_STUCK;
366			return (rv);
367		}
368		cvid = PN8_STA_CVID(status);
369		COUNT_OFF_VST(sc->vst);
370	}
371
372	/* ... then raise to voltage + RVO (if required) */
373	for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
374		/* XXX It's not clear from spec if we have to do that
375		 * in 0.25 step or in MVS.  Therefore do it as it's done
376		 * under Linux */
377		rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
378		if (rv) {
379			sc->errata |= PENDING_STUCK;
380			return (rv);
381		}
382		cvid = PN8_STA_CVID(status);
383		COUNT_OFF_VST(sc->vst);
384	}
385
386	/* Phase 2: change to requested core frequency */
387	if (cfid != fid) {
388		u_int vco_fid, vco_cfid, fid_delta;
389
390		vco_fid = FID_TO_VCO_FID(fid);
391		vco_cfid = FID_TO_VCO_FID(cfid);
392
393		while (abs(vco_fid - vco_cfid) > 2) {
394			fid_delta = (vco_cfid & 1) ? 1 : 2;
395			if (fid > cfid) {
396				if (cfid > 7)
397					val = cfid + fid_delta;
398				else
399					val = FID_TO_VCO_FID(cfid) + fid_delta;
400			} else
401				val = cfid - fid_delta;
402			rv = pn8_write_fidvid(val, cvid,
403			    sc->pll * (uint64_t) sc->fsb,
404			    &status);
405			if (rv) {
406				sc->errata |= PENDING_STUCK;
407				return (rv);
408			}
409			cfid = PN8_STA_CFID(status);
410			COUNT_OFF_IRT(sc->irt);
411
412			vco_cfid = FID_TO_VCO_FID(cfid);
413		}
414
415		rv = pn8_write_fidvid(fid, cvid,
416		    sc->pll * (uint64_t) sc->fsb,
417		    &status);
418		if (rv) {
419			sc->errata |= PENDING_STUCK;
420			return (rv);
421		}
422		cfid = PN8_STA_CFID(status);
423		COUNT_OFF_IRT(sc->irt);
424	}
425
426	/* Phase 3: change to requested voltage */
427	if (cvid != vid) {
428		rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
429		cvid = PN8_STA_CVID(status);
430		COUNT_OFF_VST(sc->vst);
431	}
432
433	/* Check if transition failed. */
434	if (cfid != fid || cvid != vid)
435		rv = ENXIO;
436
437	return (rv);
438}
439
440static int
441pn_set(device_t dev, const struct cf_setting *cf)
442{
443	struct pn_softc *sc;
444	int fid, vid;
445	int i;
446	int rv;
447
448	if (cf == NULL)
449		return (EINVAL);
450	sc = device_get_softc(dev);
451
452	if (sc->errata & PENDING_STUCK)
453		return (ENXIO);
454
455	for (i = 0; i < sc->powernow_max_states; ++i)
456		if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
457			break;
458
459	fid = sc->powernow_states[i].fid;
460	vid = sc->powernow_states[i].vid;
461
462	rv = ENODEV;
463
464	switch (sc->pn_type) {
465	case PN7_TYPE:
466		rv = pn7_setfidvid(sc, fid, vid);
467		break;
468	case PN8_TYPE:
469		rv = pn8_setfidvid(sc, fid, vid);
470		break;
471	}
472
473	return (rv);
474}
475
476static int
477pn_get(device_t dev, struct cf_setting *cf)
478{
479	struct pn_softc *sc;
480	u_int cfid = 0, cvid = 0;
481	int i;
482	uint64_t status;
483
484	if (cf == NULL)
485		return (EINVAL);
486	sc = device_get_softc(dev);
487	if (sc->errata & PENDING_STUCK)
488		return (ENXIO);
489
490	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
491
492	switch (sc->pn_type) {
493	case PN7_TYPE:
494		cfid = PN7_STA_CFID(status);
495		cvid = PN7_STA_CVID(status);
496		break;
497	case PN8_TYPE:
498		cfid = PN8_STA_CFID(status);
499		cvid = PN8_STA_CVID(status);
500		break;
501	}
502	for (i = 0; i < sc->powernow_max_states; ++i)
503		if (cfid == sc->powernow_states[i].fid &&
504		    cvid == sc->powernow_states[i].vid)
505			break;
506
507	if (i < sc->powernow_max_states) {
508		cf->freq = sc->powernow_states[i].freq / 1000;
509		cf->power = sc->powernow_states[i].power;
510		cf->lat = 200;
511		cf->volts = sc->vid_to_volts[cvid];
512		cf->dev = dev;
513	} else {
514		memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
515		cf->dev = NULL;
516	}
517
518	return (0);
519}
520
521static int
522pn_settings(device_t dev, struct cf_setting *sets, int *count)
523{
524	struct pn_softc *sc;
525	int i;
526
527	if (sets == NULL|| count == NULL)
528		return (EINVAL);
529	sc = device_get_softc(dev);
530	if (*count < sc->powernow_max_states)
531		return (E2BIG);
532	for (i = 0; i < sc->powernow_max_states; ++i) {
533		sets[i].freq = sc->powernow_states[i].freq / 1000;
534		sets[i].power = sc->powernow_states[i].power;
535		sets[i].lat = 200;
536		sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
537		sets[i].dev = dev;
538	}
539	*count = sc->powernow_max_states;
540
541	return (0);
542}
543
544static int
545pn_type(device_t dev, int *type)
546{
547	if (type == NULL)
548		return (EINVAL);
549
550	*type = CPUFREQ_TYPE_ABSOLUTE;
551
552	return (0);
553}
554
555/*
556 * Given a set of pair of fid/vid, and number of performance states,
557 * compute powernow_states via an insertion sort.
558 */
559static int
560decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
561{
562	int i, j, n;
563	struct powernow_state state;
564
565	for (i = 0; i < POWERNOW_MAX_STATES; ++i)
566		sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
567
568	for (n = 0, i = 0; i < npstates; ++i) {
569		state.fid = *p++;
570		state.vid = *p++;
571		state.power = CPUFREQ_VAL_UNKNOWN;
572
573		switch (sc->pn_type) {
574		case PN7_TYPE:
575			state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
576			if ((sc->errata & A0_ERRATA) &&
577			    (pn7_fid_to_mult[state.fid] % 10) == 5)
578				continue;
579			break;
580		case PN8_TYPE:
581			state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
582			break;
583		}
584
585		j = n;
586		while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
587			memcpy(&sc->powernow_states[j],
588			    &sc->powernow_states[j - 1],
589			    sizeof(struct powernow_state));
590			--j;
591		}
592		memcpy(&sc->powernow_states[j], &state,
593		    sizeof(struct powernow_state));
594		++n;
595	}
596
597	/*
598	 * Fix powernow_max_states, if errata a0 give us less states
599	 * than expected.
600	 */
601	sc->powernow_max_states = n;
602
603	if (bootverbose)
604		for (i = 0; i < sc->powernow_max_states; ++i) {
605			int fid = sc->powernow_states[i].fid;
606			int vid = sc->powernow_states[i].vid;
607
608			printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
609			    i,
610			    sc->powernow_states[i].freq,
611			    fid,
612			    vid);
613		}
614
615	return (0);
616}
617
618static int
619cpuid_is_k7(u_int cpuid)
620{
621
622	switch (cpuid) {
623	case 0x760:
624	case 0x761:
625	case 0x762:
626	case 0x770:
627	case 0x771:
628	case 0x780:
629	case 0x781:
630	case 0x7a0:
631		return (TRUE);
632	}
633	return (FALSE);
634}
635
636static int
637pn_decode_pst(device_t dev)
638{
639	int maxpst;
640	struct pn_softc *sc;
641	u_int cpuid, maxfid, startvid;
642	u_long sig;
643	struct psb_header *psb;
644	uint8_t *p;
645	u_int regs[4];
646	uint64_t status;
647
648	sc = device_get_softc(dev);
649
650	do_cpuid(0x80000001, regs);
651	cpuid = regs[0];
652
653	if ((cpuid & 0xfff) == 0x760)
654		sc->errata |= A0_ERRATA;
655
656	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
657
658	switch (sc->pn_type) {
659	case PN7_TYPE:
660		maxfid = PN7_STA_MFID(status);
661		startvid = PN7_STA_SVID(status);
662		break;
663	case PN8_TYPE:
664		maxfid = PN8_STA_MFID(status);
665		/*
666		 * we should actually use a variable named 'maxvid' if K8,
667		 * but why introducing a new variable for that?
668		 */
669		startvid = PN8_STA_MVID(status);
670		break;
671	default:
672		return (ENODEV);
673	}
674
675	if (bootverbose) {
676		device_printf(dev, "STATUS: 0x%jx\n", status);
677		device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
678		device_printf(dev, "STATUS: %s: 0x%02x\n",
679		    sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
680		    startvid);
681	}
682
683	sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
684	if (sig) {
685		struct pst_header *pst;
686
687		psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
688
689		switch (psb->version) {
690		default:
691			return (ENODEV);
692		case 0x14:
693			/*
694			 * We can't be picky about numpst since at least
695			 * some systems have a value of 1 and some have 2.
696			 * We trust that cpuid_is_k7() will be better at
697			 * catching that we're on a K8 anyway.
698			 */
699			if (sc->pn_type != PN8_TYPE)
700				return (EINVAL);
701			sc->vst = psb->settlingtime;
702			sc->rvo = PN8_PSB_TO_RVO(psb->res1);
703			sc->irt = PN8_PSB_TO_IRT(psb->res1);
704			sc->mvs = PN8_PSB_TO_MVS(psb->res1);
705			sc->low = PN8_PSB_TO_BATT(psb->res1);
706			if (bootverbose) {
707				device_printf(dev, "PSB: VST: %d\n",
708				    psb->settlingtime);
709				device_printf(dev, "PSB: RVO %x IRT %d "
710				    "MVS %d BATT %d\n",
711				    sc->rvo,
712				    sc->irt,
713				    sc->mvs,
714				    sc->low);
715			}
716			break;
717		case 0x12:
718			if (sc->pn_type != PN7_TYPE)
719				return (EINVAL);
720			sc->sgtc = psb->settlingtime * sc->fsb;
721			if (sc->sgtc < 100 * sc->fsb)
722				sc->sgtc = 100 * sc->fsb;
723			break;
724		}
725
726		p = ((uint8_t *) psb) + sizeof(struct psb_header);
727		pst = (struct pst_header*) p;
728
729		maxpst = 200;
730
731		do {
732			struct pst_header *pst = (struct pst_header*) p;
733
734			if (cpuid == pst->cpuid &&
735			    maxfid == pst->maxfid &&
736			    startvid == pst->startvid) {
737				sc->powernow_max_states = pst->numpstates;
738				switch (sc->pn_type) {
739				case PN7_TYPE:
740					if (abs(sc->fsb - pst->fsb) > 5)
741						continue;
742					break;
743				case PN8_TYPE:
744					break;
745				}
746				return (decode_pst(sc,
747				    p + sizeof(struct pst_header),
748				    sc->powernow_max_states));
749			}
750
751			p += sizeof(struct pst_header) + (2 * pst->numpstates);
752		} while (cpuid_is_k7(pst->cpuid) && maxpst--);
753
754		device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
755	}
756
757	return (ENODEV);
758}
759
760static int
761pn_decode_acpi(device_t dev, device_t perf_dev)
762{
763	int i, j, n;
764	uint64_t status;
765	uint32_t ctrl;
766	u_int cpuid;
767	u_int regs[4];
768	struct pn_softc *sc;
769	struct powernow_state state;
770	struct cf_setting sets[POWERNOW_MAX_STATES];
771	int count = POWERNOW_MAX_STATES;
772	int type;
773	int rv;
774
775	if (perf_dev == NULL)
776		return (ENXIO);
777
778	rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
779	if (rv)
780		return (ENXIO);
781	rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
782	if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
783		return (ENXIO);
784
785	sc = device_get_softc(dev);
786
787	do_cpuid(0x80000001, regs);
788	cpuid = regs[0];
789	if ((cpuid & 0xfff) == 0x760)
790		sc->errata |= A0_ERRATA;
791
792	ctrl = 0;
793	sc->sgtc = 0;
794	for (n = 0, i = 0; i < count; ++i) {
795		ctrl = sets[i].spec[PX_SPEC_CONTROL];
796		switch (sc->pn_type) {
797		case PN7_TYPE:
798			state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
799			state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
800			if ((sc->errata & A0_ERRATA) &&
801			    (pn7_fid_to_mult[state.fid] % 10) == 5)
802				continue;
803			break;
804		case PN8_TYPE:
805			state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
806			state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
807			break;
808		}
809		state.freq = sets[i].freq * 1000;
810		state.power = sets[i].power;
811
812		j = n;
813		while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
814			memcpy(&sc->powernow_states[j],
815			    &sc->powernow_states[j - 1],
816			    sizeof(struct powernow_state));
817			--j;
818		}
819		memcpy(&sc->powernow_states[j], &state,
820		    sizeof(struct powernow_state));
821		++n;
822	}
823
824	sc->powernow_max_states = n;
825	state = sc->powernow_states[0];
826	status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
827
828	switch (sc->pn_type) {
829	case PN7_TYPE:
830		sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
831		/*
832		 * XXX Some bios forget the max frequency!
833		 * This maybe indicates we have the wrong tables.  Therefore,
834		 * don't implement a quirk, but fallback to BIOS legacy
835		 * tables instead.
836		 */
837		if (PN7_STA_MFID(status) != state.fid) {
838			device_printf(dev, "ACPI MAX frequency not found\n");
839			return (EINVAL);
840		}
841		sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
842		break;
843	case PN8_TYPE:
844		sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
845		sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
846		sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
847		sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
848		sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
849		sc->low = 0; /* XXX */
850
851		/*
852		 * powernow k8 supports only one low frequency.
853		 */
854		if (sc->powernow_max_states >= 2 &&
855		    (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
856			return (EINVAL);
857		sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
858		break;
859	}
860
861	return (0);
862}
863
864static void
865pn_identify(driver_t *driver, device_t parent)
866{
867
868	if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
869		return;
870	switch (cpu_id & 0xf00) {
871	case 0x600:
872	case 0xf00:
873		break;
874	default:
875		return;
876	}
877	if (device_find_child(parent, "powernow", -1) != NULL)
878		return;
879	if (BUS_ADD_CHILD(parent, 10, "powernow", -1) == NULL)
880		device_printf(parent, "powernow: add child failed\n");
881}
882
883static int
884pn_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 (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
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 (PN8_STA_SFID(status) != PN8_STA_MFID(status))
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
944static int
945pn_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
964static int
965pn_detach(device_t dev)
966{
967
968	return (cpufreq_unregister(dev));
969}
970