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