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", -1) == NULL)
880 device_printf(parent, "powernow: add child failed\n");
881 }
882
883 static int
884 pn_probe(device_t dev)
885 {
886 struct pn_softc *sc;
887 uint64_t status;
888 uint64_t rate;
889 struct pcpu *pc;
890 u_int sfid, mfid, cfid;
891
892 sc = device_get_softc(dev);
893 sc->errata = 0;
894 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
895
896 pc = cpu_get_pcpu(dev);
897 if (pc == NULL)
898 return (ENODEV);
899
900 cpu_est_clockrate(pc->pc_cpuid, &rate);
901
902 switch (cpu_id & 0xf00) {
903 case 0x600:
904 sfid = PN7_STA_SFID(status);
905 mfid = PN7_STA_MFID(status);
906 cfid = PN7_STA_CFID(status);
907 sc->pn_type = PN7_TYPE;
908 sc->fsb = rate / 100000 / pn7_fid_to_mult[cfid];
909
910 /*
911 * If start FID is different to max FID, then it is a
912 * mobile processor. If not, it is a low powered desktop
913 * processor.
914 */
915 if (PN7_STA_SFID(status) != PN7_STA_MFID(status)) {
916 sc->vid_to_volts = pn7_mobile_vid_to_volts;
917 device_set_desc(dev, "PowerNow! K7");
918 } else {
919 sc->vid_to_volts = pn7_desktop_vid_to_volts;
920 device_set_desc(dev, "Cool`n'Quiet K7");
921 }
922 break;
923
924 case 0xf00:
925 sfid = PN8_STA_SFID(status);
926 mfid = PN8_STA_MFID(status);
927 cfid = PN8_STA_CFID(status);
928 sc->pn_type = PN8_TYPE;
929 sc->vid_to_volts = pn8_vid_to_volts;
930 sc->fsb = rate / 100000 / pn8_fid_to_mult[cfid];
931
932 if (PN8_STA_SFID(status) != PN8_STA_MFID(status))
933 device_set_desc(dev, "PowerNow! K8");
934 else
935 device_set_desc(dev, "Cool`n'Quiet K8");
936 break;
937 default:
938 return (ENODEV);
939 }
940
941 return (0);
942 }
943
944 static int
945 pn_attach(device_t dev)
946 {
947 int rv;
948 device_t child;
949
950 child = device_find_child(device_get_parent(dev), "acpi_perf", -1);
951 if (child) {
952 rv = pn_decode_acpi(dev, child);
953 if (rv)
954 rv = pn_decode_pst(dev);
955 } else
956 rv = pn_decode_pst(dev);
957
958 if (rv != 0)
959 return (ENXIO);
960 cpufreq_register(dev);
961 return (0);
962 }
963
964 static int
965 pn_detach(device_t dev)
966 {
967
968 return (cpufreq_unregister(dev));
969 }
Cache object: 226fec25405b650299804a9d4922eaab
|