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