xref: /netbsd-src/sys/arch/x86/acpi/acpi_pdc.c (revision 0301c37913fa6d11e8978aaf3a22b7099f750fae)
1 /* $NetBSD: acpi_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $ */
2 
3 /*-
4  * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@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_pdc.c,v 1.2 2011/06/20 15:39:54 jruoho Exp $");
31 
32 #include <sys/param.h>
33 
34 #include <x86/cpu.h>
35 #include <x86/cputypes.h>
36 #include <x86/cpuvar.h>
37 
38 #include <dev/acpi/acpireg.h>
39 #include <dev/acpi/acpivar.h>
40 #include <dev/acpi/acpi_cpu.h>
41 
42 #include <machine/acpi_machdep.h>
43 
44 #define _COMPONENT	ACPI_BUS_COMPONENT
45 ACPI_MODULE_NAME	("acpi_pdc")
46 
47 static uint32_t		flags = 0;
48 
49 static ACPI_STATUS	acpi_md_pdc_walk(ACPI_HANDLE, uint32_t,void *,void **);
50 static void		acpi_md_pdc_set(ACPI_HANDLE, uint32_t);
51 
52 uint32_t
acpi_md_pdc(void)53 acpi_md_pdc(void)
54 {
55 	struct cpu_info *ci = curcpu();
56 	uint32_t regs[4];
57 
58 	if (flags != 0)
59 		return flags;
60 
61 	if (cpu_vendor != CPUVENDOR_IDT &&
62 	    cpu_vendor != CPUVENDOR_INTEL)
63 		return 0;
64 
65 	/*
66 	 * Basic SMP C-states (required for e.g. _CST).
67 	 */
68 	flags |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
69 
70 	/*
71 	 * Claim to support dependency coordination.
72 	 */
73 	flags |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW;
74 
75         /*
76 	 * If MONITOR/MWAIT is available, announce
77 	 * support for native instructions in all C-states.
78 	 */
79         if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
80 		flags |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
81 
82 	/*
83 	 * Set native P- and T-states, if available.
84 	 */
85         if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
86 		flags |= ACPICPU_PDC_P_FFH;
87 
88 	if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
89 		flags |= ACPICPU_PDC_T_FFH;
90 
91 	/*
92 	 * Declare support for APERF and MPERF.
93 	 */
94 	if (cpuid_level >= 0x06) {
95 
96 		x86_cpuid(0x00000006, regs);
97 
98 		if ((regs[2] & CPUID_DSPM_HWF) != 0)
99 			flags |= ACPICPU_PDC_P_HWF;
100 	}
101 
102 	/*
103 	 * As the _PDC must be evaluated before the internal namespace
104 	 * is built, we have no option but to walk with the interpreter.
105 	 */
106 	(void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
107 	    UINT32_MAX, acpi_md_pdc_walk, NULL, NULL, NULL);
108 
109 	return flags;
110 }
111 
112 static ACPI_STATUS
acpi_md_pdc_walk(ACPI_HANDLE hdl,uint32_t level,void * aux,void ** sta)113 acpi_md_pdc_walk(ACPI_HANDLE hdl, uint32_t level, void *aux, void **sta)
114 {
115 	struct cpu_info *ci;
116 
117 	ci = acpi_match_cpu_handle(hdl);
118 
119 	if (ci != NULL)
120 		acpi_md_pdc_set(hdl, flags);
121 
122 	return AE_OK;
123 }
124 
125 static void
acpi_md_pdc_set(ACPI_HANDLE hdl,uint32_t val)126 acpi_md_pdc_set(ACPI_HANDLE hdl, uint32_t val)
127 {
128 	ACPI_OBJECT_LIST arg;
129 	ACPI_OBJECT obj;
130 	uint32_t cap[3];
131 
132 	arg.Count = 1;
133 	arg.Pointer = &obj;
134 
135 	cap[0] = ACPICPU_PDC_REVID;
136 	cap[1] = 1;
137 	cap[2] = val;
138 
139 	obj.Type = ACPI_TYPE_BUFFER;
140 	obj.Buffer.Length = sizeof(cap);
141 	obj.Buffer.Pointer = (void *)cap;
142 
143 	(void)AcpiEvaluateObject(hdl, "_PDC", &arg, NULL);
144 }
145