2 * Copyright (c) 2004-2005 Bruno Ducrot
3 * Copyright (c) 2004 FUKUDA Nobuhiko <nfukuda@spa.is.uec.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * Many thanks to Nate Lawson for his helpful comments on this driver and
28 * to Jung-uk Kim for testing.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
41 #include <sys/systm.h>
43 #include <machine/pc/bios.h>
44 #include <machine/md_var.h>
45 #include <machine/specialreg.h>
46 #include <machine/cputypes.h>
47 #include <machine/vmparam.h>
53 #include "cpufreq_if.h"
58 /* Flags for some hardware bugs. */
59 #define A0_ERRATA 0x1 /* Bugs for the rev. A0 of Athlon (K7):
60 * Interrupts must be disabled and no half
61 * multipliers are allowed */
62 #define PENDING_STUCK 0x2 /* With some buggy chipset and some newer AMD64
63 * processor (Rev. G?):
64 * the pending bit from the msr FIDVID_STATUS
65 * is set forever. No workaround :( */
67 /* Legacy configuration via BIOS table PSB. */
70 #define PSB_SIG "AMDK7PNOW!"
78 uint16_t settlingtime;
92 * MSRs and bits used by Powernow technology
94 #define MSR_AMDK7_FIDVID_CTL 0xc0010041
95 #define MSR_AMDK7_FIDVID_STATUS 0xc0010042
97 /* Bitfields used by K7 */
99 #define PN7_CTR_FID(x) ((x) & 0x1f)
100 #define PN7_CTR_VID(x) (((x) & 0x1f) << 8)
101 #define PN7_CTR_FIDC 0x00010000
102 #define PN7_CTR_VIDC 0x00020000
103 #define PN7_CTR_FIDCHRATIO 0x00100000
104 #define PN7_CTR_SGTC(x) (((uint64_t)(x) & 0x000fffff) << 32)
106 #define PN7_STA_CFID(x) ((x) & 0x1f)
107 #define PN7_STA_SFID(x) (((x) >> 8) & 0x1f)
108 #define PN7_STA_MFID(x) (((x) >> 16) & 0x1f)
109 #define PN7_STA_CVID(x) (((x) >> 32) & 0x1f)
110 #define PN7_STA_SVID(x) (((x) >> 40) & 0x1f)
111 #define PN7_STA_MVID(x) (((x) >> 48) & 0x1f)
113 /* ACPI ctr_val status register to powernow k7 configuration */
114 #define ACPI_PN7_CTRL_TO_FID(x) ((x) & 0x1f)
115 #define ACPI_PN7_CTRL_TO_VID(x) (((x) >> 5) & 0x1f)
116 #define ACPI_PN7_CTRL_TO_SGTC(x) (((x) >> 10) & 0xffff)
118 /* Bitfields used by K8 */
120 #define PN8_CTR_FID(x) ((x) & 0x3f)
121 #define PN8_CTR_VID(x) (((x) & 0x1f) << 8)
122 #define PN8_CTR_PENDING(x) (((x) & 1) << 32)
124 #define PN8_STA_CFID(x) ((x) & 0x3f)
125 #define PN8_STA_SFID(x) (((x) >> 8) & 0x3f)
126 #define PN8_STA_MFID(x) (((x) >> 16) & 0x3f)
127 #define PN8_STA_PENDING(x) (((x) >> 31) & 0x01)
128 #define PN8_STA_CVID(x) (((x) >> 32) & 0x1f)
129 #define PN8_STA_SVID(x) (((x) >> 40) & 0x1f)
130 #define PN8_STA_MVID(x) (((x) >> 48) & 0x1f)
132 /* Reserved1 to powernow k8 configuration */
133 #define PN8_PSB_TO_RVO(x) ((x) & 0x03)
134 #define PN8_PSB_TO_IRT(x) (((x) >> 2) & 0x03)
135 #define PN8_PSB_TO_MVS(x) (((x) >> 4) & 0x03)
136 #define PN8_PSB_TO_BATT(x) (((x) >> 6) & 0x03)
138 /* ACPI ctr_val status register to powernow k8 configuration */
139 #define ACPI_PN8_CTRL_TO_FID(x) ((x) & 0x3f)
140 #define ACPI_PN8_CTRL_TO_VID(x) (((x) >> 6) & 0x1f)
141 #define ACPI_PN8_CTRL_TO_VST(x) (((x) >> 11) & 0x1f)
142 #define ACPI_PN8_CTRL_TO_MVS(x) (((x) >> 18) & 0x03)
143 #define ACPI_PN8_CTRL_TO_PLL(x) (((x) >> 20) & 0x7f)
144 #define ACPI_PN8_CTRL_TO_RVO(x) (((x) >> 28) & 0x03)
145 #define ACPI_PN8_CTRL_TO_IRT(x) (((x) >> 30) & 0x03)
148 #define WRITE_FIDVID(fid, vid, ctrl) \
149 wrmsr(MSR_AMDK7_FIDVID_CTL, \
150 (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
152 #define COUNT_OFF_IRT(irt) DELAY(10 * (1 << (irt)))
153 #define COUNT_OFF_VST(vst) DELAY(20 * (vst))
155 #define FID_TO_VCO_FID(fid) \
156 (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
159 * Divide each value by 10 to get the processor multiplier.
160 * Some of those tables are the same as the Linux powernow-k7
161 * implementation by Dave Jones.
163 static int pn7_fid_to_mult[32] = {
164 110, 115, 120, 125, 50, 55, 60, 65,
165 70, 75, 80, 85, 90, 95, 100, 105,
166 30, 190, 40, 200, 130, 135, 140, 210,
167 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),
267 static devclass_t pn_devclass;
268 static driver_t pn_driver = {
271 sizeof(struct pn_softc),
274 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
277 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
280 uint64_t status, ctl;
282 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
283 cfid = PN7_STA_CFID(status);
284 cvid = PN7_STA_CVID(status);
286 /* We're already at the requested level. */
287 if (fid == cfid && vid == cvid)
290 ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
292 ctl |= PN7_CTR_FID(fid);
293 ctl |= PN7_CTR_VID(vid);
294 ctl |= PN7_CTR_SGTC(sc->sgtc);
296 if (sc->errata & A0_ERRATA)
299 if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
300 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
302 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
304 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
306 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
309 if (sc->errata & A0_ERRATA)
316 pn8_read_pending_wait(uint64_t *status)
321 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
322 while (PN8_STA_PENDING(*status) && --i);
324 return (i == 0 ? ENXIO : 0);
328 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
333 WRITE_FIDVID(fid, vid, ctrl);
334 while (pn8_read_pending_wait(status) && --i);
336 return (i == 0 ? ENXIO : 0);
340 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
348 rv = pn8_read_pending_wait(&status);
352 cfid = PN8_STA_CFID(status);
353 cvid = PN8_STA_CVID(status);
355 if (fid == cfid && vid == cvid)
359 * Phase 1: Raise core voltage to requested VID if frequency is
363 val = cvid - (1 << sc->mvs);
364 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
366 sc->errata |= PENDING_STUCK;
369 cvid = PN8_STA_CVID(status);
370 COUNT_OFF_VST(sc->vst);
373 /* ... then raise to voltage + RVO (if required) */
374 for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
375 /* XXX It's not clear from spec if we have to do that
376 * in 0.25 step or in MVS. Therefore do it as it's done
378 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
380 sc->errata |= PENDING_STUCK;
383 cvid = PN8_STA_CVID(status);
384 COUNT_OFF_VST(sc->vst);
387 /* Phase 2: change to requested core frequency */
389 u_int vco_fid, vco_cfid, fid_delta;
391 vco_fid = FID_TO_VCO_FID(fid);
392 vco_cfid = FID_TO_VCO_FID(cfid);
394 while (abs(vco_fid - vco_cfid) > 2) {
395 fid_delta = (vco_cfid & 1) ? 1 : 2;
398 val = cfid + fid_delta;
400 val = FID_TO_VCO_FID(cfid) + fid_delta;
402 val = cfid - fid_delta;
403 rv = pn8_write_fidvid(val, cvid,
404 sc->pll * (uint64_t) sc->fsb,
407 sc->errata |= PENDING_STUCK;
410 cfid = PN8_STA_CFID(status);
411 COUNT_OFF_IRT(sc->irt);
413 vco_cfid = FID_TO_VCO_FID(cfid);
416 rv = pn8_write_fidvid(fid, cvid,
417 sc->pll * (uint64_t) sc->fsb,
420 sc->errata |= PENDING_STUCK;
423 cfid = PN8_STA_CFID(status);
424 COUNT_OFF_IRT(sc->irt);
427 /* Phase 3: change to requested voltage */
429 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
430 cvid = PN8_STA_CVID(status);
431 COUNT_OFF_VST(sc->vst);
434 /* Check if transition failed. */
435 if (cfid != fid || cvid != vid)
442 pn_set(device_t dev, const struct cf_setting *cf)
451 sc = device_get_softc(dev);
453 if (sc->errata & PENDING_STUCK)
456 for (i = 0; i < sc->powernow_max_states; ++i)
457 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
460 fid = sc->powernow_states[i].fid;
461 vid = sc->powernow_states[i].vid;
465 switch (sc->pn_type) {
467 rv = pn7_setfidvid(sc, fid, vid);
470 rv = pn8_setfidvid(sc, fid, vid);
478 pn_get(device_t dev, struct cf_setting *cf)
481 u_int cfid = 0, cvid = 0;
487 sc = device_get_softc(dev);
488 if (sc->errata & PENDING_STUCK)
491 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
493 switch (sc->pn_type) {
495 cfid = PN7_STA_CFID(status);
496 cvid = PN7_STA_CVID(status);
499 cfid = PN8_STA_CFID(status);
500 cvid = PN8_STA_CVID(status);
503 for (i = 0; i < sc->powernow_max_states; ++i)
504 if (cfid == sc->powernow_states[i].fid &&
505 cvid == sc->powernow_states[i].vid)
508 if (i < sc->powernow_max_states) {
509 cf->freq = sc->powernow_states[i].freq / 1000;
510 cf->power = sc->powernow_states[i].power;
512 cf->volts = sc->vid_to_volts[cvid];
515 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
523 pn_settings(device_t dev, struct cf_setting *sets, int *count)
528 if (sets == NULL|| count == NULL)
530 sc = device_get_softc(dev);
531 if (*count < sc->powernow_max_states)
533 for (i = 0; i < sc->powernow_max_states; ++i) {
534 sets[i].freq = sc->powernow_states[i].freq / 1000;
535 sets[i].power = sc->powernow_states[i].power;
537 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
540 *count = sc->powernow_max_states;
546 pn_type(device_t dev, int *type)
551 *type = CPUFREQ_TYPE_ABSOLUTE;
557 * Given a set of pair of fid/vid, and number of performance states,
558 * compute powernow_states via an insertion sort.
561 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
564 struct powernow_state state;
566 for (i = 0; i < POWERNOW_MAX_STATES; ++i)
567 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
569 for (n = 0, i = 0; i < npstates; ++i) {
572 state.power = CPUFREQ_VAL_UNKNOWN;
574 switch (sc->pn_type) {
576 state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
577 if ((sc->errata & A0_ERRATA) &&
578 (pn7_fid_to_mult[state.fid] % 10) == 5)
582 state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
587 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
588 memcpy(&sc->powernow_states[j],
589 &sc->powernow_states[j - 1],
590 sizeof(struct powernow_state));
593 memcpy(&sc->powernow_states[j], &state,
594 sizeof(struct powernow_state));
599 * Fix powernow_max_states, if errata a0 give us less states
602 sc->powernow_max_states = n;
605 for (i = 0; i < sc->powernow_max_states; ++i) {
606 int fid = sc->powernow_states[i].fid;
607 int vid = sc->powernow_states[i].vid;
609 printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
611 sc->powernow_states[i].freq,
620 cpuid_is_k7(u_int cpuid)
638 pn_decode_pst(device_t dev)
642 u_int cpuid, maxfid, startvid;
644 struct psb_header *psb;
649 sc = device_get_softc(dev);
651 do_cpuid(0x80000001, regs);
654 if ((cpuid & 0xfff) == 0x760)
655 sc->errata |= A0_ERRATA;
657 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
659 switch (sc->pn_type) {
661 maxfid = PN7_STA_MFID(status);
662 startvid = PN7_STA_SVID(status);
665 maxfid = PN8_STA_MFID(status);
667 * we should actually use a variable named 'maxvid' if K8,
668 * but why introducing a new variable for that?
670 startvid = PN8_STA_MVID(status);
677 device_printf(dev, "STATUS: 0x%jx\n", status);
678 device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
679 device_printf(dev, "STATUS: %s: 0x%02x\n",
680 sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
684 sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
686 struct pst_header *pst;
688 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
690 switch (psb->version) {
695 * We can't be picky about numpst since at least
696 * some systems have a value of 1 and some have 2.
697 * We trust that cpuid_is_k7() will be better at
698 * catching that we're on a K8 anyway.
700 if (sc->pn_type != PN8_TYPE)
702 sc->vst = psb->settlingtime;
703 sc->rvo = PN8_PSB_TO_RVO(psb->res1),
704 sc->irt = PN8_PSB_TO_IRT(psb->res1),
705 sc->mvs = PN8_PSB_TO_MVS(psb->res1),
706 sc->low = PN8_PSB_TO_BATT(psb->res1);
708 device_printf(dev, "PSB: VST: %d\n",
710 device_printf(dev, "PSB: RVO %x IRT %d "
719 if (sc->pn_type != PN7_TYPE)
721 sc->sgtc = psb->settlingtime * sc->fsb;
722 if (sc->sgtc < 100 * sc->fsb)
723 sc->sgtc = 100 * sc->fsb;
727 p = ((uint8_t *) psb) + sizeof(struct psb_header);
728 pst = (struct pst_header*) p;
733 struct pst_header *pst = (struct pst_header*) p;
735 if (cpuid == pst->cpuid &&
736 maxfid == pst->maxfid &&
737 startvid == pst->startvid) {
738 sc->powernow_max_states = pst->numpstates;
739 switch (sc->pn_type) {
741 if (abs(sc->fsb - pst->fsb) > 5)
747 return (decode_pst(sc,
748 p + sizeof(struct pst_header),
749 sc->powernow_max_states));
752 p += sizeof(struct pst_header) + (2 * pst->numpstates);
753 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
755 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
762 * TODO: this should be done in sys/ARCH/ARCH/identcpu.c
765 cpu_is_powernow_capable(void)
769 if (strcmp(cpu_vendor, "AuthenticAMD") != 0 ||
770 cpu_exthigh < 0x80000007)
773 do_cpuid(0x80000007, regs);
774 return (regs[3] & 0x6);
778 pn_decode_acpi(device_t dev, device_t perf_dev)
786 struct powernow_state state;
787 struct cf_setting sets[POWERNOW_MAX_STATES];
788 int count = POWERNOW_MAX_STATES;
792 if (perf_dev == NULL)
795 rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
798 rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
799 if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
802 sc = device_get_softc(dev);
804 do_cpuid(0x80000001, regs);
806 if ((cpuid & 0xfff) == 0x760)
807 sc->errata |= A0_ERRATA;
811 for (n = 0, i = 0; i < count; ++i) {
812 ctrl = sets[i].spec[PX_SPEC_CONTROL];
813 switch (sc->pn_type) {
815 state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
816 state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
817 if ((sc->errata & A0_ERRATA) &&
818 (pn7_fid_to_mult[state.fid] % 10) == 5)
820 state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
823 state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
824 state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
825 state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
829 state.power = sets[i].power;
832 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
833 memcpy(&sc->powernow_states[j],
834 &sc->powernow_states[j - 1],
835 sizeof(struct powernow_state));
838 memcpy(&sc->powernow_states[j], &state,
839 sizeof(struct powernow_state));
843 sc->powernow_max_states = n;
844 state = sc->powernow_states[0];
845 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
847 switch (sc->pn_type) {
849 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
851 * XXX Some bios forget the max frequency!
852 * This maybe indicates we have the wrong tables. Therefore,
853 * don't implement a quirk, but fallback to BIOS legacy
856 if (PN7_STA_MFID(status) != state.fid) {
857 device_printf(dev, "ACPI MAX frequency not found\n");
862 sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
863 sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
864 sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
865 sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
866 sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
867 sc->low = 0; /* XXX */
870 * powernow k8 supports only one low frequency.
872 if (sc->powernow_max_states >= 2 &&
873 (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
882 pn_identify(driver_t *driver, device_t parent)
886 if (cpu_is_powernow_capable() == 0)
888 switch (cpu_id & 0xf00) {
895 if (device_find_child(parent, "powernow", -1) != NULL)
897 if ((child = BUS_ADD_CHILD(parent, 0, "powernow", -1)) == NULL)
898 device_printf(parent, "powernow: add child failed\n");
902 pn_probe(device_t dev)
908 u_int sfid, mfid, cfid;
910 sc = device_get_softc(dev);
912 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
914 pc = cpu_get_pcpu(dev);
918 cpu_est_clockrate(pc->pc_cpuid, &rate);
920 switch (cpu_id & 0xf00) {
922 sfid = PN7_STA_SFID(status);
923 mfid = PN7_STA_MFID(status);
924 cfid = PN7_STA_CFID(status);
925 sc->pn_type = PN7_TYPE;
926 sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];
929 * If start FID is different to max FID, then it is a
930 * mobile processor. If not, it is a low powered desktop
933 if (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
934 sc->vid_to_volts = pn7_mobile_vid_to_volts;
935 device_set_desc(dev, "PowerNow! K7");
937 sc->vid_to_volts = pn7_desktop_vid_to_volts;
938 device_set_desc(dev, "Cool`n'Quiet K7");
943 sfid = PN8_STA_SFID(status);
944 mfid = PN8_STA_MFID(status);
945 cfid = PN8_STA_CFID(status);
946 sc->pn_type = PN8_TYPE;
947 sc->vid_to_volts = pn8_vid_to_volts;
948 sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid];
950 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
951 device_set_desc(dev, "PowerNow! K8");
953 device_set_desc(dev, "Cool`n'Quiet K8");
963 pn_attach(device_t dev)
968 child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
970 rv = pn_decode_acpi(dev, child);
972 rv = pn_decode_pst(dev);
974 rv = pn_decode_pst(dev);
978 cpufreq_register(dev);
983 pn_detach(device_t dev)
986 cpufreq_unregister(dev);