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