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/clock.h>
48 #include <machine/vmparam.h>
49 #include <sys/rman.h>
50
51 #include <vm/vm.h>
52 #include <vm/pmap.h>
53
54 #include "cpufreq_if.h"
55
56 #define PN7_TYPE 0
57 #define PN8_TYPE 1
58
59 /* Legacy configuration via BIOS table PSB. */
60 #define PSB_START 0
61 #define PSB_STEP 0x10
62 #define PSB_SIG "AMDK7PNOW!"
63 #define PSB_LEN 10
64 #define PSB_OFF 0
65
66 struct psb_header {
67 char signature[10];
68 uint8_t version;
69 uint8_t flags;
70 uint16_t settlingtime;
71 uint8_t res1;
72 uint8_t numpst;
73 } __packed;
74
75 struct pst_header {
76 uint32_t cpuid;
77 uint8_t fsb;
78 uint8_t maxfid;
79 uint8_t startvid;
80 uint8_t numpstates;
81 } __packed;
82
83 /*
84 * MSRs and bits used by Powernow technology
85 */
86 #define MSR_AMDK7_FIDVID_CTL 0xc0010041
87 #define MSR_AMDK7_FIDVID_STATUS 0xc0010042
88
89 /* Bitfields used by K7 */
90
91 #define PN7_CTR_FID(x) ((x) & 0x1f)
92 #define PN7_CTR_VID(x) (((x) & 0x1f) << 8)
93 #define PN7_CTR_FIDC 0x00010000
94 #define PN7_CTR_VIDC 0x00020000
95 #define PN7_CTR_FIDCHRATIO 0x00100000
96 #define PN7_CTR_SGTC(x) (((uint64_t)(x) & 0x000fffff) << 32)
97
98 #define PN7_STA_CFID(x) ((x) & 0x1f)
99 #define PN7_STA_SFID(x) (((x) >> 8) & 0x1f)
100 #define PN7_STA_MFID(x) (((x) >> 16) & 0x1f)
101 #define PN7_STA_CVID(x) (((x) >> 32) & 0x1f)
102 #define PN7_STA_SVID(x) (((x) >> 40) & 0x1f)
103 #define PN7_STA_MVID(x) (((x) >> 48) & 0x1f)
104
105 /* ACPI ctr_val status register to powernow k7 configuration */
106 #define ACPI_PN7_CTRL_TO_FID(x) ((x) & 0x1f)
107 #define ACPI_PN7_CTRL_TO_VID(x) (((x) >> 5) & 0x1f)
108 #define ACPI_PN7_CTRL_TO_SGTC(x) (((x) >> 10) & 0xffff)
109
110 /* Bitfields used by K8 */
111
112 #define PN8_CTR_FID(x) ((x) & 0x3f)
113 #define PN8_CTR_VID(x) (((x) & 0x1f) << 8)
114 #define PN8_CTR_PENDING(x) (((x) & 1) << 32)
115
116 #define PN8_STA_CFID(x) ((x) & 0x3f)
117 #define PN8_STA_SFID(x) (((x) >> 8) & 0x3f)
118 #define PN8_STA_MFID(x) (((x) >> 16) & 0x3f)
119 #define PN8_STA_PENDING(x) (((x) >> 31) & 0x01)
120 #define PN8_STA_CVID(x) (((x) >> 32) & 0x1f)
121 #define PN8_STA_SVID(x) (((x) >> 40) & 0x1f)
122 #define PN8_STA_MVID(x) (((x) >> 48) & 0x1f)
123
124 /* Reserved1 to powernow k8 configuration */
125 #define PN8_PSB_TO_RVO(x) ((x) & 0x03)
126 #define PN8_PSB_TO_IRT(x) (((x) >> 2) & 0x03)
127 #define PN8_PSB_TO_MVS(x) (((x) >> 4) & 0x03)
128 #define PN8_PSB_TO_BATT(x) (((x) >> 6) & 0x03)
129
130 /* ACPI ctr_val status register to powernow k8 configuration */
131 #define ACPI_PN8_CTRL_TO_FID(x) ((x) & 0x3f)
132 #define ACPI_PN8_CTRL_TO_VID(x) (((x) >> 6) & 0x1f)
133 #define ACPI_PN8_CTRL_TO_VST(x) (((x) >> 11) & 0x1f)
134 #define ACPI_PN8_CTRL_TO_MVS(x) (((x) >> 18) & 0x03)
135 #define ACPI_PN8_CTRL_TO_PLL(x) (((x) >> 20) & 0x7f)
136 #define ACPI_PN8_CTRL_TO_RVO(x) (((x) >> 28) & 0x03)
137 #define ACPI_PN8_CTRL_TO_IRT(x) (((x) >> 30) & 0x03)
138
139
140 #define WRITE_FIDVID(fid, vid, ctrl) \
141 wrmsr(MSR_AMDK7_FIDVID_CTL, \
142 (((ctrl) << 32) | (1ULL << 16) | ((vid) << 8) | (fid)))
143
144 #define READ_PENDING_WAIT(status) \
145 do { \
146 (status) = rdmsr(MSR_AMDK7_FIDVID_STATUS); \
147 } while (PN8_STA_PENDING(status))
148
149 #define COUNT_OFF_IRT(irt) DELAY(10 * (1 << (irt)))
150 #define COUNT_OFF_VST(vst) DELAY(20 * (vst))
151
152 #define FID_TO_VCO_FID(fid) \
153 (((fid) < 8) ? (8 + ((fid) << 1)) : (fid))
154
155 /*
156 * Divide each value by 10 to get the processor multiplier.
157 * Some of those tables are the same as the Linux powernow-k7
158 * implementation by Dave Jones.
159 */
160 static int pn7_fid_to_mult[32] = {
161 110, 115, 120, 125, 50, 55, 60, 65,
162 70, 75, 80, 85, 90, 95, 100, 105,
163 30, 190, 40, 200, 130, 135, 140, 210,
164 150, 225, 160, 165, 170, 180, 0, 0,
165 };
166
167
168 static int pn8_fid_to_mult[32] = {
169 40, 50, 60, 70, 80, 90, 100, 110,
170 120, 130, 140, 150, 160, 170, 180, 190,
171 220, 230, 240, 250, 260, 270, 280, 290,
172 300, 310, 320, 330, 340, 350,
173 };
174
175 /*
176 * Units are in mV.
177 */
178 /* Mobile VRM (K7) */
179 static int pn7_mobile_vid_to_volts[] = {
180 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
181 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
182 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
183 1075, 1050, 1025, 1000, 975, 950, 925, 0,
184 };
185 /* Desktop VRM (K7) */
186 static int pn7_desktop_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 and Mobile VRM (K8) */
193 static int pn8_vid_to_volts[] = {
194 1550, 1525, 1500, 1475, 1450, 1425, 1400, 1375,
195 1350, 1325, 1300, 1275, 1250, 1225, 1200, 1175,
196 1150, 1125, 1100, 1075, 1050, 1025, 1000, 975,
197 950, 925, 900, 875, 850, 825, 800, 0,
198 };
199
200 #define POWERNOW_MAX_STATES 16
201
202 struct powernow_state {
203 int freq;
204 int power;
205 int fid;
206 int vid;
207 };
208
209 struct pn_softc {
210 device_t dev;
211 int pn_type;
212 struct powernow_state powernow_states[POWERNOW_MAX_STATES];
213 u_int fsb;
214 u_int sgtc;
215 u_int vst;
216 u_int mvs;
217 u_int pll;
218 u_int rvo;
219 u_int irt;
220 int low;
221 int powernow_max_states;
222 u_int powernow_state;
223 int errata_a0;
224 int *vid_to_volts;
225 };
226
227 /*
228 * Offsets in struct cf_setting array for private values given by
229 * acpi_perf driver.
230 */
231 #define PX_SPEC_CONTROL 0
232 #define PX_SPEC_STATUS 1
233
234 static void pn_identify(driver_t *driver, device_t parent);
235 static int pn_probe(device_t dev);
236 static int pn_attach(device_t dev);
237 static int pn_detach(device_t dev);
238 static int pn_set(device_t dev, const struct cf_setting *cf);
239 static int pn_get(device_t dev, struct cf_setting *cf);
240 static int pn_settings(device_t dev, struct cf_setting *sets,
241 int *count);
242 static int pn_type(device_t dev, int *type);
243
244 static device_method_t pn_methods[] = {
245 /* Device interface */
246 DEVMETHOD(device_identify, pn_identify),
247 DEVMETHOD(device_probe, pn_probe),
248 DEVMETHOD(device_attach, pn_attach),
249 DEVMETHOD(device_detach, pn_detach),
250
251 /* cpufreq interface */
252 DEVMETHOD(cpufreq_drv_set, pn_set),
253 DEVMETHOD(cpufreq_drv_get, pn_get),
254 DEVMETHOD(cpufreq_drv_settings, pn_settings),
255 DEVMETHOD(cpufreq_drv_type, pn_type),
256
257 {0, 0}
258 };
259
260 static devclass_t pn_devclass;
261 static driver_t pn_driver = {
262 "powernow",
263 pn_methods,
264 sizeof(struct pn_softc),
265 };
266
267 DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0);
268
269 static int
270 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
271 {
272 int cfid, cvid;
273 uint64_t status, ctl;
274
275 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
276 cfid = PN7_STA_CFID(status);
277 cvid = PN7_STA_CVID(status);
278
279 /* We're already at the requested level. */
280 if (fid == cfid && vid == cvid)
281 return (0);
282
283 ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
284
285 ctl |= PN7_CTR_FID(fid);
286 ctl |= PN7_CTR_VID(vid);
287 ctl |= PN7_CTR_SGTC(sc->sgtc);
288
289 if (sc->errata_a0)
290 disable_intr();
291
292 if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
293 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
294 if (vid != cvid)
295 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
296 } else {
297 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
298 if (fid != cfid)
299 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
300 }
301
302 if (sc->errata_a0)
303 enable_intr();
304
305 return (0);
306 }
307
308 static int
309 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
310 {
311 uint64_t status;
312 int cfid, cvid;
313 int rvo;
314 u_int val;
315
316 READ_PENDING_WAIT(status);
317 cfid = PN8_STA_CFID(status);
318 cvid = PN8_STA_CVID(status);
319
320 if (fid == cfid && vid == cvid)
321 return (0);
322
323 /*
324 * Phase 1: Raise core voltage to requested VID if frequency is
325 * going up.
326 */
327 while (cvid > vid) {
328 val = cvid - (1 << sc->mvs);
329 WRITE_FIDVID(cfid, (val > 0) ? val : 0, 1ULL);
330 READ_PENDING_WAIT(status);
331 cvid = PN8_STA_CVID(status);
332 COUNT_OFF_VST(sc->vst);
333 }
334
335 /* ... then raise to voltage + RVO (if required) */
336 for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
337 /* XXX It's not clear from spec if we have to do that
338 * in 0.25 step or in MVS. Therefore do it as it's done
339 * under Linux */
340 WRITE_FIDVID(cfid, cvid - 1, 1ULL);
341 READ_PENDING_WAIT(status);
342 cvid = PN8_STA_CVID(status);
343 COUNT_OFF_VST(sc->vst);
344 }
345
346 /* Phase 2: change to requested core frequency */
347 if (cfid != fid) {
348 u_int vco_fid, vco_cfid;
349
350 vco_fid = FID_TO_VCO_FID(fid);
351 vco_cfid = FID_TO_VCO_FID(cfid);
352
353 while (abs(vco_fid - vco_cfid) > 2) {
354 if (fid > cfid) {
355 if (cfid > 6)
356 val = cfid + 2;
357 else
358 val = FID_TO_VCO_FID(cfid) + 2;
359 } else
360 val = cfid - 2;
361 WRITE_FIDVID(val, cvid, sc->pll * (uint64_t) sc->fsb);
362 READ_PENDING_WAIT(status);
363 cfid = PN8_STA_CFID(status);
364 COUNT_OFF_IRT(sc->irt);
365
366 vco_cfid = FID_TO_VCO_FID(cfid);
367 }
368
369 WRITE_FIDVID(fid, cvid, sc->pll * (uint64_t) sc->fsb);
370 READ_PENDING_WAIT(status);
371 cfid = PN8_STA_CFID(status);
372 COUNT_OFF_IRT(sc->irt);
373 }
374
375 /* Phase 3: change to requested voltage */
376 if (cvid != vid) {
377 WRITE_FIDVID(cfid, vid, 1ULL);
378 READ_PENDING_WAIT(status);
379 cvid = PN8_STA_CVID(status);
380 COUNT_OFF_VST(sc->vst);
381 }
382
383 /* Check if transition failed. */
384 if (cfid != fid || cvid != vid)
385 return (ENXIO);
386
387 return (0);
388 }
389
390 static int
391 pn_set(device_t dev, const struct cf_setting *cf)
392 {
393 struct pn_softc *sc;
394 int fid, vid;
395 int i;
396 int rv;
397
398 if (cf == NULL)
399 return (EINVAL);
400 sc = device_get_softc(dev);
401
402 for (i = 0; i < sc->powernow_max_states; ++i)
403 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
404 break;
405
406 fid = sc->powernow_states[i].fid;
407 vid = sc->powernow_states[i].vid;
408
409 rv = ENODEV;
410
411 switch (sc->pn_type) {
412 case PN7_TYPE:
413 rv = pn7_setfidvid(sc, fid, vid);
414 break;
415 case PN8_TYPE:
416 rv = pn8_setfidvid(sc, fid, vid);
417 break;
418 }
419
420 return (rv);
421 }
422
423 static int
424 pn_get(device_t dev, struct cf_setting *cf)
425 {
426 struct pn_softc *sc;
427 u_int cfid = 0, cvid = 0;
428 int i;
429 uint64_t status;
430
431 if (cf == NULL)
432 return (EINVAL);
433 sc = device_get_softc(dev);
434
435 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
436
437 switch (sc->pn_type) {
438 case PN7_TYPE:
439 cfid = PN7_STA_CFID(status);
440 cvid = PN7_STA_CVID(status);
441 break;
442 case PN8_TYPE:
443 cfid = PN8_STA_CFID(status);
444 cvid = PN8_STA_CVID(status);
445 break;
446 }
447 for (i = 0; i < sc->powernow_max_states; ++i)
448 if (cfid == sc->powernow_states[i].fid &&
449 cvid == sc->powernow_states[i].vid)
450 break;
451
452 if (i < sc->powernow_max_states) {
453 cf->freq = sc->powernow_states[i].freq / 1000;
454 cf->power = sc->powernow_states[i].power;
455 cf->lat = 200;
456 cf->volts = sc->vid_to_volts[cvid];
457 cf->dev = dev;
458 } else {
459 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
460 cf->dev = NULL;
461 }
462
463 return (0);
464 }
465
466 static int
467 pn_settings(device_t dev, struct cf_setting *sets, int *count)
468 {
469 struct pn_softc *sc;
470 int i;
471
472 if (sets == NULL|| count == NULL)
473 return (EINVAL);
474 sc = device_get_softc(dev);
475 if (*count < sc->powernow_max_states)
476 return (E2BIG);
477 for (i = 0; i < sc->powernow_max_states; ++i) {
478 sets[i].freq = sc->powernow_states[i].freq / 1000;
479 sets[i].power = sc->powernow_states[i].power;
480 sets[i].lat = 200;
481 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
482 sets[i].dev = dev;
483 }
484 *count = sc->powernow_max_states;
485
486 return (0);
487 }
488
489 static int
490 pn_type(device_t dev, int *type)
491 {
492 if (type == NULL)
493 return (EINVAL);
494
495 *type = CPUFREQ_TYPE_ABSOLUTE;
496
497 return (0);
498 }
499
500 /*
501 * Given a set of pair of fid/vid, and number of performance states,
502 * compute powernow_states via an insertion sort.
503 */
504 static int
505 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
506 {
507 int i, j, n;
508 struct powernow_state state;
509
510 for (i = 0; i < POWERNOW_MAX_STATES; ++i)
511 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
512
513 for (n = 0, i = 0; i < npstates; ++i) {
514 state.fid = *p++;
515 state.vid = *p++;
516 state.power = CPUFREQ_VAL_UNKNOWN;
517
518 switch (sc->pn_type) {
519 case PN7_TYPE:
520 state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
521 if (sc->errata_a0 &&
522 (pn7_fid_to_mult[state.fid] % 10) == 5)
523 continue;
524 break;
525 case PN8_TYPE:
526 state.freq = 100 * pn8_fid_to_mult[state.fid >> 1] *
527 sc->fsb;
528 break;
529 }
530
531 j = n;
532 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
533 memcpy(&sc->powernow_states[j],
534 &sc->powernow_states[j - 1],
535 sizeof(struct powernow_state));
536 --j;
537 }
538 memcpy(&sc->powernow_states[j], &state,
539 sizeof(struct powernow_state));
540 ++n;
541 }
542
543 /*
544 * Fix powernow_max_states, if errata_a0 give us less states
545 * than expected.
546 */
547 sc->powernow_max_states = n;
548
549 if (bootverbose)
550 for (i = 0; i < sc->powernow_max_states; ++i) {
551 int fid = sc->powernow_states[i].fid;
552 int vid = sc->powernow_states[i].vid;
553
554 printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
555 i,
556 sc->powernow_states[i].freq,
557 fid,
558 vid);
559 }
560
561 return (0);
562 }
563
564 static int
565 cpuid_is_k7(u_int cpuid)
566 {
567
568 switch (cpuid) {
569 case 0x760:
570 case 0x761:
571 case 0x762:
572 case 0x770:
573 case 0x771:
574 case 0x780:
575 case 0x781:
576 case 0x7a0:
577 return (TRUE);
578 }
579 return (FALSE);
580 }
581
582 static int
583 pn_decode_pst(device_t dev)
584 {
585 int maxpst;
586 struct pn_softc *sc;
587 u_int cpuid, maxfid, startvid;
588 u_long sig;
589 struct psb_header *psb;
590 uint8_t *p;
591 u_int regs[4];
592 uint64_t status;
593
594 sc = device_get_softc(dev);
595
596 do_cpuid(0x80000001, regs);
597 cpuid = regs[0];
598
599 if ((cpuid & 0xfff) == 0x760)
600 sc->errata_a0 = TRUE;
601
602 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
603
604 switch (sc->pn_type) {
605 case PN7_TYPE:
606 maxfid = PN7_STA_MFID(status);
607 startvid = PN7_STA_SVID(status);
608 break;
609 case PN8_TYPE:
610 maxfid = PN8_STA_MFID(status);
611 /*
612 * we should actually use a variable named 'maxvid' if K8,
613 * but why introducing a new variable for that?
614 */
615 startvid = PN8_STA_MVID(status);
616 break;
617 default:
618 return (ENODEV);
619 }
620
621 if (bootverbose) {
622 device_printf(dev, "STATUS: 0x%jx\n", status);
623 device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
624 device_printf(dev, "STATUS: %s: 0x%02x\n",
625 sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
626 startvid);
627 }
628
629 sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
630 if (sig) {
631 struct pst_header *pst;
632
633 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
634
635 switch (psb->version) {
636 default:
637 return (ENODEV);
638 case 0x14:
639 /*
640 * We can't be picky about numpst since at least
641 * some systems have a value of 1 and some have 2.
642 * We trust that cpuid_is_k7() will be better at
643 * catching that we're on a K8 anyway.
644 */
645 if (sc->pn_type != PN8_TYPE)
646 return (EINVAL);
647 sc->vst = psb->settlingtime;
648 sc->rvo = PN8_PSB_TO_RVO(psb->res1),
649 sc->irt = PN8_PSB_TO_IRT(psb->res1),
650 sc->mvs = PN8_PSB_TO_MVS(psb->res1),
651 sc->low = PN8_PSB_TO_BATT(psb->res1);
652 if (bootverbose) {
653 device_printf(dev, "PSB: VST: %d\n",
654 psb->settlingtime);
655 device_printf(dev, "PSB: RVO %x IRT %d "
656 "MVS %d BATT %d\n",
657 sc->rvo,
658 sc->irt,
659 sc->mvs,
660 sc->low);
661 }
662 break;
663 case 0x12:
664 if (sc->pn_type != PN7_TYPE)
665 return (EINVAL);
666 sc->sgtc = psb->settlingtime * sc->fsb;
667 if (sc->sgtc < 100 * sc->fsb)
668 sc->sgtc = 100 * sc->fsb;
669 break;
670 }
671
672 p = ((uint8_t *) psb) + sizeof(struct psb_header);
673 pst = (struct pst_header*) p;
674
675 maxpst = 200;
676
677 do {
678 struct pst_header *pst = (struct pst_header*) p;
679
680 if (cpuid == pst->cpuid &&
681 maxfid == pst->maxfid &&
682 startvid == pst->startvid) {
683 sc->powernow_max_states = pst->numpstates;
684 switch (sc->pn_type) {
685 case PN7_TYPE:
686 if (abs(sc->fsb - pst->fsb) > 5)
687 continue;
688 break;
689 case PN8_TYPE:
690 break;
691 }
692 return (decode_pst(sc,
693 p + sizeof(struct pst_header),
694 sc->powernow_max_states));
695 }
696
697 p += sizeof(struct pst_header) + (2 * pst->numpstates);
698 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
699
700 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
701 }
702
703 return (ENODEV);
704 }
705
706 /*
707 * TODO: this should be done in sys/ARCH/ARCH/identcpu.c
708 */
709 static int
710 cpu_is_powernow_capable(void)
711 {
712 u_int regs[4];
713
714 if (strcmp(cpu_vendor, "AuthenticAMD") != 0 ||
715 cpu_exthigh < 0x80000007)
716 return (FALSE);
717
718 do_cpuid(0x80000007, regs);
719 return (regs[3] & 0x6);
720 }
721
722 static int
723 pn_decode_acpi(device_t dev, device_t perf_dev)
724 {
725 int i, j, n;
726 uint64_t status;
727 uint32_t ctrl;
728 u_int cpuid;
729 u_int regs[4];
730 struct pn_softc *sc;
731 struct powernow_state state;
732 struct cf_setting sets[POWERNOW_MAX_STATES];
733 int count = POWERNOW_MAX_STATES;
734 int type;
735 int rv;
736
737 if (perf_dev == NULL)
738 return (ENXIO);
739
740 rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
741 if (rv)
742 return (ENXIO);
743 rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
744 if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
745 return (ENXIO);
746
747 sc = device_get_softc(dev);
748
749 do_cpuid(0x80000001, regs);
750 cpuid = regs[0];
751 if ((cpuid & 0xfff) == 0x760)
752 sc->errata_a0 = TRUE;
753
754 ctrl = 0;
755 sc->sgtc = 0;
756 for (n = 0, i = 0; i < count; ++i) {
757 ctrl = sets[i].spec[PX_SPEC_CONTROL];
758 switch (sc->pn_type) {
759 case PN7_TYPE:
760 state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
761 state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
762 if (sc->errata_a0 &&
763 (pn7_fid_to_mult[state.fid] % 10) == 5)
764 continue;
765 state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
766 break;
767 case PN8_TYPE:
768 state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
769 state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
770 state.freq = 100 * pn8_fid_to_mult[state.fid >> 1] *
771 sc->fsb;
772 break;
773 }
774
775 state.power = sets[i].power;
776
777 j = n;
778 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
779 memcpy(&sc->powernow_states[j],
780 &sc->powernow_states[j - 1],
781 sizeof(struct powernow_state));
782 --j;
783 }
784 memcpy(&sc->powernow_states[j], &state,
785 sizeof(struct powernow_state));
786 ++n;
787 }
788
789 sc->powernow_max_states = n;
790 state = sc->powernow_states[0];
791 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
792
793 switch (sc->pn_type) {
794 case PN7_TYPE:
795 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
796 /*
797 * XXX Some bios forget the max frequency!
798 * This maybe indicates we have the wrong tables. Therefore,
799 * don't implement a quirk, but fallback to BIOS legacy
800 * tables instead.
801 */
802 if (PN7_STA_MFID(status) != state.fid) {
803 device_printf(dev, "ACPI MAX frequency not found\n");
804 return (EINVAL);
805 }
806 break;
807 case PN8_TYPE:
808 sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
809 sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
810 sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
811 sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
812 sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
813 sc->low = 0; /* XXX */
814
815 /*
816 * powernow k8 supports only one low frequency.
817 */
818 if (sc->powernow_max_states >= 2 &&
819 (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
820 return (EINVAL);
821 break;
822 }
823
824 return (0);
825 }
826
827 static void
828 pn_identify(driver_t *driver, device_t parent)
829 {
830 device_t child;
831
832 if (cpu_is_powernow_capable() == 0)
833 return;
834 switch (cpu_id & 0xf00) {
835 case 0x600:
836 case 0xf00:
837 break;
838 default:
839 return;
840 }
841 if (device_find_child(parent, "powernow", -1) != NULL)
842 return;
843 if ((child = BUS_ADD_CHILD(parent, 0, "powernow", -1)) == NULL)
844 device_printf(parent, "powernow: add child failed\n");
845 }
846
847 static int
848 pn_probe(device_t dev)
849 {
850 struct pn_softc *sc;
851 uint64_t status;
852 uint64_t rate;
853 struct pcpu *pc;
854 u_int sfid, mfid, cfid;
855
856 sc = device_get_softc(dev);
857 sc->errata_a0 = FALSE;
858 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
859
860 pc = cpu_get_pcpu(dev);
861 if (pc == NULL)
862 return (ENODEV);
863
864 cpu_est_clockrate(pc->pc_cpuid, &rate);
865
866 switch (cpu_id & 0xf00) {
867 case 0x600:
868 sfid = PN7_STA_SFID(status);
869 mfid = PN7_STA_MFID(status);
870 cfid = PN7_STA_CFID(status);
871 sc->pn_type = PN7_TYPE;
872 sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];
873
874 /*
875 * If start FID is different to max FID, then it is a
876 * mobile processor. If not, it is a low powered desktop
877 * processor.
878 */
879 if (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
880 sc->vid_to_volts = pn7_mobile_vid_to_volts;
881 device_set_desc(dev, "PowerNow! K7");
882 } else {
883 sc->vid_to_volts = pn7_desktop_vid_to_volts;
884 device_set_desc(dev, "Cool`n'Quiet K7");
885 }
886 break;
887
888 case 0xf00:
889 sfid = PN8_STA_SFID(status);
890 mfid = PN8_STA_MFID(status);
891 cfid = PN8_STA_CFID(status);
892 sc->pn_type = PN8_TYPE;
893 sc->vid_to_volts = pn8_vid_to_volts;
894 sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid >> 1];
895
896 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
897 device_set_desc(dev, "PowerNow! K8");
898 else
899 device_set_desc(dev, "Cool`n'Quiet K8");
900 break;
901 default:
902 return (ENODEV);
903 }
904
905 return (0);
906 }
907
908 static int
909 pn_attach(device_t dev)
910 {
911 int rv;
912 device_t child;
913
914 child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
915 if (child) {
916 rv = pn_decode_acpi(dev, child);
917 if (rv)
918 rv = pn_decode_pst(dev);
919 } else
920 rv = pn_decode_pst(dev);
921
922 if (rv != 0)
923 return (ENXIO);
924 cpufreq_register(dev);
925 return (0);
926 }
927
928 static int
929 pn_detach(device_t dev)
930 {
931
932 cpufreq_unregister(dev);
933 return (0);
934 }
Cache object: cb2180e87f3facee0f8c20795472a328
|