acpi_cpu_pstate.c revision 1.43 1 /* $NetBSD: acpi_cpu_pstate.c,v 1.43 2011/03/01 05:32:03 jruoho Exp $ */
2
3 /*-
4 * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen (at) 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.43 2011/03/01 05:32:03 jruoho Exp $");
31
32 #include <sys/param.h>
33 #include <sys/evcnt.h>
34 #include <sys/kmem.h>
35 #include <sys/once.h>
36 #include <sys/xcall.h>
37
38 #include <dev/acpi/acpireg.h>
39 #include <dev/acpi/acpivar.h>
40 #include <dev/acpi/acpi_cpu.h>
41
42 #define _COMPONENT ACPI_BUS_COMPONENT
43 ACPI_MODULE_NAME ("acpi_cpu_pstate")
44
45 static void acpicpu_pstate_attach_evcnt(struct acpicpu_softc *);
46 static void acpicpu_pstate_detach_evcnt(struct acpicpu_softc *);
47 static ACPI_STATUS acpicpu_pstate_pss(struct acpicpu_softc *);
48 static ACPI_STATUS acpicpu_pstate_pss_add(struct acpicpu_pstate *,
49 ACPI_OBJECT *);
50 static ACPI_STATUS acpicpu_pstate_xpss(struct acpicpu_softc *);
51 static ACPI_STATUS acpicpu_pstate_xpss_add(struct acpicpu_pstate *,
52 ACPI_OBJECT *);
53 static ACPI_STATUS acpicpu_pstate_pct(struct acpicpu_softc *);
54 static ACPI_STATUS acpicpu_pstate_dep(struct acpicpu_softc *);
55 static int acpicpu_pstate_max(struct acpicpu_softc *);
56 static int acpicpu_pstate_min(struct acpicpu_softc *);
57 static void acpicpu_pstate_change(struct acpicpu_softc *);
58 static void acpicpu_pstate_reset(struct acpicpu_softc *);
59 static void acpicpu_pstate_bios(void);
60 static void acpicpu_pstate_set_xcall(void *, void *);
61
62 static uint32_t acpicpu_pstate_saved = 0;
63 extern struct acpicpu_softc **acpicpu_sc;
64
65 void
66 acpicpu_pstate_attach(device_t self)
67 {
68 struct acpicpu_softc *sc = device_private(self);
69 const char *str;
70 ACPI_HANDLE tmp;
71 ACPI_STATUS rv;
72
73 rv = acpicpu_pstate_pss(sc);
74
75 if (ACPI_FAILURE(rv)) {
76 str = "_PSS";
77 goto fail;
78 }
79
80 /*
81 * Append additional information from the extended _PSS,
82 * if available. Note that XPSS can not be used on Intel
83 * systems that use either _PDC or _OSC. From the XPSS
84 * method specification:
85 *
86 * "The platform must not require the use of the
87 * optional _PDC or _OSC methods to coordinate
88 * between the operating system and firmware for
89 * the purposes of enabling specific processor
90 * power management features or implementations."
91 */
92 if (sc->sc_cap == 0) {
93
94 rv = acpicpu_pstate_xpss(sc);
95
96 if (ACPI_SUCCESS(rv))
97 sc->sc_flags |= ACPICPU_FLAG_P_XPSS;
98 }
99
100 rv = acpicpu_pstate_pct(sc);
101
102 if (ACPI_FAILURE(rv)) {
103 str = "_PCT";
104 goto fail;
105 }
106
107 /*
108 * The ACPI 3.0 and 4.0 specifications mandate three
109 * objects for P-states: _PSS, _PCT, and _PPC. A less
110 * strict wording is however used in the earlier 2.0
111 * standard, and some systems conforming to ACPI 2.0
112 * do not have _PPC, the method for dynamic maximum.
113 */
114 rv = AcpiGetHandle(sc->sc_node->ad_handle, "_PPC", &tmp);
115
116 if (ACPI_FAILURE(rv))
117 aprint_debug_dev(self, "_PPC missing\n");
118
119 /*
120 * Employ the XPSS structure by filling
121 * it with MD information required for FFH.
122 */
123 rv = acpicpu_md_pstate_pss(sc);
124
125 if (rv != 0) {
126 rv = AE_SUPPORT;
127 goto fail;
128 }
129
130 /*
131 * Query the optional _PSD.
132 */
133 rv = acpicpu_pstate_dep(sc);
134
135 if (ACPI_SUCCESS(rv))
136 sc->sc_flags |= ACPICPU_FLAG_P_DEP;
137
138 sc->sc_flags |= ACPICPU_FLAG_P;
139
140 acpicpu_pstate_bios();
141 acpicpu_pstate_reset(sc);
142 acpicpu_pstate_attach_evcnt(sc);
143
144 return;
145
146 fail:
147 switch (rv) {
148
149 case AE_NOT_FOUND:
150 return;
151
152 case AE_SUPPORT:
153 aprint_verbose_dev(self, "P-states not supported\n");
154 return;
155
156 default:
157 aprint_error_dev(self, "failed to evaluate "
158 "%s: %s\n", str, AcpiFormatException(rv));
159 }
160 }
161
162 static void
163 acpicpu_pstate_attach_evcnt(struct acpicpu_softc *sc)
164 {
165 struct acpicpu_pstate *ps;
166 uint32_t i;
167
168 for (i = 0; i < sc->sc_pstate_count; i++) {
169
170 ps = &sc->sc_pstate[i];
171
172 if (ps->ps_freq == 0)
173 continue;
174
175 (void)snprintf(ps->ps_name, sizeof(ps->ps_name),
176 "P%u (%u MHz)", i, ps->ps_freq);
177
178 evcnt_attach_dynamic(&ps->ps_evcnt, EVCNT_TYPE_MISC,
179 NULL, device_xname(sc->sc_dev), ps->ps_name);
180 }
181 }
182
183 int
184 acpicpu_pstate_detach(device_t self)
185 {
186 struct acpicpu_softc *sc = device_private(self);
187 static ONCE_DECL(once_detach);
188 size_t size;
189 int rv;
190
191 if ((sc->sc_flags & ACPICPU_FLAG_P) == 0)
192 return 0;
193
194 rv = RUN_ONCE(&once_detach, acpicpu_md_pstate_stop);
195
196 if (rv != 0)
197 return rv;
198
199 size = sc->sc_pstate_count * sizeof(*sc->sc_pstate);
200
201 if (sc->sc_pstate != NULL)
202 kmem_free(sc->sc_pstate, size);
203
204 sc->sc_flags &= ~ACPICPU_FLAG_P;
205 acpicpu_pstate_detach_evcnt(sc);
206
207 return 0;
208 }
209
210 static void
211 acpicpu_pstate_detach_evcnt(struct acpicpu_softc *sc)
212 {
213 struct acpicpu_pstate *ps;
214 uint32_t i;
215
216 for (i = 0; i < sc->sc_pstate_count; i++) {
217
218 ps = &sc->sc_pstate[i];
219
220 if (ps->ps_freq != 0)
221 evcnt_detach(&ps->ps_evcnt);
222 }
223 }
224
225 void
226 acpicpu_pstate_start(device_t self)
227 {
228 struct acpicpu_softc *sc = device_private(self);
229 struct acpicpu_pstate *ps;
230 uint32_t i;
231 int rv;
232
233 rv = acpicpu_md_pstate_start(sc);
234
235 if (rv != 0)
236 goto fail;
237
238 /*
239 * Initialize the states to P0.
240 */
241 for (i = 0, rv = ENXIO; i < sc->sc_pstate_count; i++) {
242
243 ps = &sc->sc_pstate[i];
244
245 if (ps->ps_freq != 0) {
246 acpicpu_pstate_set(sc->sc_ci, ps->ps_freq);
247 return;
248 }
249 }
250
251 fail:
252 sc->sc_flags &= ~ACPICPU_FLAG_P;
253
254 aprint_error_dev(self, "failed to start P-states (err %d)\n", rv);
255 }
256
257 bool
258 acpicpu_pstate_suspend(device_t self)
259 {
260 struct acpicpu_softc *sc = device_private(self);
261 struct acpicpu_pstate *ps = NULL;
262 int32_t i;
263
264 mutex_enter(&sc->sc_mtx);
265 acpicpu_pstate_reset(sc);
266 mutex_exit(&sc->sc_mtx);
267
268 if (acpicpu_pstate_saved != 0)
269 return true;
270
271 /*
272 * Following design notes for Windows, we set the highest
273 * P-state when entering any of the system sleep states.
274 * When resuming, the saved P-state will be restored.
275 *
276 * Microsoft Corporation: Windows Native Processor
277 * Performance Control. Version 1.1a, November, 2002.
278 */
279 for (i = sc->sc_pstate_count - 1; i >= 0; i--) {
280
281 if (sc->sc_pstate[i].ps_freq != 0) {
282 ps = &sc->sc_pstate[i];
283 break;
284 }
285 }
286
287 if (__predict_false(ps == NULL))
288 return true;
289
290 mutex_enter(&sc->sc_mtx);
291 acpicpu_pstate_saved = sc->sc_pstate_current;
292 mutex_exit(&sc->sc_mtx);
293
294 if (acpicpu_pstate_saved == ps->ps_freq)
295 return true;
296
297 acpicpu_pstate_set(sc->sc_ci, ps->ps_freq);
298
299 return true;
300 }
301
302 bool
303 acpicpu_pstate_resume(device_t self)
304 {
305 struct acpicpu_softc *sc = device_private(self);
306
307 if (acpicpu_pstate_saved != 0) {
308 acpicpu_pstate_set(sc->sc_ci, acpicpu_pstate_saved);
309 acpicpu_pstate_saved = 0;
310 }
311
312 return true;
313 }
314
315 void
316 acpicpu_pstate_callback(void *aux)
317 {
318 struct acpicpu_softc *sc;
319 device_t self = aux;
320 uint32_t old, new;
321
322 sc = device_private(self);
323
324 mutex_enter(&sc->sc_mtx);
325
326 old = sc->sc_pstate_max;
327 acpicpu_pstate_change(sc);
328 new = sc->sc_pstate_max;
329
330 if (old == new) {
331 mutex_exit(&sc->sc_mtx);
332 return;
333 }
334
335 mutex_exit(&sc->sc_mtx);
336
337 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "maximum frequency "
338 "changed from P%u (%u MHz) to P%u (%u MHz)\n",
339 old, sc->sc_pstate[old].ps_freq, new,
340 sc->sc_pstate[sc->sc_pstate_max].ps_freq));
341
342 acpicpu_pstate_set(sc->sc_ci, sc->sc_pstate[new].ps_freq);
343 }
344
345 ACPI_STATUS
346 acpicpu_pstate_pss(struct acpicpu_softc *sc)
347 {
348 struct acpicpu_pstate *ps;
349 ACPI_OBJECT *obj;
350 ACPI_BUFFER buf;
351 ACPI_STATUS rv;
352 uint32_t count;
353 uint32_t i, j;
354
355 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PSS", &buf);
356
357 if (ACPI_FAILURE(rv))
358 return rv;
359
360 obj = buf.Pointer;
361
362 if (obj->Type != ACPI_TYPE_PACKAGE) {
363 rv = AE_TYPE;
364 goto out;
365 }
366
367 sc->sc_pstate_count = obj->Package.Count;
368
369 if (sc->sc_pstate_count == 0) {
370 rv = AE_NOT_EXIST;
371 goto out;
372 }
373
374 if (sc->sc_pstate_count > ACPICPU_P_STATE_MAX) {
375 rv = AE_LIMIT;
376 goto out;
377 }
378
379 sc->sc_pstate = kmem_zalloc(sc->sc_pstate_count *
380 sizeof(struct acpicpu_pstate), KM_SLEEP);
381
382 if (sc->sc_pstate == NULL) {
383 rv = AE_NO_MEMORY;
384 goto out;
385 }
386
387 for (count = i = 0; i < sc->sc_pstate_count; i++) {
388
389 ps = &sc->sc_pstate[i];
390 rv = acpicpu_pstate_pss_add(ps, &obj->Package.Elements[i]);
391
392 if (ACPI_FAILURE(rv)) {
393 aprint_error_dev(sc->sc_dev, "failed to add "
394 "P-state: %s\n", AcpiFormatException(rv));
395 ps->ps_freq = 0;
396 continue;
397 }
398
399 for (j = 0; j < i; j++) {
400
401 if (ps->ps_freq >= sc->sc_pstate[j].ps_freq) {
402 ps->ps_freq = 0;
403 break;
404 }
405 }
406
407 if (ps->ps_freq != 0)
408 count++;
409 }
410
411 rv = (count != 0) ? AE_OK : AE_NOT_EXIST;
412
413 out:
414 if (buf.Pointer != NULL)
415 ACPI_FREE(buf.Pointer);
416
417 return rv;
418 }
419
420 static ACPI_STATUS
421 acpicpu_pstate_pss_add(struct acpicpu_pstate *ps, ACPI_OBJECT *obj)
422 {
423 ACPI_OBJECT *elm;
424 int i;
425
426 if (obj->Type != ACPI_TYPE_PACKAGE)
427 return AE_TYPE;
428
429 if (obj->Package.Count != 6)
430 return AE_BAD_DATA;
431
432 elm = obj->Package.Elements;
433
434 for (i = 0; i < 6; i++) {
435
436 if (elm[i].Type != ACPI_TYPE_INTEGER)
437 return AE_TYPE;
438
439 if (elm[i].Integer.Value > UINT32_MAX)
440 return AE_AML_NUMERIC_OVERFLOW;
441 }
442
443 ps->ps_freq = elm[0].Integer.Value;
444 ps->ps_power = elm[1].Integer.Value;
445 ps->ps_latency = elm[2].Integer.Value;
446 ps->ps_latency_bm = elm[3].Integer.Value;
447 ps->ps_control = elm[4].Integer.Value;
448 ps->ps_status = elm[5].Integer.Value;
449
450 if (ps->ps_freq == 0 || ps->ps_freq > 9999)
451 return AE_BAD_DECIMAL_CONSTANT;
452
453 if (ps->ps_latency == 0 || ps->ps_latency > 1000)
454 ps->ps_latency = 1;
455
456 return AE_OK;
457 }
458
459 static ACPI_STATUS
460 acpicpu_pstate_xpss(struct acpicpu_softc *sc)
461 {
462 struct acpicpu_pstate *ps;
463 ACPI_OBJECT *obj;
464 ACPI_BUFFER buf;
465 ACPI_STATUS rv;
466 uint32_t i = 0;
467
468 rv = acpi_eval_struct(sc->sc_node->ad_handle, "XPSS", &buf);
469
470 if (ACPI_FAILURE(rv))
471 goto out;
472
473 obj = buf.Pointer;
474
475 if (obj->Type != ACPI_TYPE_PACKAGE) {
476 rv = AE_TYPE;
477 goto out;
478 }
479
480 if (obj->Package.Count != sc->sc_pstate_count) {
481 rv = AE_LIMIT;
482 goto out;
483 }
484
485 while (i < sc->sc_pstate_count) {
486
487 ps = &sc->sc_pstate[i];
488 acpicpu_pstate_xpss_add(ps, &obj->Package.Elements[i]);
489
490 i++;
491 }
492
493 out:
494 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
495 aprint_error_dev(sc->sc_dev, "failed to evaluate "
496 "XPSS: %s\n", AcpiFormatException(rv));
497
498 if (buf.Pointer != NULL)
499 ACPI_FREE(buf.Pointer);
500
501 return rv;
502 }
503
504 static ACPI_STATUS
505 acpicpu_pstate_xpss_add(struct acpicpu_pstate *ps, ACPI_OBJECT *obj)
506 {
507 ACPI_OBJECT *elm;
508 int i;
509
510 if (obj->Type != ACPI_TYPE_PACKAGE)
511 return AE_TYPE;
512
513 if (obj->Package.Count != 8)
514 return AE_BAD_DATA;
515
516 elm = obj->Package.Elements;
517
518 for (i = 0; i < 4; i++) {
519
520 if (elm[i].Type != ACPI_TYPE_INTEGER)
521 return AE_TYPE;
522
523 if (elm[i].Integer.Value > UINT32_MAX)
524 return AE_AML_NUMERIC_OVERFLOW;
525 }
526
527 for (; i < 8; i++) {
528
529 if (elm[i].Type != ACPI_TYPE_BUFFER)
530 return AE_TYPE;
531
532 if (elm[i].Buffer.Length != 8)
533 return AE_LIMIT;
534 }
535
536 /*
537 * Only overwrite the elements that were
538 * not available from the conventional _PSS.
539 */
540 if (ps->ps_freq == 0)
541 ps->ps_freq = elm[0].Integer.Value;
542
543 if (ps->ps_power == 0)
544 ps->ps_power = elm[1].Integer.Value;
545
546 if (ps->ps_latency == 0)
547 ps->ps_latency = elm[2].Integer.Value;
548
549 if (ps->ps_latency_bm == 0)
550 ps->ps_latency_bm = elm[3].Integer.Value;
551
552 if (ps->ps_control == 0)
553 ps->ps_control = ACPI_GET64(elm[4].Buffer.Pointer);
554
555 if (ps->ps_status == 0)
556 ps->ps_status = ACPI_GET64(elm[5].Buffer.Pointer);
557
558 if (ps->ps_control_mask == 0)
559 ps->ps_control_mask = ACPI_GET64(elm[6].Buffer.Pointer);
560
561 if (ps->ps_status_mask == 0)
562 ps->ps_status_mask = ACPI_GET64(elm[7].Buffer.Pointer);
563
564 ps->ps_flags |= ACPICPU_FLAG_P_XPSS;
565
566 if (ps->ps_freq == 0 || ps->ps_freq > 9999)
567 return AE_BAD_DECIMAL_CONSTANT;
568
569 if (ps->ps_latency == 0 || ps->ps_latency > 1000)
570 ps->ps_latency = 1;
571
572 return AE_OK;
573 }
574
575 ACPI_STATUS
576 acpicpu_pstate_pct(struct acpicpu_softc *sc)
577 {
578 static const size_t size = sizeof(struct acpicpu_reg);
579 struct acpicpu_reg *reg[2];
580 struct acpicpu_pstate *ps;
581 ACPI_OBJECT *elm, *obj;
582 ACPI_BUFFER buf;
583 ACPI_STATUS rv;
584 uint8_t width;
585 uint32_t i;
586
587 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PCT", &buf);
588
589 if (ACPI_FAILURE(rv))
590 return rv;
591
592 obj = buf.Pointer;
593
594 if (obj->Type != ACPI_TYPE_PACKAGE) {
595 rv = AE_TYPE;
596 goto out;
597 }
598
599 if (obj->Package.Count != 2) {
600 rv = AE_LIMIT;
601 goto out;
602 }
603
604 for (i = 0; i < 2; i++) {
605
606 elm = &obj->Package.Elements[i];
607
608 if (elm->Type != ACPI_TYPE_BUFFER) {
609 rv = AE_TYPE;
610 goto out;
611 }
612
613 if (size > elm->Buffer.Length) {
614 rv = AE_AML_BAD_RESOURCE_LENGTH;
615 goto out;
616 }
617
618 reg[i] = (struct acpicpu_reg *)elm->Buffer.Pointer;
619
620 switch (reg[i]->reg_spaceid) {
621
622 case ACPI_ADR_SPACE_SYSTEM_IO:
623
624 if (reg[i]->reg_addr == 0) {
625 rv = AE_AML_ILLEGAL_ADDRESS;
626 goto out;
627 }
628
629 width = reg[i]->reg_bitwidth;
630
631 if (width + reg[i]->reg_bitoffset > 32) {
632 rv = AE_AML_BAD_RESOURCE_VALUE;
633 goto out;
634 }
635
636 if (width != 8 && width != 16 && width != 32) {
637 rv = AE_AML_BAD_RESOURCE_VALUE;
638 goto out;
639 }
640
641 break;
642
643 case ACPI_ADR_SPACE_FIXED_HARDWARE:
644
645 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) != 0) {
646
647 if (reg[i]->reg_bitwidth != 64) {
648 rv = AE_AML_BAD_RESOURCE_VALUE;
649 goto out;
650 }
651
652 if (reg[i]->reg_bitoffset != 0) {
653 rv = AE_AML_BAD_RESOURCE_VALUE;
654 goto out;
655 }
656
657 break;
658 }
659
660 if ((sc->sc_flags & ACPICPU_FLAG_P_FFH) == 0) {
661 rv = AE_SUPPORT;
662 goto out;
663 }
664
665 break;
666
667 default:
668 rv = AE_AML_INVALID_SPACE_ID;
669 goto out;
670 }
671 }
672
673 if (reg[0]->reg_spaceid != reg[1]->reg_spaceid) {
674 rv = AE_AML_INVALID_SPACE_ID;
675 goto out;
676 }
677
678 (void)memcpy(&sc->sc_pstate_control, reg[0], size);
679 (void)memcpy(&sc->sc_pstate_status, reg[1], size);
680
681 if ((sc->sc_flags & ACPICPU_FLAG_P_XPSS) == 0)
682 goto out;
683
684 /*
685 * In XPSS the control address can not be zero,
686 * but the status address may be. In this case,
687 * comparable to T-states, we can ignore the status
688 * check during the P-state (FFH) transition.
689 */
690 if (sc->sc_pstate_control.reg_addr == 0) {
691 rv = AE_AML_BAD_RESOURCE_LENGTH;
692 goto out;
693 }
694
695 /*
696 * If XPSS is present, copy the MSR addresses
697 * to the P-state structures for convenience.
698 */
699 for (i = 0; i < sc->sc_pstate_count; i++) {
700
701 ps = &sc->sc_pstate[i];
702
703 if (ps->ps_freq == 0)
704 continue;
705
706 ps->ps_status_addr = sc->sc_pstate_status.reg_addr;
707 ps->ps_control_addr = sc->sc_pstate_control.reg_addr;
708 }
709
710 out:
711 if (buf.Pointer != NULL)
712 ACPI_FREE(buf.Pointer);
713
714 return rv;
715 }
716
717 static ACPI_STATUS
718 acpicpu_pstate_dep(struct acpicpu_softc *sc)
719 {
720 ACPI_OBJECT *elm, *obj;
721 ACPI_BUFFER buf;
722 ACPI_STATUS rv;
723 uint32_t val;
724 uint8_t i, n;
725
726 rv = acpi_eval_struct(sc->sc_node->ad_handle, "_PSD", &buf);
727
728 if (ACPI_FAILURE(rv))
729 goto out;
730
731 obj = buf.Pointer;
732
733 if (obj->Type != ACPI_TYPE_PACKAGE) {
734 rv = AE_TYPE;
735 goto out;
736 }
737
738 if (obj->Package.Count != 1) {
739 rv = AE_LIMIT;
740 goto out;
741 }
742
743 elm = &obj->Package.Elements[0];
744
745 if (obj->Type != ACPI_TYPE_PACKAGE) {
746 rv = AE_TYPE;
747 goto out;
748 }
749
750 n = elm->Package.Count;
751
752 if (n != 5) {
753 rv = AE_LIMIT;
754 goto out;
755 }
756
757 elm = elm->Package.Elements;
758
759 for (i = 0; i < n; i++) {
760
761 if (elm[i].Type != ACPI_TYPE_INTEGER) {
762 rv = AE_TYPE;
763 goto out;
764 }
765
766 if (elm[i].Integer.Value > UINT32_MAX) {
767 rv = AE_AML_NUMERIC_OVERFLOW;
768 goto out;
769 }
770 }
771
772 val = elm[1].Integer.Value;
773
774 if (val != 0)
775 aprint_debug_dev(sc->sc_dev, "invalid revision in _PSD\n");
776
777 val = elm[3].Integer.Value;
778
779 if (val < ACPICPU_DEP_SW_ALL || val > ACPICPU_DEP_HW_ALL) {
780 rv = AE_AML_BAD_RESOURCE_VALUE;
781 goto out;
782 }
783
784 val = elm[4].Integer.Value;
785
786 if (val > sc->sc_ncpus) {
787 rv = AE_BAD_VALUE;
788 goto out;
789 }
790
791 sc->sc_pstate_dep.dep_domain = elm[2].Integer.Value;
792 sc->sc_pstate_dep.dep_type = elm[3].Integer.Value;
793 sc->sc_pstate_dep.dep_ncpus = elm[4].Integer.Value;
794
795 out:
796 if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
797 aprint_debug_dev(sc->sc_dev, "failed to evaluate "
798 "_PSD: %s\n", AcpiFormatException(rv));
799
800 if (buf.Pointer != NULL)
801 ACPI_FREE(buf.Pointer);
802
803 return rv;
804 }
805
806 static int
807 acpicpu_pstate_max(struct acpicpu_softc *sc)
808 {
809 ACPI_INTEGER val;
810 ACPI_STATUS rv;
811
812 /*
813 * Evaluate the currently highest P-state that can be used.
814 * If available, we can use either this state or any lower
815 * power (i.e. higher numbered) state from the _PSS object.
816 * Note that the return value must match the _OST parameter.
817 */
818 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PPC", &val);
819
820 if (ACPI_SUCCESS(rv) && val < sc->sc_pstate_count) {
821
822 if (sc->sc_pstate[val].ps_freq != 0) {
823 sc->sc_pstate_max = val;
824 return 0;
825 }
826 }
827
828 return 1;
829 }
830
831 static int
832 acpicpu_pstate_min(struct acpicpu_softc *sc)
833 {
834 ACPI_INTEGER val;
835 ACPI_STATUS rv;
836
837 /*
838 * The _PDL object defines the minimum when passive cooling
839 * is being performed. If available, we can use the returned
840 * state or any higher power (i.e. lower numbered) state.
841 */
842 rv = acpi_eval_integer(sc->sc_node->ad_handle, "_PDL", &val);
843
844 if (ACPI_SUCCESS(rv) && val < sc->sc_pstate_count) {
845
846 if (sc->sc_pstate[val].ps_freq == 0)
847 return 1;
848
849 if (val >= sc->sc_pstate_max) {
850 sc->sc_pstate_min = val;
851 return 0;
852 }
853 }
854
855 return 1;
856 }
857
858 static void
859 acpicpu_pstate_change(struct acpicpu_softc *sc)
860 {
861 static ACPI_STATUS rv = AE_OK;
862 ACPI_OBJECT_LIST arg;
863 ACPI_OBJECT obj[2];
864 static int val = 0;
865
866 acpicpu_pstate_reset(sc);
867
868 /*
869 * Cache the checks as the optional
870 * _PDL and _OST are rarely present.
871 */
872 if (val == 0)
873 val = acpicpu_pstate_min(sc);
874
875 arg.Count = 2;
876 arg.Pointer = obj;
877
878 obj[0].Type = ACPI_TYPE_INTEGER;
879 obj[1].Type = ACPI_TYPE_INTEGER;
880
881 obj[0].Integer.Value = ACPICPU_P_NOTIFY;
882 obj[1].Integer.Value = acpicpu_pstate_max(sc);
883
884 if (ACPI_FAILURE(rv))
885 return;
886
887 rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OST", &arg, NULL);
888 }
889
890 static void
891 acpicpu_pstate_reset(struct acpicpu_softc *sc)
892 {
893
894 sc->sc_pstate_max = 0;
895 sc->sc_pstate_min = sc->sc_pstate_count - 1;
896
897 }
898
899 static void
900 acpicpu_pstate_bios(void)
901 {
902 const uint8_t val = AcpiGbl_FADT.PstateControl;
903 const uint32_t addr = AcpiGbl_FADT.SmiCommand;
904
905 if (addr == 0 || val == 0)
906 return;
907
908 (void)AcpiOsWritePort(addr, val, 8);
909 }
910
911 int
912 acpicpu_pstate_get(struct cpu_info *ci, uint32_t *freq)
913 {
914 struct acpicpu_pstate *ps = NULL;
915 struct acpicpu_softc *sc;
916 uint32_t i, val = 0;
917 uint64_t addr;
918 uint8_t width;
919 int rv;
920
921 sc = acpicpu_sc[ci->ci_acpiid];
922
923 if (__predict_false(sc == NULL)) {
924 rv = ENXIO;
925 goto fail;
926 }
927
928 if (__predict_false(sc->sc_cold != false)) {
929 rv = EBUSY;
930 goto fail;
931 }
932
933 if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P) == 0)) {
934 rv = ENODEV;
935 goto fail;
936 }
937
938 mutex_enter(&sc->sc_mtx);
939
940 /*
941 * Use the cached value, if available.
942 */
943 if (sc->sc_pstate_current != ACPICPU_P_STATE_UNKNOWN) {
944 *freq = sc->sc_pstate_current;
945 mutex_exit(&sc->sc_mtx);
946 return 0;
947 }
948
949 mutex_exit(&sc->sc_mtx);
950
951 switch (sc->sc_pstate_status.reg_spaceid) {
952
953 case ACPI_ADR_SPACE_FIXED_HARDWARE:
954
955 rv = acpicpu_md_pstate_get(sc, freq);
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_status.reg_addr;
965 width = sc->sc_pstate_status.reg_bitwidth;
966
967 (void)AcpiOsReadPort(addr, &val, width);
968
969 if (val == 0) {
970 rv = EIO;
971 goto fail;
972 }
973
974 for (i = 0; i < sc->sc_pstate_count; i++) {
975
976 if (sc->sc_pstate[i].ps_freq == 0)
977 continue;
978
979 if (val == sc->sc_pstate[i].ps_status) {
980 ps = &sc->sc_pstate[i];
981 break;
982 }
983 }
984
985 if (ps == NULL) {
986 rv = EIO;
987 goto fail;
988 }
989
990 *freq = ps->ps_freq;
991 break;
992
993 default:
994 rv = ENOTTY;
995 goto fail;
996 }
997
998 mutex_enter(&sc->sc_mtx);
999 sc->sc_pstate_current = *freq;
1000 mutex_exit(&sc->sc_mtx);
1001
1002 return 0;
1003
1004 fail:
1005 aprint_error_dev(sc->sc_dev, "failed "
1006 "to get frequency (err %d)\n", rv);
1007
1008 mutex_enter(&sc->sc_mtx);
1009 *freq = sc->sc_pstate_current = ACPICPU_P_STATE_UNKNOWN;
1010 mutex_exit(&sc->sc_mtx);
1011
1012 return rv;
1013 }
1014
1015 void
1016 acpicpu_pstate_set(struct cpu_info *ci, uint32_t freq)
1017 {
1018 uint64_t xc;
1019
1020 xc = xc_broadcast(0, acpicpu_pstate_set_xcall, &freq, NULL);
1021 xc_wait(xc);
1022 }
1023
1024 static void
1025 acpicpu_pstate_set_xcall(void *arg1, void *arg2)
1026 {
1027 struct acpicpu_pstate *ps = NULL;
1028 struct cpu_info *ci = curcpu();
1029 struct acpicpu_softc *sc;
1030 uint32_t freq, i, val;
1031 uint64_t addr;
1032 uint8_t width;
1033 int rv;
1034
1035 freq = *(uint32_t *)arg1;
1036 sc = acpicpu_sc[ci->ci_acpiid];
1037
1038 if (__predict_false(sc == NULL)) {
1039 rv = ENXIO;
1040 goto fail;
1041 }
1042
1043 if (__predict_false(sc->sc_cold != false)) {
1044 rv = EBUSY;
1045 goto fail;
1046 }
1047
1048 if (__predict_false((sc->sc_flags & ACPICPU_FLAG_P) == 0)) {
1049 rv = ENODEV;
1050 goto fail;
1051 }
1052
1053 mutex_enter(&sc->sc_mtx);
1054
1055 if (sc->sc_pstate_current == freq) {
1056 mutex_exit(&sc->sc_mtx);
1057 return;
1058 }
1059
1060 /*
1061 * Verify that the requested frequency is available.
1062 *
1063 * The access needs to be protected since the currently
1064 * available maximum and minimum may change dynamically.
1065 */
1066 for (i = sc->sc_pstate_max; i <= sc->sc_pstate_min; i++) {
1067
1068 if (__predict_false(sc->sc_pstate[i].ps_freq == 0))
1069 continue;
1070
1071 if (sc->sc_pstate[i].ps_freq == freq) {
1072 ps = &sc->sc_pstate[i];
1073 break;
1074 }
1075 }
1076
1077 mutex_exit(&sc->sc_mtx);
1078
1079 if (__predict_false(ps == NULL)) {
1080 rv = EINVAL;
1081 goto fail;
1082 }
1083
1084 switch (sc->sc_pstate_control.reg_spaceid) {
1085
1086 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1087
1088 rv = acpicpu_md_pstate_set(ps);
1089
1090 if (__predict_false(rv != 0))
1091 goto fail;
1092
1093 break;
1094
1095 case ACPI_ADR_SPACE_SYSTEM_IO:
1096
1097 addr = sc->sc_pstate_control.reg_addr;
1098 width = sc->sc_pstate_control.reg_bitwidth;
1099
1100 (void)AcpiOsWritePort(addr, ps->ps_control, width);
1101
1102 addr = sc->sc_pstate_status.reg_addr;
1103 width = sc->sc_pstate_status.reg_bitwidth;
1104
1105 /*
1106 * Some systems take longer to respond
1107 * than the reported worst-case latency.
1108 */
1109 for (i = val = 0; i < ACPICPU_P_STATE_RETRY; i++) {
1110
1111 (void)AcpiOsReadPort(addr, &val, width);
1112
1113 if (val == ps->ps_status)
1114 break;
1115
1116 DELAY(ps->ps_latency);
1117 }
1118
1119 if (i == ACPICPU_P_STATE_RETRY) {
1120 rv = EAGAIN;
1121 goto fail;
1122 }
1123
1124 break;
1125
1126 default:
1127 rv = ENOTTY;
1128 goto fail;
1129 }
1130
1131 mutex_enter(&sc->sc_mtx);
1132 ps->ps_evcnt.ev_count++;
1133 sc->sc_pstate_current = freq;
1134 mutex_exit(&sc->sc_mtx);
1135
1136 return;
1137
1138 fail:
1139 aprint_error_dev(sc->sc_dev, "failed to set "
1140 "frequency to %u (err %d)\n", freq, rv);
1141
1142 mutex_enter(&sc->sc_mtx);
1143 sc->sc_pstate_current = ACPICPU_P_STATE_UNKNOWN;
1144 mutex_exit(&sc->sc_mtx);
1145 }
1146