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