powernow.c revision 144380
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: head/sys/i386/cpufreq/powernow.c 144380 2005-03-31 06:11:04Z njl $"); 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 66struct 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 75struct 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 */ 160static 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 168static 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) */ 179static 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) */ 186static 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) */ 193static 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 202struct powernow_state { 203 int freq; 204 int power; 205 int fid; 206 int vid; 207}; 208 209struct 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 234static void pn_identify(driver_t *driver, device_t parent); 235static int pn_probe(device_t dev); 236static int pn_attach(device_t dev); 237static int pn_detach(device_t dev); 238static int pn_set(device_t dev, const struct cf_setting *cf); 239static int pn_get(device_t dev, struct cf_setting *cf); 240static int pn_settings(device_t dev, struct cf_setting *sets, 241 int *count); 242static int pn_type(device_t dev, int *type); 243 244static 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 260static devclass_t pn_devclass; 261static driver_t pn_driver = { 262 "powernow", 263 pn_methods, 264 sizeof(struct pn_softc), 265}; 266 267DRIVER_MODULE(powernow, cpu, pn_driver, pn_devclass, 0, 0); 268 269static int 270pn7_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 308static int 309pn8_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 390static int 391pn_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 423static int 424pn_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 466static int 467pn_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 489static int 490pn_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 */ 504static int 505decode_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 564static int 565cpuid_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 582static int 583pn_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 */ 709static int 710cpu_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 722static int 723pn_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 827static void 828pn_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 847static int 848pn_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 908static int 909pn_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 928static int 929pn_detach(device_t dev) 930{ 931 932 cpufreq_unregister(dev); 933 return (0); 934} 935