xref: /netbsd-src/sys/arch/x86/acpi/acpi_pdc.c (revision d25ffa98a4bfca1fe272f3c182496ec9934faac7)
1 /* $NetBSD: acpi_pdc.c,v 1.1 2011/06/12 10:11:52 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.1 2011/06/12 10:11:52 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 ACPI_STATUS	acpi_md_pdc_set(ACPI_HANDLE, uint32_t);
51 
52 uint32_t
53 acpi_md_pdc(void)
54 {
55 	char *hid = __UNCONST("ACPI0007");
56 	struct cpu_info *ci = curcpu();
57 	uint32_t regs[4];
58 
59 	if (flags != 0)
60 		return flags;
61 
62 	if (cpu_vendor != CPUVENDOR_IDT &&
63 	    cpu_vendor != CPUVENDOR_INTEL)
64 		return 0;
65 
66 	/*
67 	 * Basic SMP C-states (required for e.g. _CST).
68 	 */
69 	flags |= ACPICPU_PDC_C_C1PT | ACPICPU_PDC_C_C2C3;
70 
71 	/*
72 	 * Claim to support dependency coordination.
73 	 */
74 	flags |= ACPICPU_PDC_P_SW | ACPICPU_PDC_C_SW | ACPICPU_PDC_T_SW;
75 
76         /*
77 	 * If MONITOR/MWAIT is available, announce
78 	 * support for native instructions in all C-states.
79 	 */
80         if ((ci->ci_feat_val[1] & CPUID2_MONITOR) != 0)
81 		flags |= ACPICPU_PDC_C_C1_FFH | ACPICPU_PDC_C_C2C3_FFH;
82 
83 	/*
84 	 * Set native P- and T-states, if available.
85 	 */
86         if ((ci->ci_feat_val[1] & CPUID2_EST) != 0)
87 		flags |= ACPICPU_PDC_P_FFH;
88 
89 	if ((ci->ci_feat_val[0] & CPUID_ACPI) != 0)
90 		flags |= ACPICPU_PDC_T_FFH;
91 
92 	/*
93 	 * Declare support for APERF and MPERF.
94 	 */
95 	if (cpuid_level >= 0x06) {
96 
97 		x86_cpuid(0x00000006, regs);
98 
99 		if ((regs[2] & CPUID_DSPM_HWF) != 0)
100 			flags |= ACPICPU_PDC_P_HWF;
101 	}
102 
103 	/*
104 	 * As the _PDC must be evaluated before the internal namespace
105 	 * is built, we have no option but to walk with the interpreter.
106 	 */
107 	(void)AcpiGetDevices(hid, acpi_md_pdc_walk, NULL, NULL);
108 
109 	(void)AcpiWalkNamespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
110 	    UINT32_MAX, acpi_md_pdc_walk, NULL, NULL, NULL);
111 
112 	return flags;
113 }
114 
115 static ACPI_STATUS
116 acpi_md_pdc_walk(ACPI_HANDLE hdl, uint32_t level, void *context, void **status)
117 {
118 	return acpi_md_pdc_set(hdl, flags);
119 }
120 
121 static ACPI_STATUS
122 acpi_md_pdc_set(ACPI_HANDLE hdl, uint32_t val)
123 {
124 	ACPI_OBJECT_LIST arg;
125 	ACPI_OBJECT obj;
126 	uint32_t cap[3];
127 
128 	arg.Count = 1;
129 	arg.Pointer = &obj;
130 
131 	cap[0] = ACPICPU_PDC_REVID;
132 	cap[1] = 1;
133 	cap[2] = val;
134 
135 	obj.Type = ACPI_TYPE_BUFFER;
136 	obj.Buffer.Length = sizeof(cap);
137 	obj.Buffer.Pointer = (void *)cap;
138 
139 	(void)AcpiEvaluateObject(hdl, "_PDC", &arg, NULL);
140 
141 	return AE_OK;
142 }
143