]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/x86/cpufreq/powernow.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / x86 / cpufreq / powernow.c
1 /*-
2  * Copyright (c) 2004-2005 Bruno Ducrot
3  * Copyright (c) 2004 FUKUDA Nobuhiko <nfukuda@spa.is.uec.ac.jp>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
24  */
25
26 /*
27  * Many thanks to Nate Lawson for his helpful comments on this driver and
28  * to Jung-uk Kim for testing.
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/bus.h>
36 #include <sys/cpu.h>
37 #include <sys/kernel.h>
38 #include <sys/malloc.h>
39 #include <sys/module.h>
40 #include <sys/pcpu.h>
41 #include <sys/systm.h>
42
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>
48 #include <sys/rman.h>
49
50 #include <vm/vm.h>
51 #include <vm/pmap.h>
52
53 #include "cpufreq_if.h"
54
55 #define PN7_TYPE        0
56 #define PN8_TYPE        1
57
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 :( */
66
67 /* Legacy configuration via BIOS table PSB. */
68 #define PSB_START       0
69 #define PSB_STEP        0x10
70 #define PSB_SIG         "AMDK7PNOW!"
71 #define PSB_LEN         10
72 #define PSB_OFF         0
73
74 struct psb_header {
75         char             signature[10];
76         uint8_t          version;
77         uint8_t          flags;
78         uint16_t         settlingtime;
79         uint8_t          res1;
80         uint8_t          numpst;
81 } __packed;
82
83 struct pst_header {
84         uint32_t         cpuid;
85         uint8_t          fsb;
86         uint8_t          maxfid;
87         uint8_t          startvid;
88         uint8_t          numpstates;
89 } __packed;
90
91 /*
92  * MSRs and bits used by Powernow technology
93  */
94 #define MSR_AMDK7_FIDVID_CTL            0xc0010041
95 #define MSR_AMDK7_FIDVID_STATUS         0xc0010042
96
97 /* Bitfields used by K7 */
98
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)
105
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)
112
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)
117
118 /* Bitfields used by K8 */
119
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)
123
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)
131
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)
137
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)
146
147
148 #define WRITE_FIDVID(fid, vid, ctrl)    \
149         wrmsr(MSR_AMDK7_FIDVID_CTL,     \
150             (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
151
152 #define COUNT_OFF_IRT(irt)      DELAY(10 * (1 << (irt)))
153 #define COUNT_OFF_VST(vst)      DELAY(20 * (vst))
154
155 #define FID_TO_VCO_FID(fid)     \
156         (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
157
158 /*
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.
162  */
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,
168 };
169
170
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,
180 };
181
182 /*
183  * Units are in mV.
184  */
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,
191 };
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,
198 };
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,
205 };
206
207 #define POWERNOW_MAX_STATES             16
208
209 struct powernow_state {
210         int freq;
211         int power;
212         int fid;
213         int vid;
214 };
215
216 struct 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
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,
248                     int *count);
249 static int      pn_type(device_t dev, int *type);
250
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),
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
264         {0, 0}
265 };
266
267 static devclass_t pn_devclass;
268 static driver_t pn_driver = {
269         "powernow",
270         pn_methods,
271         sizeof(struct pn_softc),
272 };
273
274 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
275
276 static int
277 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
278 {
279         int cfid, cvid;
280         uint64_t status, ctl;
281
282         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
283         cfid = PN7_STA_CFID(status);
284         cvid = PN7_STA_CVID(status);
285
286         /* We're already at the requested level. */
287         if (fid == cfid && vid == cvid)
288                 return (0);
289
290         ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
291
292         ctl |= PN7_CTR_FID(fid);
293         ctl |= PN7_CTR_VID(vid);
294         ctl |= PN7_CTR_SGTC(sc->sgtc);
295
296         if (sc->errata & A0_ERRATA)
297                 disable_intr();
298
299         if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
300                 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
301                 if (vid != cvid)
302                         wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
303         } else {
304                 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
305                 if (fid != cfid)
306                         wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
307         }
308
309         if (sc->errata & A0_ERRATA)
310                 enable_intr();
311
312         return (0);
313 }
314
315 static int
316 pn8_read_pending_wait(uint64_t *status)
317 {
318         int i = 10000;
319
320         do
321                 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
322         while (PN8_STA_PENDING(*status) && --i);
323
324         return (i == 0 ? ENXIO : 0);
325 }
326
327 static int
328 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
329 {
330         int i = 100;
331
332         do
333                 WRITE_FIDVID(fid, vid, ctrl);
334         while (pn8_read_pending_wait(status) && --i);
335
336         return (i == 0 ? ENXIO : 0);
337 }
338
339 static int
340 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
341 {
342         uint64_t status;
343         int cfid, cvid;
344         int rvo;
345         int rv;
346         u_int val;
347
348         rv = pn8_read_pending_wait(&status);
349         if (rv)
350                 return (rv);
351
352         cfid = PN8_STA_CFID(status);
353         cvid = PN8_STA_CVID(status);
354
355         if (fid == cfid && vid == cvid)
356                 return (0);
357
358         /*
359          * Phase 1: Raise core voltage to requested VID if frequency is
360          * going up.
361          */
362         while (cvid > vid) {
363                 val = cvid - (1 << sc->mvs);
364                 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
365                 if (rv) {
366                         sc->errata |= PENDING_STUCK;
367                         return (rv);
368                 }
369                 cvid = PN8_STA_CVID(status);
370                 COUNT_OFF_VST(sc->vst);
371         }
372
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
377                  * under Linux */
378                 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
379                 if (rv) {
380                         sc->errata |= PENDING_STUCK;
381                         return (rv);
382                 }
383                 cvid = PN8_STA_CVID(status);
384                 COUNT_OFF_VST(sc->vst);
385         }
386
387         /* Phase 2: change to requested core frequency */
388         if (cfid != fid) {
389                 u_int vco_fid, vco_cfid, fid_delta;
390
391                 vco_fid = FID_TO_VCO_FID(fid);
392                 vco_cfid = FID_TO_VCO_FID(cfid);
393
394                 while (abs(vco_fid - vco_cfid) > 2) {
395                         fid_delta = (vco_cfid & 1) ? 1 : 2;
396                         if (fid > cfid) {
397                                 if (cfid > 7)
398                                         val = cfid + fid_delta;
399                                 else
400                                         val = FID_TO_VCO_FID(cfid) + fid_delta;
401                         } else
402                                 val = cfid - fid_delta;
403                         rv = pn8_write_fidvid(val, cvid,
404                             sc->pll * (uint64_t) sc->fsb,
405                             &status);
406                         if (rv) {
407                                 sc->errata |= PENDING_STUCK;
408                                 return (rv);
409                         }
410                         cfid = PN8_STA_CFID(status);
411                         COUNT_OFF_IRT(sc->irt);
412
413                         vco_cfid = FID_TO_VCO_FID(cfid);
414                 }
415
416                 rv = pn8_write_fidvid(fid, cvid,
417                     sc->pll * (uint64_t) sc->fsb,
418                     &status);
419                 if (rv) {
420                         sc->errata |= PENDING_STUCK;
421                         return (rv);
422                 }
423                 cfid = PN8_STA_CFID(status);
424                 COUNT_OFF_IRT(sc->irt);
425         }
426
427         /* Phase 3: change to requested voltage */
428         if (cvid != vid) {
429                 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
430                 cvid = PN8_STA_CVID(status);
431                 COUNT_OFF_VST(sc->vst);
432         }
433
434         /* Check if transition failed. */
435         if (cfid != fid || cvid != vid)
436                 rv = ENXIO;
437
438         return (rv);
439 }
440
441 static int
442 pn_set(device_t dev, const struct cf_setting *cf)
443 {
444         struct pn_softc *sc;
445         int fid, vid;
446         int i;
447         int rv;
448
449         if (cf == NULL)
450                 return (EINVAL);
451         sc = device_get_softc(dev);
452
453         if (sc->errata & PENDING_STUCK)
454                 return (ENXIO);
455
456         for (i = 0; i < sc->powernow_max_states; ++i)
457                 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
458                         break;
459
460         fid = sc->powernow_states[i].fid;
461         vid = sc->powernow_states[i].vid;
462
463         rv = ENODEV;
464
465         switch (sc->pn_type) {
466         case PN7_TYPE:
467                 rv = pn7_setfidvid(sc, fid, vid);
468                 break;
469         case PN8_TYPE:
470                 rv = pn8_setfidvid(sc, fid, vid);
471                 break;
472         }
473
474         return (rv);
475 }
476
477 static int
478 pn_get(device_t dev, struct cf_setting *cf)
479 {
480         struct pn_softc *sc;
481         u_int cfid = 0, cvid = 0;
482         int i;
483         uint64_t status;
484
485         if (cf == NULL)
486                 return (EINVAL);
487         sc = device_get_softc(dev);
488         if (sc->errata & PENDING_STUCK)
489                 return (ENXIO);
490
491         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
492
493         switch (sc->pn_type) {
494         case PN7_TYPE:
495                 cfid = PN7_STA_CFID(status);
496                 cvid = PN7_STA_CVID(status);
497                 break;
498         case PN8_TYPE:
499                 cfid = PN8_STA_CFID(status);
500                 cvid = PN8_STA_CVID(status);
501                 break;
502         }
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)
506                         break;
507
508         if (i < sc->powernow_max_states) {
509                 cf->freq = sc->powernow_states[i].freq / 1000;
510                 cf->power = sc->powernow_states[i].power;
511                 cf->lat = 200;
512                 cf->volts = sc->vid_to_volts[cvid];
513                 cf->dev = dev;
514         } else {
515                 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
516                 cf->dev = NULL;
517         }
518
519         return (0);
520 }
521
522 static int
523 pn_settings(device_t dev, struct cf_setting *sets, int *count)
524 {
525         struct pn_softc *sc;
526         int i;
527
528         if (sets == NULL|| count == NULL)
529                 return (EINVAL);
530         sc = device_get_softc(dev);
531         if (*count < sc->powernow_max_states)
532                 return (E2BIG);
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;
536                 sets[i].lat = 200;
537                 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
538                 sets[i].dev = dev;
539         }
540         *count = sc->powernow_max_states;
541
542         return (0);
543 }
544
545 static int
546 pn_type(device_t dev, int *type)
547 {
548         if (type == NULL)
549                 return (EINVAL);
550
551         *type = CPUFREQ_TYPE_ABSOLUTE;
552
553         return (0);
554 }
555
556 /*
557  * Given a set of pair of fid/vid, and number of performance states,
558  * compute powernow_states via an insertion sort.
559  */
560 static int
561 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
562 {
563         int i, j, n;
564         struct powernow_state state;
565
566         for (i = 0; i < POWERNOW_MAX_STATES; ++i)
567                 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
568
569         for (n = 0, i = 0; i < npstates; ++i) {
570                 state.fid = *p++;
571                 state.vid = *p++;
572                 state.power = CPUFREQ_VAL_UNKNOWN;
573
574                 switch (sc->pn_type) {
575                 case PN7_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)
579                                 continue;
580                         break;
581                 case PN8_TYPE:
582                         state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
583                         break;
584                 }
585
586                 j = n;
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));
591                         --j;
592                 }
593                 memcpy(&sc->powernow_states[j], &state,
594                     sizeof(struct powernow_state));
595                 ++n;
596         }
597
598         /*
599          * Fix powernow_max_states, if errata a0 give us less states
600          * than expected.
601          */
602         sc->powernow_max_states = n;
603
604         if (bootverbose)
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;
608
609                         printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
610                             i,
611                             sc->powernow_states[i].freq,
612                             fid,
613                             vid);
614                 }
615
616         return (0);
617 }
618
619 static int
620 cpuid_is_k7(u_int cpuid)
621 {
622
623         switch (cpuid) {
624         case 0x760:
625         case 0x761:
626         case 0x762:
627         case 0x770:
628         case 0x771:
629         case 0x780:
630         case 0x781:
631         case 0x7a0:
632                 return (TRUE);
633         }
634         return (FALSE);
635 }
636
637 static int
638 pn_decode_pst(device_t dev)
639 {
640         int maxpst;
641         struct pn_softc *sc;
642         u_int cpuid, maxfid, startvid;
643         u_long sig;
644         struct psb_header *psb;
645         uint8_t *p;
646         u_int regs[4];
647         uint64_t status;
648
649         sc = device_get_softc(dev);
650
651         do_cpuid(0x80000001, regs);
652         cpuid = regs[0];
653
654         if ((cpuid & 0xfff) == 0x760)
655                 sc->errata |= A0_ERRATA;
656
657         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
658
659         switch (sc->pn_type) {
660         case PN7_TYPE:
661                 maxfid = PN7_STA_MFID(status);
662                 startvid = PN7_STA_SVID(status);
663                 break;
664         case PN8_TYPE:
665                 maxfid = PN8_STA_MFID(status);
666                 /*
667                  * we should actually use a variable named 'maxvid' if K8,
668                  * but why introducing a new variable for that?
669                  */
670                 startvid = PN8_STA_MVID(status);
671                 break;
672         default:
673                 return (ENODEV);
674         }
675
676         if (bootverbose) {
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",
681                     startvid);
682         }
683
684         sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
685         if (sig) {
686                 struct pst_header *pst;
687
688                 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
689
690                 switch (psb->version) {
691                 default:
692                         return (ENODEV);
693                 case 0x14:
694                         /*
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.
699                          */
700                         if (sc->pn_type != PN8_TYPE)
701                                 return (EINVAL);
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);
707                         if (bootverbose) {
708                                 device_printf(dev, "PSB: VST: %d\n",
709                                     psb->settlingtime);
710                                 device_printf(dev, "PSB: RVO %x IRT %d "
711                                     "MVS %d BATT %d\n",
712                                     sc->rvo,
713                                     sc->irt,
714                                     sc->mvs,
715                                     sc->low);
716                         }
717                         break;
718                 case 0x12:
719                         if (sc->pn_type != PN7_TYPE)
720                                 return (EINVAL);
721                         sc->sgtc = psb->settlingtime * sc->fsb;
722                         if (sc->sgtc < 100 * sc->fsb)
723                                 sc->sgtc = 100 * sc->fsb;
724                         break;
725                 }
726
727                 p = ((uint8_t *) psb) + sizeof(struct psb_header);
728                 pst = (struct pst_header*) p;
729
730                 maxpst = 200;
731
732                 do {
733                         struct pst_header *pst = (struct pst_header*) p;
734
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) {
740                                 case PN7_TYPE:
741                                         if (abs(sc->fsb - pst->fsb) > 5)
742                                                 continue;
743                                         break;
744                                 case PN8_TYPE:
745                                         break;
746                                 }
747                                 return (decode_pst(sc,
748                                     p + sizeof(struct pst_header),
749                                     sc->powernow_max_states));
750                         }
751
752                         p += sizeof(struct pst_header) + (2 * pst->numpstates);
753                 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
754
755                 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
756         }
757
758         return (ENODEV);
759 }
760
761 static int
762 pn_decode_acpi(device_t dev, device_t perf_dev)
763 {
764         int i, j, n;
765         uint64_t status;
766         uint32_t ctrl;
767         u_int cpuid;
768         u_int regs[4];
769         struct pn_softc *sc;
770         struct powernow_state state;
771         struct cf_setting sets[POWERNOW_MAX_STATES];
772         int count = POWERNOW_MAX_STATES;
773         int type;
774         int rv;
775
776         if (perf_dev == NULL)
777                 return (ENXIO);
778
779         rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
780         if (rv)
781                 return (ENXIO);
782         rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
783         if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
784                 return (ENXIO);
785
786         sc = device_get_softc(dev);
787
788         do_cpuid(0x80000001, regs);
789         cpuid = regs[0];
790         if ((cpuid & 0xfff) == 0x760)
791                 sc->errata |= A0_ERRATA;
792
793         ctrl = 0;
794         sc->sgtc = 0;
795         for (n = 0, i = 0; i < count; ++i) {
796                 ctrl = sets[i].spec[PX_SPEC_CONTROL];
797                 switch (sc->pn_type) {
798                 case PN7_TYPE:
799                         state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
800                         state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
801                         if ((sc->errata & A0_ERRATA) &&
802                             (pn7_fid_to_mult[state.fid] % 10) == 5)
803                                 continue;
804                         break;
805                 case PN8_TYPE:
806                         state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
807                         state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
808                         break;
809                 }
810                 state.freq = sets[i].freq * 1000;
811                 state.power = sets[i].power;
812
813                 j = n;
814                 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
815                         memcpy(&sc->powernow_states[j],
816                             &sc->powernow_states[j - 1],
817                             sizeof(struct powernow_state));
818                         --j;
819                 }
820                 memcpy(&sc->powernow_states[j], &state,
821                     sizeof(struct powernow_state));
822                 ++n;
823         }
824
825         sc->powernow_max_states = n;
826         state = sc->powernow_states[0];
827         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
828
829         switch (sc->pn_type) {
830         case PN7_TYPE:
831                 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
832                 /*
833                  * XXX Some bios forget the max frequency!
834                  * This maybe indicates we have the wrong tables.  Therefore,
835                  * don't implement a quirk, but fallback to BIOS legacy
836                  * tables instead.
837                  */
838                 if (PN7_STA_MFID(status) != state.fid) {
839                         device_printf(dev, "ACPI MAX frequency not found\n");
840                         return (EINVAL);
841                 }
842                 sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
843                 break;
844         case PN8_TYPE:
845                 sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
846                 sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
847                 sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
848                 sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
849                 sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
850                 sc->low = 0; /* XXX */
851
852                 /*
853                  * powernow k8 supports only one low frequency.
854                  */
855                 if (sc->powernow_max_states >= 2 &&
856                     (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
857                         return (EINVAL);
858                 sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
859                 break;
860         }
861
862         return (0);
863 }
864
865 static void
866 pn_identify(driver_t *driver, device_t parent)
867 {
868
869         if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
870                 return;
871         switch (cpu_id & 0xf00) {
872         case 0x600:
873         case 0xf00:
874                 break;
875         default:
876                 return;
877         }
878         if (device_find_child(parent, "powernow", -1) != NULL)
879                 return;
880         if (BUS_ADD_CHILD(parent, 10, "powernow", -1) == NULL)
881                 device_printf(parent, "powernow: add child failed\n");
882 }
883
884 static int
885 pn_probe(device_t dev)
886 {
887         struct pn_softc *sc;
888         uint64_t status;
889         uint64_t rate;
890         struct pcpu *pc;
891         u_int sfid, mfid, cfid;
892
893         sc = device_get_softc(dev);
894         sc->errata = 0;
895         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
896
897         pc = cpu_get_pcpu(dev);
898         if (pc == NULL)
899                 return (ENODEV);
900
901         cpu_est_clockrate(pc->pc_cpuid, &rate);
902
903         switch (cpu_id & 0xf00) {
904         case 0x600:
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];
910
911                 /*
912                  * If start FID is different to max FID, then it is a
913                  * mobile processor.  If not, it is a low powered desktop
914                  * processor.
915                  */
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");
919                 } else {
920                         sc->vid_to_volts = pn7_desktop_vid_to_volts;
921                         device_set_desc(dev, "Cool`n'Quiet K7");
922                 }
923                 break;
924
925         case 0xf00:
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];
932
933                 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
934                         device_set_desc(dev, "PowerNow! K8");
935                 else
936                         device_set_desc(dev, "Cool`n'Quiet K8");
937                 break;
938         default:
939                 return (ENODEV);
940         }
941
942         return (0);
943 }
944
945 static int
946 pn_attach(device_t dev)
947 {
948         int rv;
949         device_t child;
950
951         child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
952         if (child) {
953                 rv = pn_decode_acpi(dev, child);
954                 if (rv)
955                         rv = pn_decode_pst(dev);
956         } else
957                 rv = pn_decode_pst(dev);
958
959         if (rv != 0)
960                 return (ENXIO);
961         cpufreq_register(dev);
962         return (0);
963 }
964
965 static int
966 pn_detach(device_t dev)
967 {
968
969         return (cpufreq_unregister(dev));
970 }