]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/x86/cpufreq/powernow.c
zfs: merge openzfs/zfs@6c8f03232 (master) into main
[FreeBSD/FreeBSD.git] / sys / x86 / cpufreq / powernow.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2004-2005 Bruno Ducrot
5  * Copyright (c) 2004 FUKUDA Nobuhiko <nfukuda@spa.is.uec.ac.jp>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*
29  * Many thanks to Nate Lawson for his helpful comments on this driver and
30  * to Jung-uk Kim for testing.
31  */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/param.h>
37 #include <sys/bus.h>
38 #include <sys/cpu.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/module.h>
42 #include <sys/pcpu.h>
43 #include <sys/systm.h>
44
45 #include <machine/pc/bios.h>
46 #include <machine/md_var.h>
47 #include <machine/specialreg.h>
48 #include <machine/cputypes.h>
49 #include <machine/vmparam.h>
50 #include <sys/rman.h>
51
52 #include <vm/vm.h>
53 #include <vm/pmap.h>
54
55 #include "cpufreq_if.h"
56
57 #define PN7_TYPE        0
58 #define PN8_TYPE        1
59
60 /* Flags for some hardware bugs. */
61 #define A0_ERRATA       0x1     /* Bugs for the rev. A0 of Athlon (K7):
62                                  * Interrupts must be disabled and no half
63                                  * multipliers are allowed */
64 #define PENDING_STUCK   0x2     /* With some buggy chipset and some newer AMD64
65                                  * processor (Rev. G?):
66                                  * the pending bit from the msr FIDVID_STATUS
67                                  * is set forever.  No workaround :( */
68
69 /* Legacy configuration via BIOS table PSB. */
70 #define PSB_START       0
71 #define PSB_STEP        0x10
72 #define PSB_SIG         "AMDK7PNOW!"
73 #define PSB_LEN         10
74 #define PSB_OFF         0
75
76 struct psb_header {
77         char             signature[10];
78         uint8_t          version;
79         uint8_t          flags;
80         uint16_t         settlingtime;
81         uint8_t          res1;
82         uint8_t          numpst;
83 } __packed;
84
85 struct pst_header {
86         uint32_t         cpuid;
87         uint8_t          fsb;
88         uint8_t          maxfid;
89         uint8_t          startvid;
90         uint8_t          numpstates;
91 } __packed;
92
93 /*
94  * MSRs and bits used by Powernow technology
95  */
96 #define MSR_AMDK7_FIDVID_CTL            0xc0010041
97 #define MSR_AMDK7_FIDVID_STATUS         0xc0010042
98
99 /* Bitfields used by K7 */
100
101 #define PN7_CTR_FID(x)                  ((x) & 0x1f)
102 #define PN7_CTR_VID(x)                  (((x) & 0x1f) << 8)
103 #define PN7_CTR_FIDC                    0x00010000
104 #define PN7_CTR_VIDC                    0x00020000
105 #define PN7_CTR_FIDCHRATIO              0x00100000
106 #define PN7_CTR_SGTC(x)                 (((uint64_t)(x) & 0x000fffff) << 32)
107
108 #define PN7_STA_CFID(x)                 ((x) & 0x1f)
109 #define PN7_STA_SFID(x)                 (((x) >> 8) & 0x1f)
110 #define PN7_STA_MFID(x)                 (((x) >> 16) & 0x1f)
111 #define PN7_STA_CVID(x)                 (((x) >> 32) & 0x1f)
112 #define PN7_STA_SVID(x)                 (((x) >> 40) & 0x1f)
113 #define PN7_STA_MVID(x)                 (((x) >> 48) & 0x1f)
114
115 /* ACPI ctr_val status register to powernow k7 configuration */
116 #define ACPI_PN7_CTRL_TO_FID(x)         ((x) & 0x1f)
117 #define ACPI_PN7_CTRL_TO_VID(x)         (((x) >> 5) & 0x1f)
118 #define ACPI_PN7_CTRL_TO_SGTC(x)        (((x) >> 10) & 0xffff)
119
120 /* Bitfields used by K8 */
121
122 #define PN8_CTR_FID(x)                  ((x) & 0x3f)
123 #define PN8_CTR_VID(x)                  (((x) & 0x1f) << 8)
124 #define PN8_CTR_PENDING(x)              (((x) & 1) << 32)
125
126 #define PN8_STA_CFID(x)                 ((x) & 0x3f)
127 #define PN8_STA_SFID(x)                 (((x) >> 8) & 0x3f)
128 #define PN8_STA_MFID(x)                 (((x) >> 16) & 0x3f)
129 #define PN8_STA_PENDING(x)              (((x) >> 31) & 0x01)
130 #define PN8_STA_CVID(x)                 (((x) >> 32) & 0x1f)
131 #define PN8_STA_SVID(x)                 (((x) >> 40) & 0x1f)
132 #define PN8_STA_MVID(x)                 (((x) >> 48) & 0x1f)
133
134 /* Reserved1 to powernow k8 configuration */
135 #define PN8_PSB_TO_RVO(x)               ((x) & 0x03)
136 #define PN8_PSB_TO_IRT(x)               (((x) >> 2) & 0x03)
137 #define PN8_PSB_TO_MVS(x)               (((x) >> 4) & 0x03)
138 #define PN8_PSB_TO_BATT(x)              (((x) >> 6) & 0x03)
139
140 /* ACPI ctr_val status register to powernow k8 configuration */
141 #define ACPI_PN8_CTRL_TO_FID(x)         ((x) & 0x3f)
142 #define ACPI_PN8_CTRL_TO_VID(x)         (((x) >> 6) & 0x1f)
143 #define ACPI_PN8_CTRL_TO_VST(x)         (((x) >> 11) & 0x1f)
144 #define ACPI_PN8_CTRL_TO_MVS(x)         (((x) >> 18) & 0x03)
145 #define ACPI_PN8_CTRL_TO_PLL(x)         (((x) >> 20) & 0x7f)
146 #define ACPI_PN8_CTRL_TO_RVO(x)         (((x) >> 28) & 0x03)
147 #define ACPI_PN8_CTRL_TO_IRT(x)         (((x) >> 30) & 0x03)
148
149 #define WRITE_FIDVID(fid, vid, ctrl)    \
150         wrmsr(MSR_AMDK7_FIDVID_CTL,     \
151             (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
152
153 #define COUNT_OFF_IRT(irt)      DELAY(10 * (1 << (irt)))
154 #define COUNT_OFF_VST(vst)      DELAY(20 * (vst))
155
156 #define FID_TO_VCO_FID(fid)     \
157         (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
158
159 /*
160  * Divide each value by 10 to get the processor multiplier.
161  * Some of those tables are the same as the Linux powernow-k7
162  * implementation by Dave Jones.
163  */
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,
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         {0, 0}
264 };
265
266 static devclass_t pn_devclass;
267 static driver_t pn_driver = {
268         "powernow",
269         pn_methods,
270         sizeof(struct pn_softc),
271 };
272
273 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
274
275 static int
276 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
277 {
278         int cfid, cvid;
279         uint64_t status, ctl;
280
281         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
282         cfid = PN7_STA_CFID(status);
283         cvid = PN7_STA_CVID(status);
284
285         /* We're already at the requested level. */
286         if (fid == cfid && vid == cvid)
287                 return (0);
288
289         ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
290
291         ctl |= PN7_CTR_FID(fid);
292         ctl |= PN7_CTR_VID(vid);
293         ctl |= PN7_CTR_SGTC(sc->sgtc);
294
295         if (sc->errata & A0_ERRATA)
296                 disable_intr();
297
298         if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
299                 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
300                 if (vid != cvid)
301                         wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
302         } else {
303                 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
304                 if (fid != cfid)
305                         wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
306         }
307
308         if (sc->errata & A0_ERRATA)
309                 enable_intr();
310
311         return (0);
312 }
313
314 static int
315 pn8_read_pending_wait(uint64_t *status)
316 {
317         int i = 10000;
318
319         do
320                 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
321         while (PN8_STA_PENDING(*status) && --i);
322
323         return (i == 0 ? ENXIO : 0);
324 }
325
326 static int
327 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
328 {
329         int i = 100;
330
331         do
332                 WRITE_FIDVID(fid, vid, ctrl);
333         while (pn8_read_pending_wait(status) && --i);
334
335         return (i == 0 ? ENXIO : 0);
336 }
337
338 static int
339 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
340 {
341         uint64_t status;
342         int cfid, cvid;
343         int rvo;
344         int rv;
345         u_int val;
346
347         rv = pn8_read_pending_wait(&status);
348         if (rv)
349                 return (rv);
350
351         cfid = PN8_STA_CFID(status);
352         cvid = PN8_STA_CVID(status);
353
354         if (fid == cfid && vid == cvid)
355                 return (0);
356
357         /*
358          * Phase 1: Raise core voltage to requested VID if frequency is
359          * going up.
360          */
361         while (cvid > vid) {
362                 val = cvid - (1 << sc->mvs);
363                 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
364                 if (rv) {
365                         sc->errata |= PENDING_STUCK;
366                         return (rv);
367                 }
368                 cvid = PN8_STA_CVID(status);
369                 COUNT_OFF_VST(sc->vst);
370         }
371
372         /* ... then raise to voltage + RVO (if required) */
373         for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
374                 /* XXX It's not clear from spec if we have to do that
375                  * in 0.25 step or in MVS.  Therefore do it as it's done
376                  * under Linux */
377                 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
378                 if (rv) {
379                         sc->errata |= PENDING_STUCK;
380                         return (rv);
381                 }
382                 cvid = PN8_STA_CVID(status);
383                 COUNT_OFF_VST(sc->vst);
384         }
385
386         /* Phase 2: change to requested core frequency */
387         if (cfid != fid) {
388                 u_int vco_fid, vco_cfid, fid_delta;
389
390                 vco_fid = FID_TO_VCO_FID(fid);
391                 vco_cfid = FID_TO_VCO_FID(cfid);
392
393                 while (abs(vco_fid - vco_cfid) > 2) {
394                         fid_delta = (vco_cfid & 1) ? 1 : 2;
395                         if (fid > cfid) {
396                                 if (cfid > 7)
397                                         val = cfid + fid_delta;
398                                 else
399                                         val = FID_TO_VCO_FID(cfid) + fid_delta;
400                         } else
401                                 val = cfid - fid_delta;
402                         rv = pn8_write_fidvid(val, cvid,
403                             sc->pll * (uint64_t) sc->fsb,
404                             &status);
405                         if (rv) {
406                                 sc->errata |= PENDING_STUCK;
407                                 return (rv);
408                         }
409                         cfid = PN8_STA_CFID(status);
410                         COUNT_OFF_IRT(sc->irt);
411
412                         vco_cfid = FID_TO_VCO_FID(cfid);
413                 }
414
415                 rv = pn8_write_fidvid(fid, cvid,
416                     sc->pll * (uint64_t) sc->fsb,
417                     &status);
418                 if (rv) {
419                         sc->errata |= PENDING_STUCK;
420                         return (rv);
421                 }
422                 cfid = PN8_STA_CFID(status);
423                 COUNT_OFF_IRT(sc->irt);
424         }
425
426         /* Phase 3: change to requested voltage */
427         if (cvid != vid) {
428                 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
429                 cvid = PN8_STA_CVID(status);
430                 COUNT_OFF_VST(sc->vst);
431         }
432
433         /* Check if transition failed. */
434         if (cfid != fid || cvid != vid)
435                 rv = ENXIO;
436
437         return (rv);
438 }
439
440 static int
441 pn_set(device_t dev, const struct cf_setting *cf)
442 {
443         struct pn_softc *sc;
444         int fid, vid;
445         int i;
446         int rv;
447
448         if (cf == NULL)
449                 return (EINVAL);
450         sc = device_get_softc(dev);
451
452         if (sc->errata & PENDING_STUCK)
453                 return (ENXIO);
454
455         for (i = 0; i < sc->powernow_max_states; ++i)
456                 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
457                         break;
458
459         fid = sc->powernow_states[i].fid;
460         vid = sc->powernow_states[i].vid;
461
462         rv = ENODEV;
463
464         switch (sc->pn_type) {
465         case PN7_TYPE:
466                 rv = pn7_setfidvid(sc, fid, vid);
467                 break;
468         case PN8_TYPE:
469                 rv = pn8_setfidvid(sc, fid, vid);
470                 break;
471         }
472
473         return (rv);
474 }
475
476 static int
477 pn_get(device_t dev, struct cf_setting *cf)
478 {
479         struct pn_softc *sc;
480         u_int cfid = 0, cvid = 0;
481         int i;
482         uint64_t status;
483
484         if (cf == NULL)
485                 return (EINVAL);
486         sc = device_get_softc(dev);
487         if (sc->errata & PENDING_STUCK)
488                 return (ENXIO);
489
490         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
491
492         switch (sc->pn_type) {
493         case PN7_TYPE:
494                 cfid = PN7_STA_CFID(status);
495                 cvid = PN7_STA_CVID(status);
496                 break;
497         case PN8_TYPE:
498                 cfid = PN8_STA_CFID(status);
499                 cvid = PN8_STA_CVID(status);
500                 break;
501         }
502         for (i = 0; i < sc->powernow_max_states; ++i)
503                 if (cfid == sc->powernow_states[i].fid &&
504                     cvid == sc->powernow_states[i].vid)
505                         break;
506
507         if (i < sc->powernow_max_states) {
508                 cf->freq = sc->powernow_states[i].freq / 1000;
509                 cf->power = sc->powernow_states[i].power;
510                 cf->lat = 200;
511                 cf->volts = sc->vid_to_volts[cvid];
512                 cf->dev = dev;
513         } else {
514                 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
515                 cf->dev = NULL;
516         }
517
518         return (0);
519 }
520
521 static int
522 pn_settings(device_t dev, struct cf_setting *sets, int *count)
523 {
524         struct pn_softc *sc;
525         int i;
526
527         if (sets == NULL|| count == NULL)
528                 return (EINVAL);
529         sc = device_get_softc(dev);
530         if (*count < sc->powernow_max_states)
531                 return (E2BIG);
532         for (i = 0; i < sc->powernow_max_states; ++i) {
533                 sets[i].freq = sc->powernow_states[i].freq / 1000;
534                 sets[i].power = sc->powernow_states[i].power;
535                 sets[i].lat = 200;
536                 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
537                 sets[i].dev = dev;
538         }
539         *count = sc->powernow_max_states;
540
541         return (0);
542 }
543
544 static int
545 pn_type(device_t dev, int *type)
546 {
547         if (type == NULL)
548                 return (EINVAL);
549
550         *type = CPUFREQ_TYPE_ABSOLUTE;
551
552         return (0);
553 }
554
555 /*
556  * Given a set of pair of fid/vid, and number of performance states,
557  * compute powernow_states via an insertion sort.
558  */
559 static int
560 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
561 {
562         int i, j, n;
563         struct powernow_state state;
564
565         for (i = 0; i < POWERNOW_MAX_STATES; ++i)
566                 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
567
568         for (n = 0, i = 0; i < npstates; ++i) {
569                 state.fid = *p++;
570                 state.vid = *p++;
571                 state.power = CPUFREQ_VAL_UNKNOWN;
572
573                 switch (sc->pn_type) {
574                 case PN7_TYPE:
575                         state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
576                         if ((sc->errata & A0_ERRATA) &&
577                             (pn7_fid_to_mult[state.fid] % 10) == 5)
578                                 continue;
579                         break;
580                 case PN8_TYPE:
581                         state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
582                         break;
583                 }
584
585                 j = n;
586                 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
587                         memcpy(&sc->powernow_states[j],
588                             &sc->powernow_states[j - 1],
589                             sizeof(struct powernow_state));
590                         --j;
591                 }
592                 memcpy(&sc->powernow_states[j], &state,
593                     sizeof(struct powernow_state));
594                 ++n;
595         }
596
597         /*
598          * Fix powernow_max_states, if errata a0 give us less states
599          * than expected.
600          */
601         sc->powernow_max_states = n;
602
603         if (bootverbose)
604                 for (i = 0; i < sc->powernow_max_states; ++i) {
605                         int fid = sc->powernow_states[i].fid;
606                         int vid = sc->powernow_states[i].vid;
607
608                         printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
609                             i,
610                             sc->powernow_states[i].freq,
611                             fid,
612                             vid);
613                 }
614
615         return (0);
616 }
617
618 static int
619 cpuid_is_k7(u_int cpuid)
620 {
621
622         switch (cpuid) {
623         case 0x760:
624         case 0x761:
625         case 0x762:
626         case 0x770:
627         case 0x771:
628         case 0x780:
629         case 0x781:
630         case 0x7a0:
631                 return (TRUE);
632         }
633         return (FALSE);
634 }
635
636 static int
637 pn_decode_pst(device_t dev)
638 {
639         int maxpst;
640         struct pn_softc *sc;
641         u_int cpuid, maxfid, startvid;
642         u_long sig;
643         struct psb_header *psb;
644         uint8_t *p;
645         u_int regs[4];
646         uint64_t status;
647
648         sc = device_get_softc(dev);
649
650         do_cpuid(0x80000001, regs);
651         cpuid = regs[0];
652
653         if ((cpuid & 0xfff) == 0x760)
654                 sc->errata |= A0_ERRATA;
655
656         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
657
658         switch (sc->pn_type) {
659         case PN7_TYPE:
660                 maxfid = PN7_STA_MFID(status);
661                 startvid = PN7_STA_SVID(status);
662                 break;
663         case PN8_TYPE:
664                 maxfid = PN8_STA_MFID(status);
665                 /*
666                  * we should actually use a variable named 'maxvid' if K8,
667                  * but why introducing a new variable for that?
668                  */
669                 startvid = PN8_STA_MVID(status);
670                 break;
671         default:
672                 return (ENODEV);
673         }
674
675         if (bootverbose) {
676                 device_printf(dev, "STATUS: 0x%jx\n", status);
677                 device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
678                 device_printf(dev, "STATUS: %s: 0x%02x\n",
679                     sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
680                     startvid);
681         }
682
683         sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
684         if (sig) {
685                 struct pst_header *pst;
686
687                 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
688
689                 switch (psb->version) {
690                 default:
691                         return (ENODEV);
692                 case 0x14:
693                         /*
694                          * We can't be picky about numpst since at least
695                          * some systems have a value of 1 and some have 2.
696                          * We trust that cpuid_is_k7() will be better at
697                          * catching that we're on a K8 anyway.
698                          */
699                         if (sc->pn_type != PN8_TYPE)
700                                 return (EINVAL);
701                         sc->vst = psb->settlingtime;
702                         sc->rvo = PN8_PSB_TO_RVO(psb->res1);
703                         sc->irt = PN8_PSB_TO_IRT(psb->res1);
704                         sc->mvs = PN8_PSB_TO_MVS(psb->res1);
705                         sc->low = PN8_PSB_TO_BATT(psb->res1);
706                         if (bootverbose) {
707                                 device_printf(dev, "PSB: VST: %d\n",
708                                     psb->settlingtime);
709                                 device_printf(dev, "PSB: RVO %x IRT %d "
710                                     "MVS %d BATT %d\n",
711                                     sc->rvo,
712                                     sc->irt,
713                                     sc->mvs,
714                                     sc->low);
715                         }
716                         break;
717                 case 0x12:
718                         if (sc->pn_type != PN7_TYPE)
719                                 return (EINVAL);
720                         sc->sgtc = psb->settlingtime * sc->fsb;
721                         if (sc->sgtc < 100 * sc->fsb)
722                                 sc->sgtc = 100 * sc->fsb;
723                         break;
724                 }
725
726                 p = ((uint8_t *) psb) + sizeof(struct psb_header);
727                 pst = (struct pst_header*) p;
728
729                 maxpst = 200;
730
731                 do {
732                         struct pst_header *pst = (struct pst_header*) p;
733
734                         if (cpuid == pst->cpuid &&
735                             maxfid == pst->maxfid &&
736                             startvid == pst->startvid) {
737                                 sc->powernow_max_states = pst->numpstates;
738                                 switch (sc->pn_type) {
739                                 case PN7_TYPE:
740                                         if (abs(sc->fsb - pst->fsb) > 5)
741                                                 continue;
742                                         break;
743                                 case PN8_TYPE:
744                                         break;
745                                 }
746                                 return (decode_pst(sc,
747                                     p + sizeof(struct pst_header),
748                                     sc->powernow_max_states));
749                         }
750
751                         p += sizeof(struct pst_header) + (2 * pst->numpstates);
752                 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
753
754                 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
755         }
756
757         return (ENODEV);
758 }
759
760 static int
761 pn_decode_acpi(device_t dev, device_t perf_dev)
762 {
763         int i, j, n;
764         uint64_t status;
765         uint32_t ctrl;
766         u_int cpuid;
767         u_int regs[4];
768         struct pn_softc *sc;
769         struct powernow_state state;
770         struct cf_setting sets[POWERNOW_MAX_STATES];
771         int count = POWERNOW_MAX_STATES;
772         int type;
773         int rv;
774
775         if (perf_dev == NULL)
776                 return (ENXIO);
777
778         rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
779         if (rv)
780                 return (ENXIO);
781         rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
782         if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
783                 return (ENXIO);
784
785         sc = device_get_softc(dev);
786
787         do_cpuid(0x80000001, regs);
788         cpuid = regs[0];
789         if ((cpuid & 0xfff) == 0x760)
790                 sc->errata |= A0_ERRATA;
791
792         ctrl = 0;
793         sc->sgtc = 0;
794         for (n = 0, i = 0; i < count; ++i) {
795                 ctrl = sets[i].spec[PX_SPEC_CONTROL];
796                 switch (sc->pn_type) {
797                 case PN7_TYPE:
798                         state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
799                         state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
800                         if ((sc->errata & A0_ERRATA) &&
801                             (pn7_fid_to_mult[state.fid] % 10) == 5)
802                                 continue;
803                         break;
804                 case PN8_TYPE:
805                         state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
806                         state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
807                         break;
808                 }
809                 state.freq = sets[i].freq * 1000;
810                 state.power = sets[i].power;
811
812                 j = n;
813                 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
814                         memcpy(&sc->powernow_states[j],
815                             &sc->powernow_states[j - 1],
816                             sizeof(struct powernow_state));
817                         --j;
818                 }
819                 memcpy(&sc->powernow_states[j], &state,
820                     sizeof(struct powernow_state));
821                 ++n;
822         }
823
824         sc->powernow_max_states = n;
825         state = sc->powernow_states[0];
826         status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
827
828         switch (sc->pn_type) {
829         case PN7_TYPE:
830                 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
831                 /*
832                  * XXX Some bios forget the max frequency!
833                  * This maybe indicates we have the wrong tables.  Therefore,
834                  * don't implement a quirk, but fallback to BIOS legacy
835                  * tables instead.
836                  */
837                 if (PN7_STA_MFID(status) != state.fid) {
838                         device_printf(dev, "ACPI MAX frequency not found\n");
839                         return (EINVAL);
840                 }
841                 sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
842                 break;
843         case PN8_TYPE:
844                 sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
845                 sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
846                 sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
847                 sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
848                 sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
849                 sc->low = 0; /* XXX */
850
851                 /*
852                  * powernow k8 supports only one low frequency.
853                  */
854                 if (sc->powernow_max_states >= 2 &&
855                     (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
856                         return (EINVAL);
857                 sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
858                 break;
859         }
860
861         return (0);
862 }
863
864 static void
865 pn_identify(driver_t *driver, device_t parent)
866 {
867
868         if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
869                 return;
870         switch (cpu_id & 0xf00) {
871         case 0x600:
872         case 0xf00:
873                 break;
874         default:
875                 return;
876         }
877         if (device_find_child(parent, "powernow", -1) != NULL)
878                 return;
879         if (BUS_ADD_CHILD(parent, 10, "powernow", device_get_unit(parent))
880             == 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 }