1 /* $NetBSD: acpi_cpu_pstate.c,v 1.52 2011/10/18 05:08:24 jruoho Exp $ */ 2 3 /*- 4 * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi> 5 * All rights reserved. 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 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_pstate.c,v 1.52 2011/10/18 05:08:24 jruoho Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/cpufreq.h> 34 #include <sys/kmem.h> 35 36 #include <dev/acpi/acpireg.h> 37 #include <dev/acpi/acpivar.h> 38 #include <dev/acpi/acpi_cpu.h> 39 40 #define _COMPONENT ACPI_BUS_COMPONENT 41 ACPI_MODULE_NAME ("acpi_cpu_pstate") 42 43 static ACPI_STATUS acpicpu_pstate_pss(struct acpicpu_softc *); 44 static ACPI_STATUS acpicpu_pstate_pss_add(struct acpicpu_pstate *, 45 ACPI_OBJECT *); 46 static ACPI_STATUS acpicpu_pstate_xpss(struct acpicpu_softc *); 47 static ACPI_STATUS acpicpu_pstate_xpss_add(struct acpicpu_pstate *, 48 ACPI_OBJECT *); 49 static ACPI_STATUS acpicpu_pstate_pct(struct acpicpu_softc *); 50 static ACPI_STATUS acpicpu_pstate_dep(struct acpicpu_softc *); 51 static int acpicpu_pstate_max(struct acpicpu_softc *); 52 static int acpicpu_pstate_min(struct acpicpu_softc *); 53 static void acpicpu_pstate_change(struct acpicpu_softc *); 54 static void acpicpu_pstate_reset(struct acpicpu_softc *); 55 static void acpicpu_pstate_bios(void); 56 57 extern struct acpicpu_softc **acpicpu_sc; 58 59 void 60 acpicpu_pstate_attach(device_t self) 61 { 62 struct acpicpu_softc *sc = device_private(self); 63 const char *str; 64 ACPI_HANDLE tmp; 65 ACPI_STATUS rv; 66 67 rv = acpicpu_pstate_pss(sc); 68 69 if (ACPI_FAILURE(rv)) { 70 str = "_PSS"; 71 goto fail; 72 } 73 74 /* 75 * Append additional information from the extended _PSS, 76 * if available. Note that XPSS can not be used on Intel 77 * systems that use either _PDC or _OSC. From the XPSS 78 * method specification: 79 * 80 * "The platform must not require the use of the 81 * optional _PDC or _OSC methods to coordinate 82 * between the operating system and firmware for 83 * the purposes of enabling specific processor 84 * power management features or implementations." 85 */ 86 if (sc->sc_cap == 0) { 87 88 rv = acpicpu_pstate_xpss(sc); 89 90 if (ACPI_SUCCESS(rv)) 91 sc->sc_flags |= ACPICPU_FLAG_P_XPSS; 92 } 93 94 rv = acpicpu_pstate_pct(sc); 95 96 if (ACPI_FAILURE(rv)) { 97 str = "_PCT"; 98 goto fail; 99 } 100 101 /* 102 * The ACPI 3.0 and 4.0 specifications mandate three 103 * objects for P-states: _PSS, _PCT, and _PPC. A less 104 * strict wording is however used in the earlier 2.0 105 * standard, and some systems conforming to ACPI 2.0 106 * do not have _PPC, the method for dynamic maximum. 107 */ 108 rv = AcpiGetHandle(sc->sc_node->ad_handle, "_PPC", &tmp); 109 110 if (ACPI_FAILURE(rv)) 111 aprint_debug_dev(self, "_PPC missing\n"); 112 113 /* 114 * Carry out MD initialization. 115 */ 116 rv = acpicpu_md_pstate_init(sc); 117 118 if (rv != 0) { 119 rv = AE_SUPPORT; 120 goto fail; 121 } 122 123 /* 124 * Query the optional _PSD. 125 */ 126 rv = acpicpu_pstate_dep(sc); 127 128 if (ACPI_SUCCESS(rv)) 129 sc->sc_flags |= ACPICPU_FLAG_P_DEP; 130 131 sc->sc_pstate_current = 0; 132 sc->sc_flags |= ACPICPU_FLAG_P; 133 134 acpicpu_pstate_bios(); 135 acpicpu_pstate_reset(sc); 136 137 return; 138 139 fail: 140 switch (rv) { 141 142 case AE_NOT_FOUND: 143 return; 144 145 case AE_SUPPORT: 146 aprint_verbose_dev(self, "P-states not supported\n"); 147 return; 148 149 default: 150 aprint_error_dev(self, "failed to evaluate " 151 "%s: %s\n", str, AcpiFormatException(rv)); 152 } 153 } 154 155 void 156 acpicpu_pstate_detach(device_t self) 157 { 158 struct acpicpu_softc *sc = device_private(self); 159 size_t size; 160 161 if ((sc->sc_flags & ACPICPU_FLAG_P) == 0) 162 return; 163 164 (void)acpicpu_md_pstate_stop(); 165 166 size = sc->sc_pstate_count * sizeof(*sc->sc_pstate); 167 168 if (sc->sc_pstate != NULL) 169 kmem_free(sc->sc_pstate, size); 170 171 sc->sc_flags &= ~ACPICPU_FLAG_P; 172 } 173 174 void 175 acpicpu_pstate_start(device_t self) 176 { 177 struct acpicpu_softc *sc = device_private(self); 178 179 if (acpicpu_md_pstate_start(sc) == 0) 180 return; 181 182 sc->sc_flags &= ~ACPICPU_FLAG_P; 183 aprint_error_dev(self, "failed to start P-states\n"); 184 } 185 186 void 187 acpicpu_pstate_suspend(void *aux) 188 { 189 struct acpicpu_softc *sc; 190 device_t self = aux; 191 192 /* 193 * Reset any dynamic limits. 194 */ 195 sc = device_private(self); 196 mutex_enter(&sc->sc_mtx); 197 acpicpu_pstate_reset(sc); 198 mutex_exit(&sc->sc_mtx); 199 } 200 201 void 202 acpicpu_pstate_resume(void *aux) 203 { 204 /* Nothing. */ 205 } 206 207 void 208 acpicpu_pstate_callback(void *aux) 209 { 210 struct acpicpu_softc *sc; 211 device_t self = aux; 212 uint32_t freq; 213 214 sc = device_private(self); 215 mutex_enter(&sc->sc_mtx); 216 acpicpu_pstate_change(sc); 217 218 freq = sc->sc_pstate[sc->sc_pstate_max].ps_freq; 219 220 if (sc->sc_pstate_saved == 0) 221 sc->sc_pstate_saved = sc->sc_pstate_current; 222 223 if (sc->sc_pstate_saved <= freq) { 224 freq = sc->sc_pstate_saved; 225 sc->sc_pstate_saved = 0; 226 } 227 228 mutex_exit(&sc->sc_mtx); 229 cpufreq_set(sc->sc_ci, freq); 230 } 231 232 static ACPI_STATUS 233 acpicpu_pstate_pss(struct acpicpu_softc *sc) 234 { 235 struct acpicpu_pstate *ps; 236 ACPI_OBJECT *obj; 237 ACPI_BUFFER buf; 238 ACPI_STATUS rv; 239 uint32_t count; 240 uint32_t i, j; 241 242 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PSS", &buf); 243 244 if (ACPI_FAILURE(rv)) 245 return rv; 246 247 obj = buf.Pointer; 248 249 if (obj->Type != ACPI_TYPE_PACKAGE) { 250 rv = AE_TYPE; 251 goto out; 252 } 253 254 sc->sc_pstate_count = obj->Package.Count; 255 256 if (sc->sc_pstate_count == 0) { 257 rv = AE_NOT_EXIST; 258 goto out; 259 } 260 261 if (sc->sc_pstate_count > ACPICPU_P_STATE_MAX) { 262 rv = AE_LIMIT; 263 goto out; 264 } 265 266 sc->sc_pstate = kmem_zalloc(sc->sc_pstate_count * 267 sizeof(struct acpicpu_pstate), KM_SLEEP); 268 269 if (sc->sc_pstate == NULL) { 270 rv = AE_NO_MEMORY; 271 goto out; 272 } 273 274 for (count = i = 0; i < sc->sc_pstate_count; i++) { 275 276 ps = &sc->sc_pstate[i]; 277 rv = acpicpu_pstate_pss_add(ps, &obj->Package.Elements[i]); 278 279 if (ACPI_FAILURE(rv)) { 280 aprint_error_dev(sc->sc_dev, "failed to add " 281 "P-state: %s\n", AcpiFormatException(rv)); 282 ps->ps_freq = 0; 283 continue; 284 } 285 286 for (j = 0; j < i; j++) { 287 288 if (ps->ps_freq >= sc->sc_pstate[j].ps_freq) { 289 ps->ps_freq = 0; 290 break; 291 } 292 } 293 294 if (ps->ps_freq != 0) 295 count++; 296 } 297 298 rv = (count != 0) ? AE_OK : AE_NOT_EXIST; 299 300 out: 301 if (buf.Pointer != NULL) 302 ACPI_FREE(buf.Pointer); 303 304 return rv; 305 } 306 307 static ACPI_STATUS 308 acpicpu_pstate_pss_add(struct acpicpu_pstate *ps, ACPI_OBJECT *obj) 309 { 310 ACPI_OBJECT *elm; 311 int i; 312 313 if (obj->Type != ACPI_TYPE_PACKAGE) 314 return AE_TYPE; 315 316 if (obj->Package.Count != 6) 317 return AE_BAD_DATA; 318 319 elm = obj->Package.Elements; 320 321 for (i = 0; i < 6; i++) { 322 323 if (elm[i].Type != ACPI_TYPE_INTEGER) 324 return AE_TYPE; 325 326 if (elm[i].Integer.Value > UINT32_MAX) 327 return AE_AML_NUMERIC_OVERFLOW; 328 } 329 330 ps->ps_freq = elm[0].Integer.Value; 331 ps->ps_power = elm[1].Integer.Value; 332 ps->ps_latency = elm[2].Integer.Value; 333 ps->ps_latency_bm = elm[3].Integer.Value; 334 ps->ps_control = elm[4].Integer.Value; 335 ps->ps_status = elm[5].Integer.Value; 336 337 if (ps->ps_freq == 0 || ps->ps_freq > 9999) 338 return AE_BAD_DECIMAL_CONSTANT; 339 340 if (ps->ps_latency == 0 || ps->ps_latency > 1000) 341 ps->ps_latency = 1; 342 343 return AE_OK; 344 } 345 346 static ACPI_STATUS 347 acpicpu_pstate_xpss(struct acpicpu_softc *sc) 348 { 349 struct acpicpu_pstate *ps; 350 ACPI_OBJECT *obj; 351 ACPI_BUFFER buf; 352 ACPI_STATUS rv; 353 uint32_t i = 0; 354 355 rv = acpi_eval_struct(sc->sc_node->ad_handle, "XPSS", &buf); 356 357 if (ACPI_FAILURE(rv)) 358 goto out; 359 360 obj = buf.Pointer; 361 362 if (obj->Type != ACPI_TYPE_PACKAGE) { 363 rv = AE_TYPE; 364 goto out; 365 } 366 367 if (obj->Package.Count != sc->sc_pstate_count) { 368 rv = AE_LIMIT; 369 goto out; 370 } 371 372 while (i < sc->sc_pstate_count) { 373 374 ps = &sc->sc_pstate[i]; 375 acpicpu_pstate_xpss_add(ps, &obj->Package.Elements[i]); 376 377 i++; 378 } 379 380 out: 381 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) 382 aprint_error_dev(sc->sc_dev, "failed to evaluate " 383 "XPSS: %s\n", AcpiFormatException(rv)); 384 385 if (buf.Pointer != NULL) 386 ACPI_FREE(buf.Pointer); 387 388 return rv; 389 } 390 391 static ACPI_STATUS 392 acpicpu_pstate_xpss_add(struct acpicpu_pstate *ps, ACPI_OBJECT *obj) 393 { 394 ACPI_OBJECT *elm; 395 int i; 396 397 if (obj->Type != ACPI_TYPE_PACKAGE) 398 return AE_TYPE; 399 400 if (obj->Package.Count != 8) 401 return AE_BAD_DATA; 402 403 elm = obj->Package.Elements; 404 405 for (i = 0; i < 4; i++) { 406 407 if (elm[i].Type != ACPI_TYPE_INTEGER) 408 return AE_TYPE; 409 410 if (elm[i].Integer.Value > UINT32_MAX) 411 return AE_AML_NUMERIC_OVERFLOW; 412 } 413 414 for (; i < 8; i++) { 415 416 if (elm[i].Type != ACPI_TYPE_BUFFER) 417 return AE_TYPE; 418 419 if (elm[i].Buffer.Length != 8) 420 return AE_LIMIT; 421 } 422 423 /* 424 * Only overwrite the elements that were 425 * not available from the conventional _PSS. 426 */ 427 if (ps->ps_freq == 0) 428 ps->ps_freq = elm[0].Integer.Value; 429 430 if (ps->ps_power == 0) 431 ps->ps_power = elm[1].Integer.Value; 432 433 if (ps->ps_latency == 0) 434 ps->ps_latency = elm[2].Integer.Value; 435 436 if (ps->ps_latency_bm == 0) 437 ps->ps_latency_bm = elm[3].Integer.Value; 438 439 if (ps->ps_control == 0) 440 ps->ps_control = ACPI_GET64(elm[4].Buffer.Pointer); 441 442 if (ps->ps_status == 0) 443 ps->ps_status = ACPI_GET64(elm[5].Buffer.Pointer); 444 445 if (ps->ps_control_mask == 0) 446 ps->ps_control_mask = ACPI_GET64(elm[6].Buffer.Pointer); 447 448 if (ps->ps_status_mask == 0) 449 ps->ps_status_mask = ACPI_GET64(elm[7].Buffer.Pointer); 450 451 ps->ps_flags |= ACPICPU_FLAG_P_XPSS; 452 453 if (ps->ps_freq == 0 || ps->ps_freq > 9999) 454 return AE_BAD_DECIMAL_CONSTANT; 455 456 if (ps->ps_latency == 0 || ps->ps_latency > 1000) 457 ps->ps_latency = 1; 458 459 return AE_OK; 460 } 461 462 static ACPI_STATUS 463 acpicpu_pstate_pct(struct acpicpu_softc *sc) 464 { 465 static const size_t size = sizeof(struct acpicpu_reg); 466 struct acpicpu_reg *reg[2]; 467 struct acpicpu_pstate *ps; 468 ACPI_OBJECT *elm, *obj; 469 ACPI_BUFFER buf; 470 ACPI_STATUS rv; 471 uint8_t width; 472 uint32_t i; 473 474 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PCT", &buf); 475 476 if (ACPI_FAILURE(rv)) 477 return rv; 478 479 obj = buf.Pointer; 480 481 if (obj->Type != ACPI_TYPE_PACKAGE) { 482 rv = AE_TYPE; 483 goto out; 484 } 485 486 if (obj->Package.Count != 2) { 487 rv = AE_LIMIT; 488 goto out; 489 } 490 491 for (i = 0; i < 2; i++) { 492 493 elm = &obj->Package.Elements[i]; 494 495 if (elm->Type != ACPI_TYPE_BUFFER) { 496 rv = AE_TYPE; 497 goto out; 498 } 499 500 if (size > elm->Buffer.Length) { 501 rv = AE_AML_BAD_RESOURCE_LENGTH; 502 goto out; 503 } 504 505 reg[i] = (struct acpicpu_reg *)elm->Buffer.Pointer; 506 507 switch (reg[i]->reg_spaceid) { 508 509 case ACPI_ADR_SPACE_SYSTEM_IO: 510 511 if (reg[i]->reg_addr == 0) { 512 rv = AE_AML_ILLEGAL_ADDRESS; 513 goto out; 514 } 515 516 width = reg[i]->reg_bitwidth; 517 518 if (width + reg[i]->reg_bitoffset > 32) { 519 rv = AE_AML_BAD_RESOURCE_VALUE; 520 goto out; 521 } 522 523 if (width != 8 && width != 16 && width != 32) { 524 rv = AE_AML_BAD_RESOURCE_VALUE; 525 goto out; 526 } 527 528 break; 529 530 case ACPI_ADR_SPACE_FIXED_HARDWARE: 531 532 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) != 0) { 533 534 if (reg[i]->reg_bitwidth != 64) { 535 rv = AE_AML_BAD_RESOURCE_VALUE; 536 goto out; 537 } 538 539 if (reg[i]->reg_bitoffset != 0) { 540 rv = AE_AML_BAD_RESOURCE_VALUE; 541 goto out; 542 } 543 544 break; 545 } 546 547 if ((sc->sc_flags & ACPICPU_FLAG_P_FFH) == 0) { 548 rv = AE_SUPPORT; 549 goto out; 550 } 551 552 break; 553 554 default: 555 rv = AE_AML_INVALID_SPACE_ID; 556 goto out; 557 } 558 } 559 560 if (reg[0]->reg_spaceid != reg[1]->reg_spaceid) { 561 rv = AE_AML_INVALID_SPACE_ID; 562 goto out; 563 } 564 565 (void)memcpy(&sc->sc_pstate_control, reg[0], size); 566 (void)memcpy(&sc->sc_pstate_status, reg[1], size); 567 568 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) != 0) { 569 570 /* 571 * At the very least, mandate that 572 * XPSS supplies the control address. 573 */ 574 if (sc->sc_pstate_control.reg_addr == 0) { 575 rv = AE_AML_BAD_RESOURCE_LENGTH; 576 goto out; 577 } 578 579 /* 580 * If XPSS is present, copy the supplied 581 * MSR addresses to the P-state structures. 582 */ 583 for (i = 0; i < sc->sc_pstate_count; i++) { 584 585 ps = &sc->sc_pstate[i]; 586 587 if (ps->ps_freq == 0) 588 continue; 589 590 ps->ps_status_addr = sc->sc_pstate_status.reg_addr; 591 ps->ps_control_addr = sc->sc_pstate_control.reg_addr; 592 } 593 } 594 595 out: 596 if (buf.Pointer != NULL) 597 ACPI_FREE(buf.Pointer); 598 599 return rv; 600 } 601 602 static ACPI_STATUS 603 acpicpu_pstate_dep(struct acpicpu_softc *sc) 604 { 605 ACPI_OBJECT *elm, *obj; 606 ACPI_BUFFER buf; 607 ACPI_STATUS rv; 608 uint32_t val; 609 uint8_t i, n; 610 611 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PSD", &buf); 612 613 if (ACPI_FAILURE(rv)) 614 goto out; 615 616 obj = buf.Pointer; 617 618 if (obj->Type != ACPI_TYPE_PACKAGE) { 619 rv = AE_TYPE; 620 goto out; 621 } 622 623 if (obj->Package.Count != 1) { 624 rv = AE_LIMIT; 625 goto out; 626 } 627 628 elm = &obj->Package.Elements[0]; 629 630 if (obj->Type != ACPI_TYPE_PACKAGE) { 631 rv = AE_TYPE; 632 goto out; 633 } 634 635 n = elm->Package.Count; 636 637 if (n != 5) { 638 rv = AE_LIMIT; 639 goto out; 640 } 641 642 elm = elm->Package.Elements; 643 644 for (i = 0; i < n; i++) { 645 646 if (elm[i].Type != ACPI_TYPE_INTEGER) { 647 rv = AE_TYPE; 648 goto out; 649 } 650 651 if (elm[i].Integer.Value > UINT32_MAX) { 652 rv = AE_AML_NUMERIC_OVERFLOW; 653 goto out; 654 } 655 } 656 657 val = elm[1].Integer.Value; 658 659 if (val != 0) 660 aprint_debug_dev(sc->sc_dev, "invalid revision in _PSD\n"); 661 662 val = elm[3].Integer.Value; 663 664 if (val < ACPICPU_DEP_SW_ALL || val > ACPICPU_DEP_HW_ALL) { 665 rv = AE_AML_BAD_RESOURCE_VALUE; 666 goto out; 667 } 668 669 val = elm[4].Integer.Value; 670 671 if (val > sc->sc_ncpus) { 672 rv = AE_BAD_VALUE; 673 goto out; 674 } 675 676 sc->sc_pstate_dep.dep_domain = elm[2].Integer.Value; 677 sc->sc_pstate_dep.dep_type = elm[3].Integer.Value; 678 sc->sc_pstate_dep.dep_ncpus = elm[4].Integer.Value; 679 680 out: 681 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) 682 aprint_debug_dev(sc->sc_dev, "failed to evaluate " 683 "_PSD: %s\n", AcpiFormatException(rv)); 684 685 if (buf.Pointer != NULL) 686 ACPI_FREE(buf.Pointer); 687 688 return rv; 689 } 690 691 static int 692 acpicpu_pstate_max(struct acpicpu_softc *sc) 693 { 694 ACPI_INTEGER val; 695 ACPI_STATUS rv; 696 697 /* 698 * Evaluate the currently highest P-state that can be used. 699 * If available, we can use either this state or any lower 700 * power (i.e. higher numbered) state from the _PSS object. 701 * Note that the return value must match the _OST parameter. 702 */ 703 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PPC", &val); 704 705 if (ACPI_SUCCESS(rv) && val < sc->sc_pstate_count) { 706 707 if (sc->sc_pstate[val].ps_freq != 0) { 708 sc->sc_pstate_max = val; 709 return 0; 710 } 711 } 712 713 return 1; 714 } 715 716 static int 717 acpicpu_pstate_min(struct acpicpu_softc *sc) 718 { 719 ACPI_INTEGER val; 720 ACPI_STATUS rv; 721 722 /* 723 * The _PDL object defines the minimum when passive cooling 724 * is being performed. If available, we can use the returned 725 * state or any higher power (i.e. lower numbered) state. 726 */ 727 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PDL", &val); 728 729 if (ACPI_SUCCESS(rv) && val < sc->sc_pstate_count) { 730 731 if (sc->sc_pstate[val].ps_freq == 0) 732 return 1; 733 734 if (val >= sc->sc_pstate_max) { 735 sc->sc_pstate_min = val; 736 return 0; 737 } 738 } 739 740 return 1; 741 } 742 743 static void 744 acpicpu_pstate_change(struct acpicpu_softc *sc) 745 { 746 static ACPI_STATUS rv = AE_OK; 747 ACPI_OBJECT_LIST arg; 748 ACPI_OBJECT obj[2]; 749 static int val = 0; 750 751 acpicpu_pstate_reset(sc); 752 753 /* 754 * Cache the checks as the optional 755 * _PDL and _OST are rarely present. 756 */ 757 if (val == 0) 758 val = acpicpu_pstate_min(sc); 759 760 arg.Count = 2; 761 arg.Pointer = obj; 762 763 obj[0].Type = ACPI_TYPE_INTEGER; 764 obj[1].Type = ACPI_TYPE_INTEGER; 765 766 obj[0].Integer.Value = ACPICPU_P_NOTIFY; 767 obj[1].Integer.Value = acpicpu_pstate_max(sc); 768 769 if (ACPI_FAILURE(rv)) 770 return; 771 772 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OST", &arg, NULL); 773 } 774 775 static void 776 acpicpu_pstate_reset(struct acpicpu_softc *sc) 777 { 778 779 sc->sc_pstate_max = 0; 780 sc->sc_pstate_min = sc->sc_pstate_count - 1; 781 782 } 783 784 static void 785 acpicpu_pstate_bios(void) 786 { 787 const uint8_t val = AcpiGbl_FADT.PstateControl; 788 const uint32_t addr = AcpiGbl_FADT.SmiCommand; 789 790 if (addr == 0 || val == 0) 791 return; 792 793 (void)AcpiOsWritePort(addr, val, 8); 794 } 795 796 void 797 acpicpu_pstate_get(void *aux, void *cpu_freq) 798 { 799 struct acpicpu_pstate *ps = NULL; 800 struct cpu_info *ci = curcpu(); 801 struct acpicpu_softc *sc; 802 uint32_t freq, i, val = 0; 803 uint64_t addr; 804 uint8_t width; 805 int rv; 806 807 sc = acpicpu_sc[ci->ci_acpiid]; 808 809 if (__predict_false(sc == NULL)) { 810 rv = ENXIO; 811 goto fail; 812 } 813 814 if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P) == 0)) { 815 rv = ENODEV; 816 goto fail; 817 } 818 819 mutex_enter(&sc->sc_mtx); 820 821 /* 822 * Use the cached value, if available. 823 */ 824 if (sc->sc_pstate_current != 0) { 825 *(uint32_t *)cpu_freq = sc->sc_pstate_current; 826 mutex_exit(&sc->sc_mtx); 827 return; 828 } 829 830 mutex_exit(&sc->sc_mtx); 831 832 switch (sc->sc_pstate_status.reg_spaceid) { 833 834 case ACPI_ADR_SPACE_FIXED_HARDWARE: 835 836 rv = acpicpu_md_pstate_get(sc, &freq); 837 838 if (__predict_false(rv != 0)) 839 goto fail; 840 841 break; 842 843 case ACPI_ADR_SPACE_SYSTEM_IO: 844 845 addr = sc->sc_pstate_status.reg_addr; 846 width = sc->sc_pstate_status.reg_bitwidth; 847 848 (void)AcpiOsReadPort(addr, &val, width); 849 850 if (val == 0) { 851 rv = EIO; 852 goto fail; 853 } 854 855 for (i = 0; i < sc->sc_pstate_count; i++) { 856 857 if (sc->sc_pstate[i].ps_freq == 0) 858 continue; 859 860 if (val == sc->sc_pstate[i].ps_status) { 861 ps = &sc->sc_pstate[i]; 862 break; 863 } 864 } 865 866 if (ps == NULL) { 867 rv = EIO; 868 goto fail; 869 } 870 871 freq = ps->ps_freq; 872 break; 873 874 default: 875 rv = ENOTTY; 876 goto fail; 877 } 878 879 mutex_enter(&sc->sc_mtx); 880 sc->sc_pstate_current = freq; 881 *(uint32_t *)cpu_freq = freq; 882 mutex_exit(&sc->sc_mtx); 883 884 return; 885 886 fail: 887 aprint_error_dev(sc->sc_dev, "failed " 888 "to get frequency (err %d)\n", rv); 889 890 mutex_enter(&sc->sc_mtx); 891 sc->sc_pstate_current = 0; 892 *(uint32_t *)cpu_freq = 0; 893 mutex_exit(&sc->sc_mtx); 894 } 895 896 void 897 acpicpu_pstate_set(void *aux, void *cpu_freq) 898 { 899 struct acpicpu_pstate *ps = NULL; 900 struct cpu_info *ci = curcpu(); 901 struct acpicpu_softc *sc; 902 uint32_t freq, i, val; 903 uint64_t addr; 904 uint8_t width; 905 int rv; 906 907 freq = *(uint32_t *)cpu_freq; 908 sc = acpicpu_sc[ci->ci_acpiid]; 909 910 if (__predict_false(sc == NULL)) { 911 rv = ENXIO; 912 goto fail; 913 } 914 915 if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P) == 0)) { 916 rv = ENODEV; 917 goto fail; 918 } 919 920 mutex_enter(&sc->sc_mtx); 921 922 if (sc->sc_pstate_current == freq) { 923 mutex_exit(&sc->sc_mtx); 924 return; 925 } 926 927 /* 928 * Verify that the requested frequency is available. 929 * 930 * The access needs to be protected since the currently 931 * available maximum and minimum may change dynamically. 932 */ 933 for (i = sc->sc_pstate_max; i <= sc->sc_pstate_min; i++) { 934 935 if (__predict_false(sc->sc_pstate[i].ps_freq == 0)) 936 continue; 937 938 if (sc->sc_pstate[i].ps_freq == freq) { 939 ps = &sc->sc_pstate[i]; 940 break; 941 } 942 } 943 944 mutex_exit(&sc->sc_mtx); 945 946 if (__predict_false(ps == NULL)) { 947 rv = EINVAL; 948 goto fail; 949 } 950 951 switch (sc->sc_pstate_control.reg_spaceid) { 952 953 case ACPI_ADR_SPACE_FIXED_HARDWARE: 954 955 rv = acpicpu_md_pstate_set(ps); 956 957 if (__predict_false(rv != 0)) 958 goto fail; 959 960 break; 961 962 case ACPI_ADR_SPACE_SYSTEM_IO: 963 964 addr = sc->sc_pstate_control.reg_addr; 965 width = sc->sc_pstate_control.reg_bitwidth; 966 967 (void)AcpiOsWritePort(addr, ps->ps_control, width); 968 969 addr = sc->sc_pstate_status.reg_addr; 970 width = sc->sc_pstate_status.reg_bitwidth; 971 972 /* 973 * Some systems take longer to respond 974 * than the reported worst-case latency. 975 */ 976 for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) { 977 978 (void)AcpiOsReadPort(addr, &val, width); 979 980 if (val == ps->ps_status) 981 break; 982 983 DELAY(ps->ps_latency); 984 } 985 986 if (i == ACPICPU_P_STATE_RETRY) { 987 rv = EAGAIN; 988 goto fail; 989 } 990 991 break; 992 993 default: 994 rv = ENOTTY; 995 goto fail; 996 } 997 998 mutex_enter(&sc->sc_mtx); 999 ps->ps_evcnt.ev_count++; 1000 sc->sc_pstate_current = freq; 1001 mutex_exit(&sc->sc_mtx); 1002 1003 return; 1004 1005 fail: 1006 if (rv != EINVAL) 1007 aprint_error_dev(sc->sc_dev, "failed to set " 1008 "frequency to %u (err %d)\n", freq, rv); 1009 1010 mutex_enter(&sc->sc_mtx); 1011 sc->sc_pstate_current = 0; 1012 mutex_exit(&sc->sc_mtx); 1013 } 1014