xref: /netbsd-src/sys/arch/x86/acpi/acpi_pdc.c (revision 0301c37913fa6d11e8978aaf3a22b7099f750fae)
1*0301c379Sjruoho /* $NetBSD: acpi_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $ */
20fc4e4abSjruoho 
30fc4e4abSjruoho /*-
40fc4e4abSjruoho  * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi>
50fc4e4abSjruoho  * All rights reserved.
60fc4e4abSjruoho  *
70fc4e4abSjruoho  * Redistribution and use in source and binary forms, with or without
80fc4e4abSjruoho  * modification, are permitted provided that the following conditions
90fc4e4abSjruoho  * are met:
100fc4e4abSjruoho  *
110fc4e4abSjruoho  * 1. Redistributions of source code must retain the above copyright
120fc4e4abSjruoho  *    notice, this list of conditions and the following disclaimer.
130fc4e4abSjruoho  * 2. Redistributions in binary form must reproduce the above copyright
140fc4e4abSjruoho  *    notice, this list of conditions and the following disclaimer in the
150fc4e4abSjruoho  *    documentation and/or other materials provided with the distribution.
160fc4e4abSjruoho  *
170fc4e4abSjruoho  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
180fc4e4abSjruoho  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190fc4e4abSjruoho  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200fc4e4abSjruoho  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
210fc4e4abSjruoho  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
220fc4e4abSjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
230fc4e4abSjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
240fc4e4abSjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
250fc4e4abSjruoho  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
260fc4e4abSjruoho  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270fc4e4abSjruoho  * SUCH DAMAGE.
280fc4e4abSjruoho  */
290fc4e4abSjruoho #include <sys/cdefs.h>
30*0301c379Sjruoho __KERNEL_RCSID(0, "$NetBSD: acpi_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $");
310fc4e4abSjruoho 
320fc4e4abSjruoho #include <sys/param.h>
330fc4e4abSjruoho 
340fc4e4abSjruoho #include <x86/cpu.h>
350fc4e4abSjruoho #include <x86/cputypes.h>
360fc4e4abSjruoho #include <x86/cpuvar.h>
370fc4e4abSjruoho 
380fc4e4abSjruoho #include <dev/acpi/acpireg.h>
390fc4e4abSjruoho #include <dev/acpi/acpivar.h>
400fc4e4abSjruoho #include <dev/acpi/acpi_cpu.h>
410fc4e4abSjruoho 
420fc4e4abSjruoho #include <machine/acpi_machdep.h>
430fc4e4abSjruoho 
440fc4e4abSjruoho #define _COMPONENT	ACPI_BUS_COMPONENT
450fc4e4abSjruoho ACPI_MODULE_NAME	("acpi_pdc")
460fc4e4abSjruoho 
470fc4e4abSjruoho static uint32_t		flags = 0;
480fc4e4abSjruoho 
490fc4e4abSjruoho static ACPI_STATUS	acpi_md_pdc_walk(ACPI_HANDLE, uint32_t,void *,void **);
50*0301c379Sjruoho static void		acpi_md_pdc_set(ACPI_HANDLE, uint32_t);
510fc4e4abSjruoho 
520fc4e4abSjruoho uint32_t
acpi_md_pdc(void)530fc4e4abSjruoho acpi_md_pdc(void)
540fc4e4abSjruoho {
550fc4e4abSjruoho 	struct cpu_info *ci = curcpu();
560fc4e4abSjruoho 	uint32_t regs[4];
570fc4e4abSjruoho 
580fc4e4abSjruoho 	if (flags != 0)
590fc4e4abSjruoho 		return flags;
600fc4e4abSjruoho 
610fc4e4abSjruoho 	if (cpu_vendor != CPUVENDOR_IDT &&
620fc4e4abSjruoho 	    cpu_vendor != CPUVENDOR_INTEL)
630fc4e4abSjruoho 		return 0;
640fc4e4abSjruoho 
650fc4e4abSjruoho 	/*
660fc4e4abSjruoho 	 * Basic SMP C-states (required for e.g. _CST).
670fc4e4abSjruoho 	 */
680fc4e4abSjruoho 	flags |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
690fc4e4abSjruoho 
700fc4e4abSjruoho 	/*
710fc4e4abSjruoho 	 * Claim to support dependency coordination.
720fc4e4abSjruoho 	 */
730fc4e4abSjruoho 	flags |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW;
740fc4e4abSjruoho 
750fc4e4abSjruoho         /*
760fc4e4abSjruoho 	 * If MONITOR/MWAIT is available, announce
770fc4e4abSjruoho 	 * support for native instructions in all C-states.
780fc4e4abSjruoho 	 */
790fc4e4abSjruoho         if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
800fc4e4abSjruoho 		flags |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
810fc4e4abSjruoho 
820fc4e4abSjruoho 	/*
830fc4e4abSjruoho 	 * Set native P- and T-states, if available.
840fc4e4abSjruoho 	 */
850fc4e4abSjruoho         if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
860fc4e4abSjruoho 		flags |= ACPICPU_PDC_P_FFH;
870fc4e4abSjruoho 
880fc4e4abSjruoho 	if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
890fc4e4abSjruoho 		flags |= ACPICPU_PDC_T_FFH;
900fc4e4abSjruoho 
910fc4e4abSjruoho 	/*
920fc4e4abSjruoho 	 * Declare support for APERF and MPERF.
930fc4e4abSjruoho 	 */
940fc4e4abSjruoho 	if (cpuid_level >= 0x06) {
950fc4e4abSjruoho 
960fc4e4abSjruoho 		x86_cpuid(0x00000006, regs);
970fc4e4abSjruoho 
980fc4e4abSjruoho 		if ((regs[2] & CPUID_DSPM_HWF) != 0)
990fc4e4abSjruoho 			flags |= ACPICPU_PDC_P_HWF;
1000fc4e4abSjruoho 	}
1010fc4e4abSjruoho 
1020fc4e4abSjruoho 	/*
1030fc4e4abSjruoho 	 * As the _PDC must be evaluated before the internal namespace
1040fc4e4abSjruoho 	 * is built, we have no option but to walk with the interpreter.
1050fc4e4abSjruoho 	 */
106*0301c379Sjruoho 	(void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
1070fc4e4abSjruoho 	    UINT32_MAX, acpi_md_pdc_walk, NULL, NULL, NULL);
1080fc4e4abSjruoho 
1090fc4e4abSjruoho 	return flags;
1100fc4e4abSjruoho }
1110fc4e4abSjruoho 
1120fc4e4abSjruoho static ACPI_STATUS
acpi_md_pdc_walk(ACPI_HANDLE hdl,uint32_t level,void * aux,void ** sta)113*0301c379Sjruoho acpi_md_pdc_walk(ACPI_HANDLE hdl, uint32_t level, void *aux, void **sta)
1140fc4e4abSjruoho {
115*0301c379Sjruoho 	struct cpu_info *ci;
116*0301c379Sjruoho 
117*0301c379Sjruoho 	ci = acpi_match_cpu_handle(hdl);
118*0301c379Sjruoho 
119*0301c379Sjruoho 	if (ci != NULL)
120*0301c379Sjruoho 		acpi_md_pdc_set(hdl, flags);
121*0301c379Sjruoho 
122*0301c379Sjruoho 	return AE_OK;
1230fc4e4abSjruoho }
1240fc4e4abSjruoho 
125*0301c379Sjruoho static void
acpi_md_pdc_set(ACPI_HANDLE hdl,uint32_t val)1260fc4e4abSjruoho acpi_md_pdc_set(ACPI_HANDLE hdl, uint32_t val)
1270fc4e4abSjruoho {
1280fc4e4abSjruoho 	ACPI_OBJECT_LIST arg;
1290fc4e4abSjruoho 	ACPI_OBJECT obj;
1300fc4e4abSjruoho 	uint32_t cap[3];
1310fc4e4abSjruoho 
1320fc4e4abSjruoho 	arg.Count = 1;
1330fc4e4abSjruoho 	arg.Pointer = &obj;
1340fc4e4abSjruoho 
1350fc4e4abSjruoho 	cap[0] = ACPICPU_PDC_REVID;
1360fc4e4abSjruoho 	cap[1] = 1;
1370fc4e4abSjruoho 	cap[2] = val;
1380fc4e4abSjruoho 
1390fc4e4abSjruoho 	obj.Type = ACPI_TYPE_BUFFER;
1400fc4e4abSjruoho 	obj.Buffer.Length = sizeof(cap);
1410fc4e4abSjruoho 	obj.Buffer.Pointer = (void *)cap;
1420fc4e4abSjruoho 
1430fc4e4abSjruoho 	(void)AcpiEvaluateObject(hdl, "_PDC", &arg, NULL);
1440fc4e4abSjruoho }
145