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 driver_t pn_driver = {
267 "powernow",
268 pn_methods,
269 sizeof(struct pn_softc),
270 };
271
272 DRIVER_MODULE(powernow, cpu, pn_driver, 0, 0);
273
274 static int
275 pn7_setfidvid(struct pn_softc *sc, int fid, int vid)
276 {
277 int cfid, cvid;
278 uint64_t status, ctl;
279
280 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
281 cfid = PN7_STA_CFID(status);
282 cvid = PN7_STA_CVID(status);
283
284 /* We're already at the requested level. */
285 if (fid == cfid && vid == cvid)
286 return (0);
287
288 ctl = rdmsr(MSR_AMDK7_FIDVID_CTL) & PN7_CTR_FIDCHRATIO;
289
290 ctl |= PN7_CTR_FID(fid);
291 ctl |= PN7_CTR_VID(vid);
292 ctl |= PN7_CTR_SGTC(sc->sgtc);
293
294 if (sc->errata & A0_ERRATA)
295 disable_intr();
296
297 if (pn7_fid_to_mult[fid] < pn7_fid_to_mult[cfid]) {
298 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
299 if (vid != cvid)
300 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
301 } else {
302 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_VIDC);
303 if (fid != cfid)
304 wrmsr(MSR_AMDK7_FIDVID_CTL, ctl | PN7_CTR_FIDC);
305 }
306
307 if (sc->errata & A0_ERRATA)
308 enable_intr();
309
310 return (0);
311 }
312
313 static int
314 pn8_read_pending_wait(uint64_t *status)
315 {
316 int i = 10000;
317
318 do
319 *status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
320 while (PN8_STA_PENDING(*status) && --i);
321
322 return (i == 0 ? ENXIO : 0);
323 }
324
325 static int
326 pn8_write_fidvid(u_int fid, u_int vid, uint64_t ctrl, uint64_t *status)
327 {
328 int i = 100;
329
330 do
331 WRITE_FIDVID(fid, vid, ctrl);
332 while (pn8_read_pending_wait(status) && --i);
333
334 return (i == 0 ? ENXIO : 0);
335 }
336
337 static int
338 pn8_setfidvid(struct pn_softc *sc, int fid, int vid)
339 {
340 uint64_t status;
341 int cfid, cvid;
342 int rvo;
343 int rv;
344 u_int val;
345
346 rv = pn8_read_pending_wait(&status);
347 if (rv)
348 return (rv);
349
350 cfid = PN8_STA_CFID(status);
351 cvid = PN8_STA_CVID(status);
352
353 if (fid == cfid && vid == cvid)
354 return (0);
355
356 /*
357 * Phase 1: Raise core voltage to requested VID if frequency is
358 * going up.
359 */
360 while (cvid > vid) {
361 val = cvid - (1 << sc->mvs);
362 rv = pn8_write_fidvid(cfid, (val > 0) ? val : 0, 1ULL, &status);
363 if (rv) {
364 sc->errata |= PENDING_STUCK;
365 return (rv);
366 }
367 cvid = PN8_STA_CVID(status);
368 COUNT_OFF_VST(sc->vst);
369 }
370
371 /* ... then raise to voltage + RVO (if required) */
372 for (rvo = sc->rvo; rvo > 0 && cvid > 0; --rvo) {
373 /* XXX It's not clear from spec if we have to do that
374 * in 0.25 step or in MVS. Therefore do it as it's done
375 * under Linux */
376 rv = pn8_write_fidvid(cfid, cvid - 1, 1ULL, &status);
377 if (rv) {
378 sc->errata |= PENDING_STUCK;
379 return (rv);
380 }
381 cvid = PN8_STA_CVID(status);
382 COUNT_OFF_VST(sc->vst);
383 }
384
385 /* Phase 2: change to requested core frequency */
386 if (cfid != fid) {
387 u_int vco_fid, vco_cfid, fid_delta;
388
389 vco_fid = FID_TO_VCO_FID(fid);
390 vco_cfid = FID_TO_VCO_FID(cfid);
391
392 while (abs(vco_fid - vco_cfid) > 2) {
393 fid_delta = (vco_cfid & 1) ? 1 : 2;
394 if (fid > cfid) {
395 if (cfid > 7)
396 val = cfid + fid_delta;
397 else
398 val = FID_TO_VCO_FID(cfid) + fid_delta;
399 } else
400 val = cfid - fid_delta;
401 rv = pn8_write_fidvid(val, cvid,
402 sc->pll * (uint64_t) sc->fsb,
403 &status);
404 if (rv) {
405 sc->errata |= PENDING_STUCK;
406 return (rv);
407 }
408 cfid = PN8_STA_CFID(status);
409 COUNT_OFF_IRT(sc->irt);
410
411 vco_cfid = FID_TO_VCO_FID(cfid);
412 }
413
414 rv = pn8_write_fidvid(fid, cvid,
415 sc->pll * (uint64_t) sc->fsb,
416 &status);
417 if (rv) {
418 sc->errata |= PENDING_STUCK;
419 return (rv);
420 }
421 cfid = PN8_STA_CFID(status);
422 COUNT_OFF_IRT(sc->irt);
423 }
424
425 /* Phase 3: change to requested voltage */
426 if (cvid != vid) {
427 rv = pn8_write_fidvid(cfid, vid, 1ULL, &status);
428 cvid = PN8_STA_CVID(status);
429 COUNT_OFF_VST(sc->vst);
430 }
431
432 /* Check if transition failed. */
433 if (cfid != fid || cvid != vid)
434 rv = ENXIO;
435
436 return (rv);
437 }
438
439 static int
440 pn_set(device_t dev, const struct cf_setting *cf)
441 {
442 struct pn_softc *sc;
443 int fid, vid;
444 int i;
445 int rv;
446
447 if (cf == NULL)
448 return (EINVAL);
449 sc = device_get_softc(dev);
450
451 if (sc->errata & PENDING_STUCK)
452 return (ENXIO);
453
454 for (i = 0; i < sc->powernow_max_states; ++i)
455 if (CPUFREQ_CMP(sc->powernow_states[i].freq / 1000, cf->freq))
456 break;
457
458 fid = sc->powernow_states[i].fid;
459 vid = sc->powernow_states[i].vid;
460
461 rv = ENODEV;
462
463 switch (sc->pn_type) {
464 case PN7_TYPE:
465 rv = pn7_setfidvid(sc, fid, vid);
466 break;
467 case PN8_TYPE:
468 rv = pn8_setfidvid(sc, fid, vid);
469 break;
470 }
471
472 return (rv);
473 }
474
475 static int
476 pn_get(device_t dev, struct cf_setting *cf)
477 {
478 struct pn_softc *sc;
479 u_int cfid = 0, cvid = 0;
480 int i;
481 uint64_t status;
482
483 if (cf == NULL)
484 return (EINVAL);
485 sc = device_get_softc(dev);
486 if (sc->errata & PENDING_STUCK)
487 return (ENXIO);
488
489 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
490
491 switch (sc->pn_type) {
492 case PN7_TYPE:
493 cfid = PN7_STA_CFID(status);
494 cvid = PN7_STA_CVID(status);
495 break;
496 case PN8_TYPE:
497 cfid = PN8_STA_CFID(status);
498 cvid = PN8_STA_CVID(status);
499 break;
500 }
501 for (i = 0; i < sc->powernow_max_states; ++i)
502 if (cfid == sc->powernow_states[i].fid &&
503 cvid == sc->powernow_states[i].vid)
504 break;
505
506 if (i < sc->powernow_max_states) {
507 cf->freq = sc->powernow_states[i].freq / 1000;
508 cf->power = sc->powernow_states[i].power;
509 cf->lat = 200;
510 cf->volts = sc->vid_to_volts[cvid];
511 cf->dev = dev;
512 } else {
513 memset(cf, CPUFREQ_VAL_UNKNOWN, sizeof(*cf));
514 cf->dev = NULL;
515 }
516
517 return (0);
518 }
519
520 static int
521 pn_settings(device_t dev, struct cf_setting *sets, int *count)
522 {
523 struct pn_softc *sc;
524 int i;
525
526 if (sets == NULL|| count == NULL)
527 return (EINVAL);
528 sc = device_get_softc(dev);
529 if (*count < sc->powernow_max_states)
530 return (E2BIG);
531 for (i = 0; i < sc->powernow_max_states; ++i) {
532 sets[i].freq = sc->powernow_states[i].freq / 1000;
533 sets[i].power = sc->powernow_states[i].power;
534 sets[i].lat = 200;
535 sets[i].volts = sc->vid_to_volts[sc->powernow_states[i].vid];
536 sets[i].dev = dev;
537 }
538 *count = sc->powernow_max_states;
539
540 return (0);
541 }
542
543 static int
544 pn_type(device_t dev, int *type)
545 {
546 if (type == NULL)
547 return (EINVAL);
548
549 *type = CPUFREQ_TYPE_ABSOLUTE;
550
551 return (0);
552 }
553
554 /*
555 * Given a set of pair of fid/vid, and number of performance states,
556 * compute powernow_states via an insertion sort.
557 */
558 static int
559 decode_pst(struct pn_softc *sc, uint8_t *p, int npstates)
560 {
561 int i, j, n;
562 struct powernow_state state;
563
564 for (i = 0; i < POWERNOW_MAX_STATES; ++i)
565 sc->powernow_states[i].freq = CPUFREQ_VAL_UNKNOWN;
566
567 for (n = 0, i = 0; i < npstates; ++i) {
568 state.fid = *p++;
569 state.vid = *p++;
570 state.power = CPUFREQ_VAL_UNKNOWN;
571
572 switch (sc->pn_type) {
573 case PN7_TYPE:
574 state.freq = 100 * pn7_fid_to_mult[state.fid] * sc->fsb;
575 if ((sc->errata & A0_ERRATA) &&
576 (pn7_fid_to_mult[state.fid] % 10) == 5)
577 continue;
578 break;
579 case PN8_TYPE:
580 state.freq = 100 * pn8_fid_to_mult[state.fid] * sc->fsb;
581 break;
582 }
583
584 j = n;
585 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
586 memcpy(&sc->powernow_states[j],
587 &sc->powernow_states[j - 1],
588 sizeof(struct powernow_state));
589 --j;
590 }
591 memcpy(&sc->powernow_states[j], &state,
592 sizeof(struct powernow_state));
593 ++n;
594 }
595
596 /*
597 * Fix powernow_max_states, if errata a0 give us less states
598 * than expected.
599 */
600 sc->powernow_max_states = n;
601
602 if (bootverbose)
603 for (i = 0; i < sc->powernow_max_states; ++i) {
604 int fid = sc->powernow_states[i].fid;
605 int vid = sc->powernow_states[i].vid;
606
607 printf("powernow: %2i %8dkHz FID %02x VID %02x\n",
608 i,
609 sc->powernow_states[i].freq,
610 fid,
611 vid);
612 }
613
614 return (0);
615 }
616
617 static int
618 cpuid_is_k7(u_int cpuid)
619 {
620
621 switch (cpuid) {
622 case 0x760:
623 case 0x761:
624 case 0x762:
625 case 0x770:
626 case 0x771:
627 case 0x780:
628 case 0x781:
629 case 0x7a0:
630 return (TRUE);
631 }
632 return (FALSE);
633 }
634
635 static int
636 pn_decode_pst(device_t dev)
637 {
638 int maxpst;
639 struct pn_softc *sc;
640 u_int cpuid, maxfid, startvid;
641 u_long sig;
642 struct psb_header *psb;
643 uint8_t *p;
644 u_int regs[4];
645 uint64_t status;
646
647 sc = device_get_softc(dev);
648
649 do_cpuid(0x80000001, regs);
650 cpuid = regs[0];
651
652 if ((cpuid & 0xfff) == 0x760)
653 sc->errata |= A0_ERRATA;
654
655 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
656
657 switch (sc->pn_type) {
658 case PN7_TYPE:
659 maxfid = PN7_STA_MFID(status);
660 startvid = PN7_STA_SVID(status);
661 break;
662 case PN8_TYPE:
663 maxfid = PN8_STA_MFID(status);
664 /*
665 * we should actually use a variable named 'maxvid' if K8,
666 * but why introducing a new variable for that?
667 */
668 startvid = PN8_STA_MVID(status);
669 break;
670 default:
671 return (ENODEV);
672 }
673
674 if (bootverbose) {
675 device_printf(dev, "STATUS: 0x%jx\n", status);
676 device_printf(dev, "STATUS: maxfid: 0x%02x\n", maxfid);
677 device_printf(dev, "STATUS: %s: 0x%02x\n",
678 sc->pn_type == PN7_TYPE ? "startvid" : "maxvid",
679 startvid);
680 }
681
682 sig = bios_sigsearch(PSB_START, PSB_SIG, PSB_LEN, PSB_STEP, PSB_OFF);
683 if (sig) {
684 struct pst_header *pst;
685
686 psb = (struct psb_header*)(uintptr_t)BIOS_PADDRTOVADDR(sig);
687
688 switch (psb->version) {
689 default:
690 return (ENODEV);
691 case 0x14:
692 /*
693 * We can't be picky about numpst since at least
694 * some systems have a value of 1 and some have 2.
695 * We trust that cpuid_is_k7() will be better at
696 * catching that we're on a K8 anyway.
697 */
698 if (sc->pn_type != PN8_TYPE)
699 return (EINVAL);
700 sc->vst = psb->settlingtime;
701 sc->rvo = PN8_PSB_TO_RVO(psb->res1);
702 sc->irt = PN8_PSB_TO_IRT(psb->res1);
703 sc->mvs = PN8_PSB_TO_MVS(psb->res1);
704 sc->low = PN8_PSB_TO_BATT(psb->res1);
705 if (bootverbose) {
706 device_printf(dev, "PSB: VST: %d\n",
707 psb->settlingtime);
708 device_printf(dev, "PSB: RVO %x IRT %d "
709 "MVS %d BATT %d\n",
710 sc->rvo,
711 sc->irt,
712 sc->mvs,
713 sc->low);
714 }
715 break;
716 case 0x12:
717 if (sc->pn_type != PN7_TYPE)
718 return (EINVAL);
719 sc->sgtc = psb->settlingtime * sc->fsb;
720 if (sc->sgtc < 100 * sc->fsb)
721 sc->sgtc = 100 * sc->fsb;
722 break;
723 }
724
725 p = ((uint8_t *) psb) + sizeof(struct psb_header);
726 pst = (struct pst_header*) p;
727
728 maxpst = 200;
729
730 do {
731 struct pst_header *pst = (struct pst_header*) p;
732
733 if (cpuid == pst->cpuid &&
734 maxfid == pst->maxfid &&
735 startvid == pst->startvid) {
736 sc->powernow_max_states = pst->numpstates;
737 switch (sc->pn_type) {
738 case PN7_TYPE:
739 if (abs(sc->fsb - pst->fsb) > 5)
740 continue;
741 break;
742 case PN8_TYPE:
743 break;
744 }
745 return (decode_pst(sc,
746 p + sizeof(struct pst_header),
747 sc->powernow_max_states));
748 }
749
750 p += sizeof(struct pst_header) + (2 * pst->numpstates);
751 } while (cpuid_is_k7(pst->cpuid) && maxpst--);
752
753 device_printf(dev, "no match for extended cpuid %.3x\n", cpuid);
754 }
755
756 return (ENODEV);
757 }
758
759 static int
760 pn_decode_acpi(device_t dev, device_t perf_dev)
761 {
762 int i, j, n;
763 uint64_t status;
764 uint32_t ctrl;
765 u_int cpuid;
766 u_int regs[4];
767 struct pn_softc *sc;
768 struct powernow_state state;
769 struct cf_setting sets[POWERNOW_MAX_STATES];
770 int count = POWERNOW_MAX_STATES;
771 int type;
772 int rv;
773
774 if (perf_dev == NULL)
775 return (ENXIO);
776
777 rv = CPUFREQ_DRV_SETTINGS(perf_dev, sets, &count);
778 if (rv)
779 return (ENXIO);
780 rv = CPUFREQ_DRV_TYPE(perf_dev, &type);
781 if (rv || (type & CPUFREQ_FLAG_INFO_ONLY) == 0)
782 return (ENXIO);
783
784 sc = device_get_softc(dev);
785
786 do_cpuid(0x80000001, regs);
787 cpuid = regs[0];
788 if ((cpuid & 0xfff) == 0x760)
789 sc->errata |= A0_ERRATA;
790
791 ctrl = 0;
792 sc->sgtc = 0;
793 for (n = 0, i = 0; i < count; ++i) {
794 ctrl = sets[i].spec[PX_SPEC_CONTROL];
795 switch (sc->pn_type) {
796 case PN7_TYPE:
797 state.fid = ACPI_PN7_CTRL_TO_FID(ctrl);
798 state.vid = ACPI_PN7_CTRL_TO_VID(ctrl);
799 if ((sc->errata & A0_ERRATA) &&
800 (pn7_fid_to_mult[state.fid] % 10) == 5)
801 continue;
802 break;
803 case PN8_TYPE:
804 state.fid = ACPI_PN8_CTRL_TO_FID(ctrl);
805 state.vid = ACPI_PN8_CTRL_TO_VID(ctrl);
806 break;
807 }
808 state.freq = sets[i].freq * 1000;
809 state.power = sets[i].power;
810
811 j = n;
812 while (j > 0 && sc->powernow_states[j - 1].freq < state.freq) {
813 memcpy(&sc->powernow_states[j],
814 &sc->powernow_states[j - 1],
815 sizeof(struct powernow_state));
816 --j;
817 }
818 memcpy(&sc->powernow_states[j], &state,
819 sizeof(struct powernow_state));
820 ++n;
821 }
822
823 sc->powernow_max_states = n;
824 state = sc->powernow_states[0];
825 status = rdmsr(MSR_AMDK7_FIDVID_STATUS);
826
827 switch (sc->pn_type) {
828 case PN7_TYPE:
829 sc->sgtc = ACPI_PN7_CTRL_TO_SGTC(ctrl);
830 /*
831 * XXX Some bios forget the max frequency!
832 * This maybe indicates we have the wrong tables. Therefore,
833 * don't implement a quirk, but fallback to BIOS legacy
834 * tables instead.
835 */
836 if (PN7_STA_MFID(status) != state.fid) {
837 device_printf(dev, "ACPI MAX frequency not found\n");
838 return (EINVAL);
839 }
840 sc->fsb = state.freq / 100 / pn7_fid_to_mult[state.fid];
841 break;
842 case PN8_TYPE:
843 sc->vst = ACPI_PN8_CTRL_TO_VST(ctrl),
844 sc->mvs = ACPI_PN8_CTRL_TO_MVS(ctrl),
845 sc->pll = ACPI_PN8_CTRL_TO_PLL(ctrl),
846 sc->rvo = ACPI_PN8_CTRL_TO_RVO(ctrl),
847 sc->irt = ACPI_PN8_CTRL_TO_IRT(ctrl);
848 sc->low = 0; /* XXX */
849
850 /*
851 * powernow k8 supports only one low frequency.
852 */
853 if (sc->powernow_max_states >= 2 &&
854 (sc->powernow_states[sc->powernow_max_states - 2].fid < 8))
855 return (EINVAL);
856 sc->fsb = state.freq / 100 / pn8_fid_to_mult[state.fid];
857 break;
858 }
859
860 return (0);
861 }
862
863 static void
864 pn_identify(driver_t *driver, device_t parent)
865 {
866
867 if ((amd_pminfo & AMDPM_FID) == 0 || (amd_pminfo & AMDPM_VID) == 0)
868 return;
869 switch (cpu_id & 0xf00) {
870 case 0x600:
871 case 0xf00:
872 break;
873 default:
874 return;
875 }
876 if (device_find_child(parent, "powernow", -1) != NULL)
877 return;
878 if (BUS_ADD_CHILD(parent, 10, "powernow", device_get_unit(parent))
879 == 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 (sfid != mfid) {
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 (sfid != mfid)
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: 16f572218dc99113264db6bb07450341
|