2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2004-2005 Bruno Ducrot
5 * Copyright (c) 2004 FUKUDA Nobuhiko <nfukuda@spa.is.uec.ac.jp>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
29 * Many thanks to Nate Lawson for his helpful comments on this driver and
30 * to Jung-uk Kim for testing.
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
36 #include <sys/param.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
43 #include <sys/systm.h>
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>
55 #include "cpufreq_if.h"
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 :( */
69 /* Legacy configuration via BIOS table PSB. */
72 #define PSB_SIG "AMDK7PNOW!"
80 uint16_t settlingtime;
94 * MSRs and bits used by Powernow technology
96 #define MSR_AMDK7_FIDVID_CTL 0xc0010041
97 #define MSR_AMDK7_FIDVID_STATUS 0xc0010042
99 /* Bitfields used by K7 */
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)
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)
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)
120 /* Bitfields used by K8 */
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)
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)
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)
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)
150 #define WRITE_FIDVID(fid, vid, ctrl) \
151 wrmsr(MSR_AMDK7_FIDVID_CTL, \
152 (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
154 #define COUNT_OFF_IRT(irt) DELAY(10 * (1 << (irt)))
155 #define COUNT_OFF_VST(vst) DELAY(20 * (vst))
157 #define FID_TO_VCO_FID(fid) \
158 (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
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.
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,
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,
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,
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,
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,
209 #define POWERNOW_MAX_STATES 16
211 struct powernow_state {
221 struct powernow_state powernow_states[POWERNOW_MAX_STATES];
230 int powernow_max_states;
231 u_int powernow_state;
237 * Offsets in struct cf_setting array for private values given by
240 #define PX_SPEC_CONTROL 0
241 #define PX_SPEC_STATUS 1
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,
251 static int pn_type(device_t dev, int *type);
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),
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),
269 static devclass_t pn_devclass;
270 static driver_t pn_driver = {
273 sizeof(struct pn_softc),
276 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
279 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
282 uint64_t status, ctl;
284 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
285 cfid = PN7_STA_CFID(status);
286 cvid = PN7_STA_CVID(status);
288 /* We're already at the requested level. */
289 if (fid == cfid && vid == cvid)
292 ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
294 ctl |= PN7_CTR_FID(fid);
295 ctl |= PN7_CTR_VID(vid);
296 ctl |= PN7_CTR_SGTC(sc->sgtc);
298 if (sc->errata & A0_ERRATA)
301 if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
302 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
304 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
306 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
308 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
311 if (sc->errata & A0_ERRATA)
318 pn8_read_pending_wait(uint64_t *status)
323 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
324 while (PN8_STA_PENDING(*status) && --i);
326 return (i == 0 ? ENXIO : 0);
330 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
335 WRITE_FIDVID(fid, vid, ctrl);
336 while (pn8_read_pending_wait(status) && --i);
338 return (i == 0 ? ENXIO : 0);
342 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
350 rv = pn8_read_pending_wait(&status);
354 cfid = PN8_STA_CFID(status);
355 cvid = PN8_STA_CVID(status);
357 if (fid == cfid && vid == cvid)
361 * Phase 1: Raise core voltage to requested VID if frequency is
365 val = cvid - (1 << sc->mvs);
366 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
368 sc->errata |= PENDING_STUCK;
371 cvid = PN8_STA_CVID(status);
372 COUNT_OFF_VST(sc->vst);
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
380 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
382 sc->errata |= PENDING_STUCK;
385 cvid = PN8_STA_CVID(status);
386 COUNT_OFF_VST(sc->vst);
389 /* Phase 2: change to requested core frequency */
391 u_int vco_fid, vco_cfid, fid_delta;
393 vco_fid = FID_TO_VCO_FID(fid);
394 vco_cfid = FID_TO_VCO_FID(cfid);
396 while (abs(vco_fid - vco_cfid) > 2) {
397 fid_delta = (vco_cfid & 1) ? 1 : 2;
400 val = cfid + fid_delta;
402 val = FID_TO_VCO_FID(cfid) + fid_delta;
404 val = cfid - fid_delta;
405 rv = pn8_write_fidvid(val, cvid,
406 sc->pll * (uint64_t) sc->fsb,
409 sc->errata |= PENDING_STUCK;
412 cfid = PN8_STA_CFID(status);
413 COUNT_OFF_IRT(sc->irt);
415 vco_cfid = FID_TO_VCO_FID(cfid);
418 rv = pn8_write_fidvid(fid, cvid,
419 sc->pll * (uint64_t) sc->fsb,
422 sc->errata |= PENDING_STUCK;
425 cfid = PN8_STA_CFID(status);
426 COUNT_OFF_IRT(sc->irt);
429 /* Phase 3: change to requested voltage */
431 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
432 cvid = PN8_STA_CVID(status);
433 COUNT_OFF_VST(sc->vst);
436 /* Check if transition failed. */
437 if (cfid != fid || cvid != vid)
444 pn_set(device_t dev, const struct cf_setting *cf)
453 sc = device_get_softc(dev);
455 if (sc->errata & PENDING_STUCK)
458 for (i = 0; i < sc->powernow_max_states; ++i)
459 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
462 fid = sc->powernow_states[i].fid;
463 vid = sc->powernow_states[i].vid;
467 switch (sc->pn_type) {
469 rv = pn7_setfidvid(sc, fid, vid);
472 rv = pn8_setfidvid(sc, fid, vid);
480 pn_get(device_t dev, struct cf_setting *cf)
483 u_int cfid = 0, cvid = 0;
489 sc = device_get_softc(dev);
490 if (sc->errata & PENDING_STUCK)
493 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
495 switch (sc->pn_type) {
497 cfid = PN7_STA_CFID(status);
498 cvid = PN7_STA_CVID(status);
501 cfid = PN8_STA_CFID(status);
502 cvid = PN8_STA_CVID(status);
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)
510 if (i < sc->powernow_max_states) {
511 cf->freq = sc->powernow_states[i].freq / 1000;
512 cf->power = sc->powernow_states[i].power;
514 cf->volts = sc->vid_to_volts[cvid];
517 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
525 pn_settings(device_t dev, struct cf_setting *sets, int *count)
530 if (sets == NULL|| count == NULL)
532 sc = device_get_softc(dev);
533 if (*count < sc->powernow_max_states)
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;
539 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
542 *count = sc->powernow_max_states;
548 pn_type(device_t dev, int *type)
553 *type = CPUFREQ_TYPE_ABSOLUTE;
559 * Given a set of pair of fid/vid, and number of performance states,
560 * compute powernow_states via an insertion sort.
563 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
566 struct powernow_state state;
568 for (i = 0; i < POWERNOW_MAX_STATES; ++i)
569 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
571 for (n = 0, i = 0; i < npstates; ++i) {
574 state.power = CPUFREQ_VAL_UNKNOWN;
576 switch (sc->pn_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)
584 state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
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));
595 memcpy(&sc->powernow_states[j], &state,
596 sizeof(struct powernow_state));
601 * Fix powernow_max_states, if errata a0 give us less states
604 sc->powernow_max_states = n;
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;
611 printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
613 sc->powernow_states[i].freq,
622 cpuid_is_k7(u_int cpuid)
640 pn_decode_pst(device_t dev)
644 u_int cpuid, maxfid, startvid;
646 struct psb_header *psb;
651 sc = device_get_softc(dev);
653 do_cpuid(0x80000001, regs);
656 if ((cpuid & 0xfff) == 0x760)
657 sc->errata |= A0_ERRATA;
659 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
661 switch (sc->pn_type) {
663 maxfid = PN7_STA_MFID(status);
664 startvid = PN7_STA_SVID(status);
667 maxfid = PN8_STA_MFID(status);
669 * we should actually use a variable named 'maxvid' if K8,
670 * but why introducing a new variable for that?
672 startvid = PN8_STA_MVID(status);
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",
686 sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
688 struct pst_header *pst;
690 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
692 switch (psb->version) {
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.
702 if (sc->pn_type != PN8_TYPE)
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);
710 device_printf(dev, "PSB: VST: %d\n",
712 device_printf(dev, "PSB: RVO %x IRT %d "
721 if (sc->pn_type != PN7_TYPE)
723 sc->sgtc = psb->settlingtime * sc->fsb;
724 if (sc->sgtc < 100 * sc->fsb)
725 sc->sgtc = 100 * sc->fsb;
729 p = ((uint8_t *) psb) + sizeof(struct psb_header);
730 pst = (struct pst_header*) p;
735 struct pst_header *pst = (struct pst_header*) p;
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) {
743 if (abs(sc->fsb - pst->fsb) > 5)
749 return (decode_pst(sc,
750 p + sizeof(struct pst_header),
751 sc->powernow_max_states));
754 p += sizeof(struct pst_header) + (2 * pst->numpstates);
755 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
757 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
764 pn_decode_acpi(device_t dev, device_t perf_dev)
772 struct powernow_state state;
773 struct cf_setting sets[POWERNOW_MAX_STATES];
774 int count = POWERNOW_MAX_STATES;
778 if (perf_dev == NULL)
781 rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
784 rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
785 if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
788 sc = device_get_softc(dev);
790 do_cpuid(0x80000001, regs);
792 if ((cpuid & 0xfff) == 0x760)
793 sc->errata |= A0_ERRATA;
797 for (n = 0, i = 0; i < count; ++i) {
798 ctrl = sets[i].spec[PX_SPEC_CONTROL];
799 switch (sc->pn_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)
808 state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
809 state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
812 state.freq = sets[i].freq * 1000;
813 state.power = sets[i].power;
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));
822 memcpy(&sc->powernow_states[j], &state,
823 sizeof(struct powernow_state));
827 sc->powernow_max_states = n;
828 state = sc->powernow_states[0];
829 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
831 switch (sc->pn_type) {
833 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
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
840 if (PN7_STA_MFID(status) != state.fid) {
841 device_printf(dev, "ACPI MAX frequency not found\n");
844 sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
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 */
855 * powernow k8 supports only one low frequency.
857 if (sc->powernow_max_states >= 2 &&
858 (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
860 sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
868 pn_identify(driver_t *driver, device_t parent)
871 if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
873 switch (cpu_id & 0xf00) {
880 if (device_find_child(parent, "powernow", -1) != NULL)
882 if (BUS_ADD_CHILD(parent, 10, "powernow", -1) == NULL)
883 device_printf(parent, "powernow: add child failed\n");
887 pn_probe(device_t dev)
893 u_int sfid, mfid, cfid;
895 sc = device_get_softc(dev);
897 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
899 pc = cpu_get_pcpu(dev);
903 cpu_est_clockrate(pc->pc_cpuid, &rate);
905 switch (cpu_id & 0xf00) {
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];
914 * If start FID is different to max FID, then it is a
915 * mobile processor. If not, it is a low powered desktop
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");
922 sc->vid_to_volts = pn7_desktop_vid_to_volts;
923 device_set_desc(dev, "Cool`n'Quiet K7");
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];
935 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
936 device_set_desc(dev, "PowerNow! K8");
938 device_set_desc(dev, "Cool`n'Quiet K8");
948 pn_attach(device_t dev)
953 child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
955 rv = pn_decode_acpi(dev, child);
957 rv = pn_decode_pst(dev);
959 rv = pn_decode_pst(dev);
963 cpufreq_register(dev);
968 pn_detach(device_t dev)
971 return (cpufreq_unregister(dev));