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)
149 #define WRITE_FIDVID(fid, vid, ctrl) \
150 wrmsr(MSR_AMDK7_FIDVID_CTL, \
151 (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
153 #define COUNT_OFF_IRT(irt) DELAY(10 * (1 << (irt)))
154 #define COUNT_OFF_VST(vst) DELAY(20 * (vst))
156 #define FID_TO_VCO_FID(fid) \
157 (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
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.
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,
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,
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,
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,
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,
207 #define POWERNOW_MAX_STATES 16
209 struct powernow_state {
219 struct powernow_state powernow_states[POWERNOW_MAX_STATES];
228 int powernow_max_states;
229 u_int powernow_state;
235 * Offsets in struct cf_setting array for private values given by
238 #define PX_SPEC_CONTROL 0
239 #define PX_SPEC_STATUS 1
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,
249 static int pn_type(device_t dev, int *type);
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),
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),
266 static devclass_t pn_devclass;
267 static driver_t pn_driver = {
270 sizeof(struct pn_softc),
273 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
276 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
279 uint64_t status, ctl;
281 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
282 cfid = PN7_STA_CFID(status);
283 cvid = PN7_STA_CVID(status);
285 /* We're already at the requested level. */
286 if (fid == cfid && vid == cvid)
289 ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
291 ctl |= PN7_CTR_FID(fid);
292 ctl |= PN7_CTR_VID(vid);
293 ctl |= PN7_CTR_SGTC(sc->sgtc);
295 if (sc->errata & A0_ERRATA)
298 if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
299 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
301 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
303 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
305 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
308 if (sc->errata & A0_ERRATA)
315 pn8_read_pending_wait(uint64_t *status)
320 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
321 while (PN8_STA_PENDING(*status) && --i);
323 return (i == 0 ? ENXIO : 0);
327 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
332 WRITE_FIDVID(fid, vid, ctrl);
333 while (pn8_read_pending_wait(status) && --i);
335 return (i == 0 ? ENXIO : 0);
339 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
347 rv = pn8_read_pending_wait(&status);
351 cfid = PN8_STA_CFID(status);
352 cvid = PN8_STA_CVID(status);
354 if (fid == cfid && vid == cvid)
358 * Phase 1: Raise core voltage to requested VID if frequency is
362 val = cvid - (1 << sc->mvs);
363 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
365 sc->errata |= PENDING_STUCK;
368 cvid = PN8_STA_CVID(status);
369 COUNT_OFF_VST(sc->vst);
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
377 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
379 sc->errata |= PENDING_STUCK;
382 cvid = PN8_STA_CVID(status);
383 COUNT_OFF_VST(sc->vst);
386 /* Phase 2: change to requested core frequency */
388 u_int vco_fid, vco_cfid, fid_delta;
390 vco_fid = FID_TO_VCO_FID(fid);
391 vco_cfid = FID_TO_VCO_FID(cfid);
393 while (abs(vco_fid - vco_cfid) > 2) {
394 fid_delta = (vco_cfid & 1) ? 1 : 2;
397 val = cfid + fid_delta;
399 val = FID_TO_VCO_FID(cfid) + fid_delta;
401 val = cfid - fid_delta;
402 rv = pn8_write_fidvid(val, cvid,
403 sc->pll * (uint64_t) sc->fsb,
406 sc->errata |= PENDING_STUCK;
409 cfid = PN8_STA_CFID(status);
410 COUNT_OFF_IRT(sc->irt);
412 vco_cfid = FID_TO_VCO_FID(cfid);
415 rv = pn8_write_fidvid(fid, cvid,
416 sc->pll * (uint64_t) sc->fsb,
419 sc->errata |= PENDING_STUCK;
422 cfid = PN8_STA_CFID(status);
423 COUNT_OFF_IRT(sc->irt);
426 /* Phase 3: change to requested voltage */
428 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
429 cvid = PN8_STA_CVID(status);
430 COUNT_OFF_VST(sc->vst);
433 /* Check if transition failed. */
434 if (cfid != fid || cvid != vid)
441 pn_set(device_t dev, const struct cf_setting *cf)
450 sc = device_get_softc(dev);
452 if (sc->errata & PENDING_STUCK)
455 for (i = 0; i < sc->powernow_max_states; ++i)
456 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
459 fid = sc->powernow_states[i].fid;
460 vid = sc->powernow_states[i].vid;
464 switch (sc->pn_type) {
466 rv = pn7_setfidvid(sc, fid, vid);
469 rv = pn8_setfidvid(sc, fid, vid);
477 pn_get(device_t dev, struct cf_setting *cf)
480 u_int cfid = 0, cvid = 0;
486 sc = device_get_softc(dev);
487 if (sc->errata & PENDING_STUCK)
490 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
492 switch (sc->pn_type) {
494 cfid = PN7_STA_CFID(status);
495 cvid = PN7_STA_CVID(status);
498 cfid = PN8_STA_CFID(status);
499 cvid = PN8_STA_CVID(status);
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)
507 if (i < sc->powernow_max_states) {
508 cf->freq = sc->powernow_states[i].freq / 1000;
509 cf->power = sc->powernow_states[i].power;
511 cf->volts = sc->vid_to_volts[cvid];
514 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
522 pn_settings(device_t dev, struct cf_setting *sets, int *count)
527 if (sets == NULL|| count == NULL)
529 sc = device_get_softc(dev);
530 if (*count < sc->powernow_max_states)
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;
536 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
539 *count = sc->powernow_max_states;
545 pn_type(device_t dev, int *type)
550 *type = CPUFREQ_TYPE_ABSOLUTE;
556 * Given a set of pair of fid/vid, and number of performance states,
557 * compute powernow_states via an insertion sort.
560 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
563 struct powernow_state state;
565 for (i = 0; i < POWERNOW_MAX_STATES; ++i)
566 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
568 for (n = 0, i = 0; i < npstates; ++i) {
571 state.power = CPUFREQ_VAL_UNKNOWN;
573 switch (sc->pn_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)
581 state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
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));
592 memcpy(&sc->powernow_states[j], &state,
593 sizeof(struct powernow_state));
598 * Fix powernow_max_states, if errata a0 give us less states
601 sc->powernow_max_states = n;
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;
608 printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
610 sc->powernow_states[i].freq,
619 cpuid_is_k7(u_int cpuid)
637 pn_decode_pst(device_t dev)
641 u_int cpuid, maxfid, startvid;
643 struct psb_header *psb;
648 sc = device_get_softc(dev);
650 do_cpuid(0x80000001, regs);
653 if ((cpuid & 0xfff) == 0x760)
654 sc->errata |= A0_ERRATA;
656 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
658 switch (sc->pn_type) {
660 maxfid = PN7_STA_MFID(status);
661 startvid = PN7_STA_SVID(status);
664 maxfid = PN8_STA_MFID(status);
666 * we should actually use a variable named 'maxvid' if K8,
667 * but why introducing a new variable for that?
669 startvid = PN8_STA_MVID(status);
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",
683 sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
685 struct pst_header *pst;
687 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
689 switch (psb->version) {
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.
699 if (sc->pn_type != PN8_TYPE)
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);
707 device_printf(dev, "PSB: VST: %d\n",
709 device_printf(dev, "PSB: RVO %x IRT %d "
718 if (sc->pn_type != PN7_TYPE)
720 sc->sgtc = psb->settlingtime * sc->fsb;
721 if (sc->sgtc < 100 * sc->fsb)
722 sc->sgtc = 100 * sc->fsb;
726 p = ((uint8_t *) psb) + sizeof(struct psb_header);
727 pst = (struct pst_header*) p;
732 struct pst_header *pst = (struct pst_header*) p;
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) {
740 if (abs(sc->fsb - pst->fsb) > 5)
746 return (decode_pst(sc,
747 p + sizeof(struct pst_header),
748 sc->powernow_max_states));
751 p += sizeof(struct pst_header) + (2 * pst->numpstates);
752 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
754 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
761 pn_decode_acpi(device_t dev, device_t perf_dev)
769 struct powernow_state state;
770 struct cf_setting sets[POWERNOW_MAX_STATES];
771 int count = POWERNOW_MAX_STATES;
775 if (perf_dev == NULL)
778 rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
781 rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
782 if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
785 sc = device_get_softc(dev);
787 do_cpuid(0x80000001, regs);
789 if ((cpuid & 0xfff) == 0x760)
790 sc->errata |= A0_ERRATA;
794 for (n = 0, i = 0; i < count; ++i) {
795 ctrl = sets[i].spec[PX_SPEC_CONTROL];
796 switch (sc->pn_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)
805 state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
806 state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
809 state.freq = sets[i].freq * 1000;
810 state.power = sets[i].power;
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));
819 memcpy(&sc->powernow_states[j], &state,
820 sizeof(struct powernow_state));
824 sc->powernow_max_states = n;
825 state = sc->powernow_states[0];
826 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
828 switch (sc->pn_type) {
830 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
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
837 if (PN7_STA_MFID(status) != state.fid) {
838 device_printf(dev, "ACPI MAX frequency not found\n");
841 sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
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 */
852 * powernow k8 supports only one low frequency.
854 if (sc->powernow_max_states >= 2 &&
855 (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
857 sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
865 pn_identify(driver_t *driver, device_t parent)
868 if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
870 switch (cpu_id & 0xf00) {
877 if (device_find_child(parent, "powernow", -1) != NULL)
879 if (BUS_ADD_CHILD(parent, 10, "powernow", device_get_unit(parent))
881 device_printf(parent, "powernow: add child failed\n");
885 pn_probe(device_t dev)
891 u_int sfid, mfid, cfid;
893 sc = device_get_softc(dev);
895 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
897 pc = cpu_get_pcpu(dev);
901 cpu_est_clockrate(pc->pc_cpuid, &rate);
903 switch (cpu_id & 0xf00) {
905 sfid = PN7_STA_SFID(status);
906 mfid = PN7_STA_MFID(status);
907 cfid = PN7_STA_CFID(status);
908 sc->pn_type = PN7_TYPE;
909 sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];
912 * If start FID is different to max FID, then it is a
913 * mobile processor. If not, it is a low powered desktop
916 if (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
917 sc->vid_to_volts = pn7_mobile_vid_to_volts;
918 device_set_desc(dev, "PowerNow! K7");
920 sc->vid_to_volts = pn7_desktop_vid_to_volts;
921 device_set_desc(dev, "Cool`n'Quiet K7");
926 sfid = PN8_STA_SFID(status);
927 mfid = PN8_STA_MFID(status);
928 cfid = PN8_STA_CFID(status);
929 sc->pn_type = PN8_TYPE;
930 sc->vid_to_volts = pn8_vid_to_volts;
931 sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid];
933 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
934 device_set_desc(dev, "PowerNow! K8");
936 device_set_desc(dev, "Cool`n'Quiet K8");
946 pn_attach(device_t dev)
951 child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
953 rv = pn_decode_acpi(dev, child);
955 rv = pn_decode_pst(dev);
957 rv = pn_decode_pst(dev);
961 cpufreq_register(dev);
966 pn_detach(device_t dev)
969 return (cpufreq_unregister(dev));