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