xref: /netbsd-src/sys/arch/arm/acpi/acpi_cpu_md.c (revision 30d28f20005de11b20499fed000071fb0a455337)
1*30d28f20Sjmcneill /* $NetBSD: acpi_cpu_md.c,v 1.1 2020/12/07 10:57:41 jmcneill Exp $ */
2*30d28f20Sjmcneill 
3*30d28f20Sjmcneill /*-
4*30d28f20Sjmcneill  * Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
5*30d28f20Sjmcneill  * All rights reserved.
6*30d28f20Sjmcneill  *
7*30d28f20Sjmcneill  * Redistribution and use in source and binary forms, with or without
8*30d28f20Sjmcneill  * modification, are permitted provided that the following conditions
9*30d28f20Sjmcneill  * are met:
10*30d28f20Sjmcneill  * 1. Redistributions of source code must retain the above copyright
11*30d28f20Sjmcneill  *    notice, this list of conditions and the following disclaimer.
12*30d28f20Sjmcneill  * 2. Redistributions in binary form must reproduce the above copyright
13*30d28f20Sjmcneill  *    notice, this list of conditions and the following disclaimer in the
14*30d28f20Sjmcneill  *    documentation and/or other materials provided with the distribution.
15*30d28f20Sjmcneill  *
16*30d28f20Sjmcneill  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17*30d28f20Sjmcneill  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18*30d28f20Sjmcneill  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19*30d28f20Sjmcneill  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20*30d28f20Sjmcneill  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21*30d28f20Sjmcneill  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22*30d28f20Sjmcneill  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23*30d28f20Sjmcneill  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24*30d28f20Sjmcneill  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25*30d28f20Sjmcneill  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26*30d28f20Sjmcneill  * POSSIBILITY OF SUCH DAMAGE.
27*30d28f20Sjmcneill  */
28*30d28f20Sjmcneill 
29*30d28f20Sjmcneill #include <sys/cdefs.h>
30*30d28f20Sjmcneill __KERNEL_RCSID(0, "$NetBSD: acpi_cpu_md.c,v 1.1 2020/12/07 10:57:41 jmcneill Exp $");
31*30d28f20Sjmcneill 
32*30d28f20Sjmcneill #include <sys/param.h>
33*30d28f20Sjmcneill #include <sys/bus.h>
34*30d28f20Sjmcneill #include <sys/cpu.h>
35*30d28f20Sjmcneill #include <sys/cpufreq.h>
36*30d28f20Sjmcneill #include <sys/device.h>
37*30d28f20Sjmcneill #include <sys/sysctl.h>
38*30d28f20Sjmcneill 
39*30d28f20Sjmcneill #include <dev/acpi/acpica.h>
40*30d28f20Sjmcneill #include <dev/acpi/acpivar.h>
41*30d28f20Sjmcneill #include <dev/acpi/acpi_cpu.h>
42*30d28f20Sjmcneill #include <dev/acpi/acpi_util.h>
43*30d28f20Sjmcneill 
44*30d28f20Sjmcneill static struct sysctllog *acpicpu_log = NULL;
45*30d28f20Sjmcneill 
46*30d28f20Sjmcneill /*
47*30d28f20Sjmcneill  * acpicpu_md_match --
48*30d28f20Sjmcneill  *
49*30d28f20Sjmcneill  * 	Match against an ACPI processor device node (either a device
50*30d28f20Sjmcneill  * 	with HID "ACPI0007" or a processor node) and return a pointer
51*30d28f20Sjmcneill  * 	to the corresponding CPU device's 'cpu_info' struct.
52*30d28f20Sjmcneill  *
53*30d28f20Sjmcneill  */
54*30d28f20Sjmcneill struct cpu_info *
acpicpu_md_match(device_t parent,cfdata_t cf,void * aux)55*30d28f20Sjmcneill acpicpu_md_match(device_t parent, cfdata_t cf, void *aux)
56*30d28f20Sjmcneill {
57*30d28f20Sjmcneill 	struct acpi_attach_args * const aa = aux;
58*30d28f20Sjmcneill 
59*30d28f20Sjmcneill 	return acpi_match_cpu_handle(aa->aa_node->ad_handle);
60*30d28f20Sjmcneill }
61*30d28f20Sjmcneill 
62*30d28f20Sjmcneill /*
63*30d28f20Sjmcneill  * acpicpu_md_attach --
64*30d28f20Sjmcneill  *
65*30d28f20Sjmcneill  * 	Return a pointer to the CPU device's 'cpu_info' struct
66*30d28f20Sjmcneill  * 	corresponding with this device.
67*30d28f20Sjmcneill  *
68*30d28f20Sjmcneill  */
69*30d28f20Sjmcneill struct cpu_info *
acpicpu_md_attach(device_t parent,device_t self,void * aux)70*30d28f20Sjmcneill acpicpu_md_attach(device_t parent, device_t self, void *aux)
71*30d28f20Sjmcneill {
72*30d28f20Sjmcneill 	struct acpi_attach_args * const aa = aux;
73*30d28f20Sjmcneill 
74*30d28f20Sjmcneill 	return acpi_match_cpu_handle(aa->aa_node->ad_handle);
75*30d28f20Sjmcneill }
76*30d28f20Sjmcneill 
77*30d28f20Sjmcneill /*
78*30d28f20Sjmcneill  * acpicpu_md_flags --
79*30d28f20Sjmcneill  *
80*30d28f20Sjmcneill  * 	Return a bitmask of ACPICPU_FLAG_* platform specific quirks.
81*30d28f20Sjmcneill  *
82*30d28f20Sjmcneill  */
83*30d28f20Sjmcneill uint32_t
acpicpu_md_flags(void)84*30d28f20Sjmcneill acpicpu_md_flags(void)
85*30d28f20Sjmcneill {
86*30d28f20Sjmcneill 	return 0;
87*30d28f20Sjmcneill }
88*30d28f20Sjmcneill 
89*30d28f20Sjmcneill /*
90*30d28f20Sjmcneill  * acpicpu_md_cstate_start --
91*30d28f20Sjmcneill  *
92*30d28f20Sjmcneill  * 	Not implemented.
93*30d28f20Sjmcneill  *
94*30d28f20Sjmcneill  */
95*30d28f20Sjmcneill int
acpicpu_md_cstate_start(struct acpicpu_softc * sc)96*30d28f20Sjmcneill acpicpu_md_cstate_start(struct acpicpu_softc *sc)
97*30d28f20Sjmcneill {
98*30d28f20Sjmcneill 	return EINVAL;
99*30d28f20Sjmcneill }
100*30d28f20Sjmcneill 
101*30d28f20Sjmcneill /*
102*30d28f20Sjmcneill  * acpicpu_md_cstate_stop --
103*30d28f20Sjmcneill  *
104*30d28f20Sjmcneill  * 	Not implemented.
105*30d28f20Sjmcneill  *
106*30d28f20Sjmcneill  */
107*30d28f20Sjmcneill int
acpicpu_md_cstate_stop(void)108*30d28f20Sjmcneill acpicpu_md_cstate_stop(void)
109*30d28f20Sjmcneill {
110*30d28f20Sjmcneill 	return EALREADY;
111*30d28f20Sjmcneill }
112*30d28f20Sjmcneill 
113*30d28f20Sjmcneill /*
114*30d28f20Sjmcneill  * acpicpu_md_cstate_enter --
115*30d28f20Sjmcneill  *
116*30d28f20Sjmcneill  * 	Not implemented.
117*30d28f20Sjmcneill  *
118*30d28f20Sjmcneill  */
119*30d28f20Sjmcneill void
acpicpu_md_cstate_enter(int method,int state)120*30d28f20Sjmcneill acpicpu_md_cstate_enter(int method, int state)
121*30d28f20Sjmcneill {
122*30d28f20Sjmcneill }
123*30d28f20Sjmcneill 
124*30d28f20Sjmcneill /*
125*30d28f20Sjmcneill  * acpicpu_md_pstate_init --
126*30d28f20Sjmcneill  *
127*30d28f20Sjmcneill  * 	MD initialization for P-state support. Nothing to do here.
128*30d28f20Sjmcneill  *
129*30d28f20Sjmcneill  */
130*30d28f20Sjmcneill int
acpicpu_md_pstate_init(struct acpicpu_softc * sc)131*30d28f20Sjmcneill acpicpu_md_pstate_init(struct acpicpu_softc *sc)
132*30d28f20Sjmcneill {
133*30d28f20Sjmcneill 	return 0;
134*30d28f20Sjmcneill }
135*30d28f20Sjmcneill 
136*30d28f20Sjmcneill /*
137*30d28f20Sjmcneill  * acpicpu_md_pstate_sysctl_current --
138*30d28f20Sjmcneill  *
139*30d28f20Sjmcneill  * 	sysctl(9) callback for retrieving the current CPU frequency.
140*30d28f20Sjmcneill  *
141*30d28f20Sjmcneill  */
142*30d28f20Sjmcneill static int
acpicpu_md_pstate_sysctl_current(SYSCTLFN_ARGS)143*30d28f20Sjmcneill acpicpu_md_pstate_sysctl_current(SYSCTLFN_ARGS)
144*30d28f20Sjmcneill {
145*30d28f20Sjmcneill 	struct sysctlnode node;
146*30d28f20Sjmcneill 	uint32_t freq;
147*30d28f20Sjmcneill 	int error;
148*30d28f20Sjmcneill 
149*30d28f20Sjmcneill 	freq = cpufreq_get(curcpu());
150*30d28f20Sjmcneill 	if (freq == 0)
151*30d28f20Sjmcneill 		return ENXIO;
152*30d28f20Sjmcneill 
153*30d28f20Sjmcneill 	node = *rnode;
154*30d28f20Sjmcneill 	node.sysctl_data = &freq;
155*30d28f20Sjmcneill 
156*30d28f20Sjmcneill 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
157*30d28f20Sjmcneill 	if (error || newp == NULL)
158*30d28f20Sjmcneill 		return error;
159*30d28f20Sjmcneill 
160*30d28f20Sjmcneill 	return 0;
161*30d28f20Sjmcneill }
162*30d28f20Sjmcneill 
163*30d28f20Sjmcneill /*
164*30d28f20Sjmcneill  * acpicpu_md_pstate_sysctl_target --
165*30d28f20Sjmcneill  *
166*30d28f20Sjmcneill  * 	sysctl(9) callback for setting the target CPU frequency.
167*30d28f20Sjmcneill  *
168*30d28f20Sjmcneill  */
169*30d28f20Sjmcneill static int
acpicpu_md_pstate_sysctl_target(SYSCTLFN_ARGS)170*30d28f20Sjmcneill acpicpu_md_pstate_sysctl_target(SYSCTLFN_ARGS)
171*30d28f20Sjmcneill {
172*30d28f20Sjmcneill 	struct sysctlnode node;
173*30d28f20Sjmcneill 	uint32_t freq;
174*30d28f20Sjmcneill 	int error;
175*30d28f20Sjmcneill 
176*30d28f20Sjmcneill 	freq = cpufreq_get(curcpu());
177*30d28f20Sjmcneill 	if (freq == 0)
178*30d28f20Sjmcneill 		return ENXIO;
179*30d28f20Sjmcneill 
180*30d28f20Sjmcneill 	node = *rnode;
181*30d28f20Sjmcneill 	node.sysctl_data = &freq;
182*30d28f20Sjmcneill 
183*30d28f20Sjmcneill 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
184*30d28f20Sjmcneill 	if (error || newp == NULL)
185*30d28f20Sjmcneill 		return error;
186*30d28f20Sjmcneill 
187*30d28f20Sjmcneill 	cpufreq_set_all(freq);
188*30d28f20Sjmcneill 
189*30d28f20Sjmcneill 	return 0;
190*30d28f20Sjmcneill }
191*30d28f20Sjmcneill 
192*30d28f20Sjmcneill /*
193*30d28f20Sjmcneill  * acpicpu_md_pstate_sysctl_available --
194*30d28f20Sjmcneill  *
195*30d28f20Sjmcneill  * 	sysctl(9) callback for returning a list of supported CPU frequencies.
196*30d28f20Sjmcneill  *
197*30d28f20Sjmcneill  */
198*30d28f20Sjmcneill static int
acpicpu_md_pstate_sysctl_available(SYSCTLFN_ARGS)199*30d28f20Sjmcneill acpicpu_md_pstate_sysctl_available(SYSCTLFN_ARGS)
200*30d28f20Sjmcneill {
201*30d28f20Sjmcneill 	struct acpicpu_softc * const sc = rnode->sysctl_data;
202*30d28f20Sjmcneill 	struct sysctlnode node;
203*30d28f20Sjmcneill 	char buf[1024];
204*30d28f20Sjmcneill 	size_t len;
205*30d28f20Sjmcneill 	uint32_t i;
206*30d28f20Sjmcneill 	int error;
207*30d28f20Sjmcneill 
208*30d28f20Sjmcneill 	memset(buf, 0, sizeof(buf));
209*30d28f20Sjmcneill 
210*30d28f20Sjmcneill 	mutex_enter(&sc->sc_mtx);
211*30d28f20Sjmcneill 	for (len = 0, i = sc->sc_pstate_max; i < sc->sc_pstate_count; i++) {
212*30d28f20Sjmcneill 		if (sc->sc_pstate[i].ps_freq == 0)
213*30d28f20Sjmcneill 			continue;
214*30d28f20Sjmcneill 		if (len >= sizeof(buf))
215*30d28f20Sjmcneill 			break;
216*30d28f20Sjmcneill 		len += snprintf(buf + len, sizeof(buf) - len, "%u%s",
217*30d28f20Sjmcneill 		    sc->sc_pstate[i].ps_freq,
218*30d28f20Sjmcneill 		    i < (sc->sc_pstate_count - 1) ? " " : "");
219*30d28f20Sjmcneill 	}
220*30d28f20Sjmcneill 	mutex_exit(&sc->sc_mtx);
221*30d28f20Sjmcneill 
222*30d28f20Sjmcneill 	node = *rnode;
223*30d28f20Sjmcneill 	node.sysctl_data = buf;
224*30d28f20Sjmcneill 
225*30d28f20Sjmcneill 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
226*30d28f20Sjmcneill 	if (error || newp == NULL)
227*30d28f20Sjmcneill 		return error;
228*30d28f20Sjmcneill 
229*30d28f20Sjmcneill 	return 0;
230*30d28f20Sjmcneill }
231*30d28f20Sjmcneill 
232*30d28f20Sjmcneill /*
233*30d28f20Sjmcneill  * acpicpu_md_pstate_start --
234*30d28f20Sjmcneill  *
235*30d28f20Sjmcneill  * 	MD startup for P-state support. Create sysctls here.
236*30d28f20Sjmcneill  *
237*30d28f20Sjmcneill  */
238*30d28f20Sjmcneill int
acpicpu_md_pstate_start(struct acpicpu_softc * sc)239*30d28f20Sjmcneill acpicpu_md_pstate_start(struct acpicpu_softc *sc)
240*30d28f20Sjmcneill {
241*30d28f20Sjmcneill 	const struct sysctlnode *mnode, *cnode, *fnode, *node;
242*30d28f20Sjmcneill 	int error;
243*30d28f20Sjmcneill 
244*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, NULL, &mnode,
245*30d28f20Sjmcneill 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep", NULL,
246*30d28f20Sjmcneill 	    NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL);
247*30d28f20Sjmcneill 	if (error) {
248*30d28f20Sjmcneill 		goto teardown;
249*30d28f20Sjmcneill 	}
250*30d28f20Sjmcneill 
251*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, &mnode, &cnode,
252*30d28f20Sjmcneill 	    0, CTLTYPE_NODE, "cpu", NULL,
253*30d28f20Sjmcneill 	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
254*30d28f20Sjmcneill 	if (error) {
255*30d28f20Sjmcneill 		goto teardown;
256*30d28f20Sjmcneill 	}
257*30d28f20Sjmcneill 
258*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, &cnode, &fnode,
259*30d28f20Sjmcneill 	    0, CTLTYPE_NODE, "frequency", NULL,
260*30d28f20Sjmcneill 	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
261*30d28f20Sjmcneill 	if (error) {
262*30d28f20Sjmcneill 		goto teardown;
263*30d28f20Sjmcneill 	}
264*30d28f20Sjmcneill 
265*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, &fnode, &node,
266*30d28f20Sjmcneill 	    CTLFLAG_READWRITE, CTLTYPE_INT, "target", NULL,
267*30d28f20Sjmcneill 	    acpicpu_md_pstate_sysctl_target, 0, NULL, 0, CTL_CREATE, CTL_EOL);
268*30d28f20Sjmcneill 	if (error) {
269*30d28f20Sjmcneill 		goto teardown;
270*30d28f20Sjmcneill 	}
271*30d28f20Sjmcneill 
272*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, &fnode, &node,
273*30d28f20Sjmcneill 	    CTLFLAG_READONLY, CTLTYPE_INT, "current", NULL,
274*30d28f20Sjmcneill 	    acpicpu_md_pstate_sysctl_current, 0, NULL, 0, CTL_CREATE, CTL_EOL);
275*30d28f20Sjmcneill 	if (error) {
276*30d28f20Sjmcneill 		goto teardown;
277*30d28f20Sjmcneill 	}
278*30d28f20Sjmcneill 
279*30d28f20Sjmcneill 	error = sysctl_createv(&acpicpu_log, 0, &fnode, &node,
280*30d28f20Sjmcneill 	    CTLFLAG_READONLY, CTLTYPE_STRING, "available", NULL,
281*30d28f20Sjmcneill 	    acpicpu_md_pstate_sysctl_available, 0, (void *)sc, 0, CTL_CREATE,
282*30d28f20Sjmcneill 	    CTL_EOL);
283*30d28f20Sjmcneill 	if (error) {
284*30d28f20Sjmcneill 		goto teardown;
285*30d28f20Sjmcneill 	}
286*30d28f20Sjmcneill 
287*30d28f20Sjmcneill 	return 0;
288*30d28f20Sjmcneill 
289*30d28f20Sjmcneill teardown:
290*30d28f20Sjmcneill 	if (acpicpu_log != NULL) {
291*30d28f20Sjmcneill 		sysctl_teardown(&acpicpu_log);
292*30d28f20Sjmcneill 		acpicpu_log = NULL;
293*30d28f20Sjmcneill 	}
294*30d28f20Sjmcneill 
295*30d28f20Sjmcneill 	return error;
296*30d28f20Sjmcneill }
297*30d28f20Sjmcneill 
298*30d28f20Sjmcneill /*
299*30d28f20Sjmcneill  * acpicpu_md_pstate_stop --
300*30d28f20Sjmcneill  *
301*30d28f20Sjmcneill  * 	MD shutdown for P-state support. Destroy sysctls here.
302*30d28f20Sjmcneill  *
303*30d28f20Sjmcneill  */
304*30d28f20Sjmcneill int
acpicpu_md_pstate_stop(void)305*30d28f20Sjmcneill acpicpu_md_pstate_stop(void)
306*30d28f20Sjmcneill {
307*30d28f20Sjmcneill 	if (acpicpu_log != NULL) {
308*30d28f20Sjmcneill 		sysctl_teardown(&acpicpu_log);
309*30d28f20Sjmcneill 		acpicpu_log = NULL;
310*30d28f20Sjmcneill 	}
311*30d28f20Sjmcneill 
312*30d28f20Sjmcneill 	return 0;
313*30d28f20Sjmcneill }
314*30d28f20Sjmcneill 
315*30d28f20Sjmcneill /*
316*30d28f20Sjmcneill  * acpicpu_md_pstate_get --
317*30d28f20Sjmcneill  *
318*30d28f20Sjmcneill  * 	Fixed hardware access method for getting current processor P-state.
319*30d28f20Sjmcneill  * 	Not implemented.
320*30d28f20Sjmcneill  *
321*30d28f20Sjmcneill  */
322*30d28f20Sjmcneill int
acpicpu_md_pstate_get(struct acpicpu_softc * sc,uint32_t * freq)323*30d28f20Sjmcneill acpicpu_md_pstate_get(struct acpicpu_softc *sc, uint32_t *freq)
324*30d28f20Sjmcneill {
325*30d28f20Sjmcneill 	return EINVAL;
326*30d28f20Sjmcneill }
327*30d28f20Sjmcneill 
328*30d28f20Sjmcneill /*
329*30d28f20Sjmcneill  * acpicpu_md_pstate_set --
330*30d28f20Sjmcneill  *
331*30d28f20Sjmcneill  * 	Fixed hardware access method for setting current processor P-state.
332*30d28f20Sjmcneill  * 	Not implemented.
333*30d28f20Sjmcneill  *
334*30d28f20Sjmcneill  */
335*30d28f20Sjmcneill int
acpicpu_md_pstate_set(struct acpicpu_pstate * ps)336*30d28f20Sjmcneill acpicpu_md_pstate_set(struct acpicpu_pstate *ps)
337*30d28f20Sjmcneill {
338*30d28f20Sjmcneill 	return EINVAL;
339*30d28f20Sjmcneill }
340*30d28f20Sjmcneill 
341*30d28f20Sjmcneill /*
342*30d28f20Sjmcneill  * acpicpu_md_tstate_get --
343*30d28f20Sjmcneill  *
344*30d28f20Sjmcneill  * 	Fixed hardware access method for getting current processor T-state.
345*30d28f20Sjmcneill  * 	Not implemented.
346*30d28f20Sjmcneill  *
347*30d28f20Sjmcneill  */
348*30d28f20Sjmcneill int
acpicpu_md_tstate_get(struct acpicpu_softc * sc,uint32_t * percent)349*30d28f20Sjmcneill acpicpu_md_tstate_get(struct acpicpu_softc *sc, uint32_t *percent)
350*30d28f20Sjmcneill {
351*30d28f20Sjmcneill 	return EINVAL;
352*30d28f20Sjmcneill }
353*30d28f20Sjmcneill 
354*30d28f20Sjmcneill /*
355*30d28f20Sjmcneill  * acpicpu_md_tstate_set --
356*30d28f20Sjmcneill  *
357*30d28f20Sjmcneill  * 	Fixed hardware access method for setting current processor T-state.
358*30d28f20Sjmcneill  * 	Not implemented.
359*30d28f20Sjmcneill  *
360*30d28f20Sjmcneill  */
361*30d28f20Sjmcneill int
acpicpu_md_tstate_set(struct acpicpu_tstate * ts)362*30d28f20Sjmcneill acpicpu_md_tstate_set(struct acpicpu_tstate *ts)
363*30d28f20Sjmcneill {
364*30d28f20Sjmcneill 	return EINVAL;
365*30d28f20Sjmcneill }
366