1*30d28f20Sjmcneill /* $NetBSD: acpi_cpu.c,v 1.53 2020/12/07 10:57:41 jmcneill Exp $ */
24d861e5bSjruoho
34d861e5bSjruoho /*-
4eb43e911Sjruoho * Copyright (c) 2010, 2011 Jukka Ruohonen <jruohonen@iki.fi>
54d861e5bSjruoho * All rights reserved.
64d861e5bSjruoho *
74d861e5bSjruoho * Redistribution and use in source and binary forms, with or without
84d861e5bSjruoho * modification, are permitted provided that the following conditions
94d861e5bSjruoho * are met:
104d861e5bSjruoho *
114d861e5bSjruoho * 1. Redistributions of source code must retain the above copyright
124d861e5bSjruoho * notice, this list of conditions and the following disclaimer.
134d861e5bSjruoho * 2. Redistributions in binary form must reproduce the above copyright
144d861e5bSjruoho * notice, this list of conditions and the following disclaimer in the
154d861e5bSjruoho * documentation and/or other materials provided with the distribution.
164d861e5bSjruoho *
174d861e5bSjruoho * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
184d861e5bSjruoho * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
194d861e5bSjruoho * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
204d861e5bSjruoho * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
214d861e5bSjruoho * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
224d861e5bSjruoho * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
234d861e5bSjruoho * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
244d861e5bSjruoho * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
254d861e5bSjruoho * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
264d861e5bSjruoho * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
274d861e5bSjruoho * SUCH DAMAGE.
284d861e5bSjruoho */
294d861e5bSjruoho #include <sys/cdefs.h>
30*30d28f20Sjmcneill __KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.53 2020/12/07 10:57:41 jmcneill Exp $");
314d861e5bSjruoho
324d861e5bSjruoho #include <sys/param.h>
334d861e5bSjruoho #include <sys/cpu.h>
34e98440f2Sjruoho #include <sys/evcnt.h>
354d861e5bSjruoho #include <sys/kernel.h>
364d861e5bSjruoho #include <sys/kmem.h>
374d861e5bSjruoho #include <sys/module.h>
3887a3551cSjruoho #include <sys/mutex.h>
39a5a73b2aSjruoho #include <sys/sysctl.h>
40804fdee3Sjruoho #include <sys/cpufreq.h>
414d861e5bSjruoho
424d861e5bSjruoho #include <dev/acpi/acpireg.h>
434d861e5bSjruoho #include <dev/acpi/acpivar.h>
444d861e5bSjruoho #include <dev/acpi/acpi_cpu.h>
454d861e5bSjruoho
464d861e5bSjruoho #include <machine/acpi_machdep.h>
47*30d28f20Sjmcneill
48*30d28f20Sjmcneill #if defined(__i386__) || defined(__x86_64__)
49494badebSjruoho #include <machine/cpuvar.h>
50*30d28f20Sjmcneill #endif
514d861e5bSjruoho
524d861e5bSjruoho #define _COMPONENT ACPI_BUS_COMPONENT
534d861e5bSjruoho ACPI_MODULE_NAME ("acpi_cpu")
544d861e5bSjruoho
554d861e5bSjruoho static int acpicpu_match(device_t, cfdata_t, void *);
564d861e5bSjruoho static void acpicpu_attach(device_t, device_t, void *);
574d861e5bSjruoho static int acpicpu_detach(device_t, int);
584d861e5bSjruoho static int acpicpu_once_attach(void);
594d861e5bSjruoho static int acpicpu_once_detach(void);
602510a0e2Sjruoho static void acpicpu_start(device_t);
614d861e5bSjruoho
62494badebSjruoho static ACPI_STATUS acpicpu_object(ACPI_HANDLE, struct acpicpu_object *);
634d861e5bSjruoho static uint32_t acpicpu_cap(struct acpicpu_softc *);
649d3272e7Sjruoho static ACPI_STATUS acpicpu_cap_osc(struct acpicpu_softc *,
659d3272e7Sjruoho uint32_t, uint32_t *);
664d861e5bSjruoho static void acpicpu_notify(ACPI_HANDLE, uint32_t, void *);
674d861e5bSjruoho static bool acpicpu_suspend(device_t, const pmf_qual_t *);
684d861e5bSjruoho static bool acpicpu_resume(device_t, const pmf_qual_t *);
69e98440f2Sjruoho static void acpicpu_evcnt_attach(device_t);
70e98440f2Sjruoho static void acpicpu_evcnt_detach(device_t);
71e98440f2Sjruoho static void acpicpu_debug_print(device_t);
72804fdee3Sjruoho static const char *acpicpu_debug_print_method_c(uint8_t);
73804fdee3Sjruoho static const char *acpicpu_debug_print_method_pt(uint8_t);
74e98440f2Sjruoho static const char *acpicpu_debug_print_dep(uint32_t);
754d861e5bSjruoho
76494badebSjruoho static uint32_t acpicpu_count = 0;
774d861e5bSjruoho struct acpicpu_softc **acpicpu_sc = NULL;
78a5a73b2aSjruoho static bool acpicpu_dynamic = true;
79a5a73b2aSjruoho static bool acpicpu_passive = true;
804d861e5bSjruoho
8180dcd7f7Sjruoho static const struct {
8280dcd7f7Sjruoho const char *manu;
8380dcd7f7Sjruoho const char *prod;
8480dcd7f7Sjruoho const char *vers;
8580dcd7f7Sjruoho } acpicpu_quirks[] = {
8680dcd7f7Sjruoho { "Supermicro", "PDSMi-LN4", "0123456789" },
8778d78ed5Sjruoho { "ASUSTeK Computer INC.", "M2A-MX", "Rev 1.xx" },
8880dcd7f7Sjruoho };
8980dcd7f7Sjruoho
904d861e5bSjruoho CFATTACH_DECL_NEW(acpicpu, sizeof(struct acpicpu_softc),
914d861e5bSjruoho acpicpu_match, acpicpu_attach, acpicpu_detach, NULL);
924d861e5bSjruoho
934d861e5bSjruoho static int
acpicpu_match(device_t parent,cfdata_t match,void * aux)944d861e5bSjruoho acpicpu_match(device_t parent, cfdata_t match, void *aux)
954d861e5bSjruoho {
9680dcd7f7Sjruoho const char *manu, *prod, *vers;
97cd966b24Sjruoho struct cpu_info *ci;
9880dcd7f7Sjruoho size_t i;
994d861e5bSjruoho
100494badebSjruoho if (acpi_softc == NULL)
1014d861e5bSjruoho return 0;
1024d861e5bSjruoho
10378d78ed5Sjruoho manu = pmf_get_platform("board-vendor");
10478d78ed5Sjruoho prod = pmf_get_platform("board-product");
10578d78ed5Sjruoho vers = pmf_get_platform("board-version");
10680dcd7f7Sjruoho
10780dcd7f7Sjruoho if (manu != NULL && prod != NULL && vers != NULL) {
10880dcd7f7Sjruoho
10980dcd7f7Sjruoho for (i = 0; i < __arraycount(acpicpu_quirks); i++) {
11080dcd7f7Sjruoho
11180dcd7f7Sjruoho if (strcasecmp(acpicpu_quirks[i].manu, manu) == 0 &&
11280dcd7f7Sjruoho strcasecmp(acpicpu_quirks[i].prod, prod) == 0 &&
11380dcd7f7Sjruoho strcasecmp(acpicpu_quirks[i].vers, vers) == 0)
11480dcd7f7Sjruoho return 0;
11580dcd7f7Sjruoho }
11680dcd7f7Sjruoho }
11780dcd7f7Sjruoho
118cd966b24Sjruoho ci = acpicpu_md_match(parent, match, aux);
119cd966b24Sjruoho
120cd966b24Sjruoho if (ci == NULL)
121515e411dSchristos return 0;
12244091f01Sjruoho
123d7b285b0Sjruoho if (acpi_match_cpu_info(ci) == NULL)
124d7b285b0Sjruoho return 0;
125d7b285b0Sjruoho
126d7b285b0Sjruoho return 10;
1274d861e5bSjruoho }
1284d861e5bSjruoho
1294d861e5bSjruoho static void
acpicpu_attach(device_t parent,device_t self,void * aux)1304d861e5bSjruoho acpicpu_attach(device_t parent, device_t self, void *aux)
1314d861e5bSjruoho {
1324d861e5bSjruoho struct acpicpu_softc *sc = device_private(self);
133cd966b24Sjruoho struct cpu_info *ci;
134d7b285b0Sjruoho ACPI_HANDLE hdl;
13586bc152dSjruoho cpuid_t id;
1364d861e5bSjruoho int rv;
1374d861e5bSjruoho
138cd966b24Sjruoho ci = acpicpu_md_attach(parent, self, aux);
139cd966b24Sjruoho
140cd966b24Sjruoho if (ci == NULL)
141cd966b24Sjruoho return;
142cd966b24Sjruoho
143494badebSjruoho sc->sc_ci = ci;
1444d861e5bSjruoho sc->sc_dev = self;
1452510a0e2Sjruoho sc->sc_cold = true;
1464d861e5bSjruoho
147d7b285b0Sjruoho hdl = acpi_match_cpu_info(ci);
14886bc152dSjruoho
149d7b285b0Sjruoho if (hdl == NULL) {
150494badebSjruoho aprint_normal(": failed to match processor\n");
1514d861e5bSjruoho return;
1524d861e5bSjruoho }
1534d861e5bSjruoho
154a9db528eSjruoho sc->sc_node = acpi_match_node(hdl);
155d7b285b0Sjruoho
156494badebSjruoho if (acpicpu_once_attach() != 0) {
157494badebSjruoho aprint_normal(": failed to initialize\n");
158494badebSjruoho return;
159494badebSjruoho }
160494badebSjruoho
161494badebSjruoho KASSERT(acpi_softc != NULL);
162494badebSjruoho KASSERT(acpicpu_sc != NULL);
163494badebSjruoho KASSERT(sc->sc_node != NULL);
164494badebSjruoho
16586bc152dSjruoho id = sc->sc_ci->ci_acpiid;
16686bc152dSjruoho
16786bc152dSjruoho if (acpicpu_sc[id] != NULL) {
168494badebSjruoho aprint_normal(": already attached\n");
1694d861e5bSjruoho return;
1704d861e5bSjruoho }
1714d861e5bSjruoho
1729d3272e7Sjruoho aprint_naive("\n");
1739d3272e7Sjruoho aprint_normal(": ACPI CPU\n");
1749d3272e7Sjruoho
175494badebSjruoho rv = acpicpu_object(sc->sc_node->ad_handle, &sc->sc_object);
176494badebSjruoho
177*30d28f20Sjmcneill if (ACPI_FAILURE(rv) && rv != AE_TYPE)
178494badebSjruoho aprint_verbose_dev(self, "failed to obtain CPU object\n");
179494badebSjruoho
180494badebSjruoho acpicpu_count++;
18186bc152dSjruoho acpicpu_sc[id] = sc;
1824d861e5bSjruoho
1834d861e5bSjruoho sc->sc_cap = acpicpu_cap(sc);
184a080ec14Sjruoho sc->sc_ncpus = acpi_md_ncpus();
185494badebSjruoho sc->sc_flags = acpicpu_md_flags();
1864d861e5bSjruoho
187494badebSjruoho KASSERT(acpicpu_count <= sc->sc_ncpus);
188494badebSjruoho KASSERT(sc->sc_node->ad_device == NULL);
189494badebSjruoho
190494badebSjruoho sc->sc_node->ad_device = self;
19187a3551cSjruoho mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
19287a3551cSjruoho
193*30d28f20Sjmcneill #if defined(__i386__) || defined(__x86_64__)
1944d861e5bSjruoho acpicpu_cstate_attach(self);
195*30d28f20Sjmcneill #endif
19653e8f6c9Sjruoho acpicpu_pstate_attach(self);
1976b9ff107Sjruoho acpicpu_tstate_attach(self);
19853e8f6c9Sjruoho
199494badebSjruoho acpicpu_debug_print(self);
200e98440f2Sjruoho acpicpu_evcnt_attach(self);
201494badebSjruoho
202494badebSjruoho (void)config_interrupts(self, acpicpu_start);
2034d861e5bSjruoho (void)acpi_register_notify(sc->sc_node, acpicpu_notify);
2044d861e5bSjruoho (void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume);
2054d861e5bSjruoho }
2064d861e5bSjruoho
2074d861e5bSjruoho static int
acpicpu_detach(device_t self,int flags)2084d861e5bSjruoho acpicpu_detach(device_t self, int flags)
2094d861e5bSjruoho {
2104d861e5bSjruoho struct acpicpu_softc *sc = device_private(self);
2114d861e5bSjruoho
2127a639613Sjruoho sc->sc_cold = true;
2135b407ea2Sjruoho
2145b407ea2Sjruoho acpicpu_evcnt_detach(self);
2154d861e5bSjruoho acpi_deregister_notify(sc->sc_node);
2164d861e5bSjruoho
2174fb79b4eSjruoho acpicpu_cstate_detach(self);
2184fb79b4eSjruoho acpicpu_pstate_detach(self);
2194fb79b4eSjruoho acpicpu_tstate_detach(self);
2206b9ff107Sjruoho
22187a3551cSjruoho mutex_destroy(&sc->sc_mtx);
222494badebSjruoho sc->sc_node->ad_device = NULL;
223494badebSjruoho
224494badebSjruoho acpicpu_count--;
225494badebSjruoho acpicpu_once_detach();
22687a3551cSjruoho
2274d861e5bSjruoho return 0;
2284d861e5bSjruoho }
2294d861e5bSjruoho
2304d861e5bSjruoho static int
acpicpu_once_attach(void)2314d861e5bSjruoho acpicpu_once_attach(void)
2324d861e5bSjruoho {
2334d861e5bSjruoho struct acpicpu_softc *sc;
2344d861e5bSjruoho unsigned int i;
2354d861e5bSjruoho
236494badebSjruoho if (acpicpu_count != 0)
237494badebSjruoho return 0;
238494badebSjruoho
239494badebSjruoho KASSERT(acpicpu_sc == NULL);
240494badebSjruoho
2414d861e5bSjruoho acpicpu_sc = kmem_zalloc(maxcpus * sizeof(*sc), KM_SLEEP);
2424d861e5bSjruoho
2434d861e5bSjruoho for (i = 0; i < maxcpus; i++)
2444d861e5bSjruoho acpicpu_sc[i] = NULL;
2454d861e5bSjruoho
2464d861e5bSjruoho return 0;
2474d861e5bSjruoho }
2484d861e5bSjruoho
2494d861e5bSjruoho static int
acpicpu_once_detach(void)2504d861e5bSjruoho acpicpu_once_detach(void)
2514d861e5bSjruoho {
2524d861e5bSjruoho struct acpicpu_softc *sc;
2534d861e5bSjruoho
254494badebSjruoho if (acpicpu_count != 0)
255494badebSjruoho return EDEADLK;
2564d861e5bSjruoho
25777e84d0eSjruoho cpufreq_deregister();
25877e84d0eSjruoho
25977e84d0eSjruoho if (acpicpu_sc != NULL)
260494badebSjruoho kmem_free(acpicpu_sc, maxcpus * sizeof(*sc));
261494badebSjruoho
2624d861e5bSjruoho return 0;
2634d861e5bSjruoho }
2644d861e5bSjruoho
2652510a0e2Sjruoho static void
acpicpu_start(device_t self)2665ecdb7f3Sjruoho acpicpu_start(device_t self)
2675ecdb7f3Sjruoho {
2685ecdb7f3Sjruoho struct acpicpu_softc *sc = device_private(self);
269494badebSjruoho static uint32_t count = 0;
270804fdee3Sjruoho struct cpufreq cf;
271804fdee3Sjruoho uint32_t i;
2725ecdb7f3Sjruoho
2732510a0e2Sjruoho /*
274494badebSjruoho * Run the state-specific initialization routines. These
275494badebSjruoho * must run only once, after interrupts have been enabled,
276494badebSjruoho * all CPUs are running, and all ACPI CPUs have attached.
277494badebSjruoho */
278494badebSjruoho if (++count != acpicpu_count || acpicpu_count != sc->sc_ncpus) {
279494badebSjruoho sc->sc_cold = false;
280494badebSjruoho return;
281494badebSjruoho }
282494badebSjruoho
283494badebSjruoho /*
284494badebSjruoho * Set the last ACPI CPU as non-cold
285494badebSjruoho * only after C-states are enabled.
2862510a0e2Sjruoho */
2872510a0e2Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
2882510a0e2Sjruoho acpicpu_cstate_start(self);
2892510a0e2Sjruoho
290494badebSjruoho sc->sc_cold = false;
291494badebSjruoho
2922510a0e2Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
2932510a0e2Sjruoho acpicpu_pstate_start(self);
2942510a0e2Sjruoho
2952510a0e2Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
2962510a0e2Sjruoho acpicpu_tstate_start(self);
2972510a0e2Sjruoho
298494badebSjruoho aprint_debug_dev(self, "ACPI CPUs started\n");
299804fdee3Sjruoho
300804fdee3Sjruoho /*
301804fdee3Sjruoho * Register with cpufreq(9).
302804fdee3Sjruoho */
303804fdee3Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_P) != 0) {
304804fdee3Sjruoho
305804fdee3Sjruoho (void)memset(&cf, 0, sizeof(struct cpufreq));
306804fdee3Sjruoho
307804fdee3Sjruoho cf.cf_mp = false;
308804fdee3Sjruoho cf.cf_cookie = NULL;
309804fdee3Sjruoho cf.cf_get_freq = acpicpu_pstate_get;
310804fdee3Sjruoho cf.cf_set_freq = acpicpu_pstate_set;
311804fdee3Sjruoho cf.cf_state_count = sc->sc_pstate_count;
312804fdee3Sjruoho
313804fdee3Sjruoho (void)strlcpy(cf.cf_name, "acpicpu", sizeof(cf.cf_name));
314804fdee3Sjruoho
315804fdee3Sjruoho for (i = 0; i < sc->sc_pstate_count; i++) {
316804fdee3Sjruoho
317804fdee3Sjruoho if (sc->sc_pstate[i].ps_freq == 0)
318804fdee3Sjruoho continue;
319804fdee3Sjruoho
320804fdee3Sjruoho cf.cf_state[i].cfs_freq = sc->sc_pstate[i].ps_freq;
321804fdee3Sjruoho cf.cf_state[i].cfs_power = sc->sc_pstate[i].ps_power;
322804fdee3Sjruoho }
323804fdee3Sjruoho
324804fdee3Sjruoho if (cpufreq_register(&cf) != 0)
325804fdee3Sjruoho aprint_error_dev(self, "failed to register cpufreq\n");
326804fdee3Sjruoho }
3272510a0e2Sjruoho }
3282510a0e2Sjruoho
3299120d451Spgoyette SYSCTL_SETUP(acpicpu_sysctl, "acpi_cpu sysctls")
330a5a73b2aSjruoho {
331a5a73b2aSjruoho const struct sysctlnode *node;
332a5a73b2aSjruoho int err;
333a5a73b2aSjruoho
3349120d451Spgoyette err = sysctl_createv(clog, 0, NULL, &node,
335a5a73b2aSjruoho CTLFLAG_PERMANENT, CTLTYPE_NODE, "acpi", NULL,
3364f6fb3bfSpooka NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
337a5a73b2aSjruoho
338a5a73b2aSjruoho if (err != 0)
339a5a73b2aSjruoho goto fail;
340a5a73b2aSjruoho
3419120d451Spgoyette err = sysctl_createv(clog, 0, &node, &node,
342a5a73b2aSjruoho 0, CTLTYPE_NODE, "cpu", SYSCTL_DESCR("ACPI CPU"),
343a5a73b2aSjruoho NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
344a5a73b2aSjruoho
345a5a73b2aSjruoho if (err != 0)
346a5a73b2aSjruoho goto fail;
347a5a73b2aSjruoho
3489120d451Spgoyette err = sysctl_createv(clog, 0, &node, NULL,
349a5a73b2aSjruoho CTLFLAG_READWRITE, CTLTYPE_BOOL, "dynamic",
350a5a73b2aSjruoho SYSCTL_DESCR("Dynamic states"), NULL, 0,
351a5a73b2aSjruoho &acpicpu_dynamic, 0, CTL_CREATE, CTL_EOL);
352a5a73b2aSjruoho
353a5a73b2aSjruoho if (err != 0)
354a5a73b2aSjruoho goto fail;
355a5a73b2aSjruoho
3569120d451Spgoyette err = sysctl_createv(clog, 0, &node, NULL,
357a5a73b2aSjruoho CTLFLAG_READWRITE, CTLTYPE_BOOL, "passive",
358a5a73b2aSjruoho SYSCTL_DESCR("Passive cooling"), NULL, 0,
359a5a73b2aSjruoho &acpicpu_passive, 0, CTL_CREATE, CTL_EOL);
360a5a73b2aSjruoho
361a5a73b2aSjruoho if (err != 0)
362a5a73b2aSjruoho goto fail;
363a5a73b2aSjruoho
364a5a73b2aSjruoho return;
365a5a73b2aSjruoho
366a5a73b2aSjruoho fail:
3679120d451Spgoyette aprint_error("%s: failed to init sysctl (err %d)\n", __func__, err);
368a5a73b2aSjruoho }
369a5a73b2aSjruoho
370494badebSjruoho static ACPI_STATUS
acpicpu_object(ACPI_HANDLE hdl,struct acpicpu_object * ao)3714d861e5bSjruoho acpicpu_object(ACPI_HANDLE hdl, struct acpicpu_object *ao)
3724d861e5bSjruoho {
373*30d28f20Sjmcneill ACPI_OBJECT_TYPE typ;
3744d861e5bSjruoho ACPI_OBJECT *obj;
3754d861e5bSjruoho ACPI_BUFFER buf;
3764d861e5bSjruoho ACPI_STATUS rv;
3774d861e5bSjruoho
378*30d28f20Sjmcneill rv = AcpiGetType(hdl, &typ);
379*30d28f20Sjmcneill if (typ != ACPI_TYPE_PROCESSOR) {
380*30d28f20Sjmcneill return AE_TYPE;
381*30d28f20Sjmcneill }
382*30d28f20Sjmcneill
3834d861e5bSjruoho rv = acpi_eval_struct(hdl, NULL, &buf);
3844d861e5bSjruoho
3854d861e5bSjruoho if (ACPI_FAILURE(rv))
386494badebSjruoho goto out;
3874d861e5bSjruoho
3884d861e5bSjruoho obj = buf.Pointer;
3894d861e5bSjruoho
3904d861e5bSjruoho if (obj->Type != ACPI_TYPE_PROCESSOR) {
3914d861e5bSjruoho rv = AE_TYPE;
3924d861e5bSjruoho goto out;
3934d861e5bSjruoho }
3944d861e5bSjruoho
3954d861e5bSjruoho if (obj->Processor.ProcId > (uint32_t)maxcpus) {
3964d861e5bSjruoho rv = AE_LIMIT;
3974d861e5bSjruoho goto out;
3984d861e5bSjruoho }
3994d861e5bSjruoho
4004d861e5bSjruoho KDASSERT((uint64_t)obj->Processor.PblkAddress < UINT32_MAX);
4014d861e5bSjruoho
4024d861e5bSjruoho if (ao != NULL) {
4034d861e5bSjruoho ao->ao_procid = obj->Processor.ProcId;
4044d861e5bSjruoho ao->ao_pblklen = obj->Processor.PblkLength;
4054d861e5bSjruoho ao->ao_pblkaddr = obj->Processor.PblkAddress;
4064d861e5bSjruoho }
4074d861e5bSjruoho
4084d861e5bSjruoho out:
4094d861e5bSjruoho if (buf.Pointer != NULL)
4104d861e5bSjruoho ACPI_FREE(buf.Pointer);
4114d861e5bSjruoho
412494badebSjruoho return rv;
4134d861e5bSjruoho }
4144d861e5bSjruoho
4154d861e5bSjruoho static uint32_t
acpicpu_cap(struct acpicpu_softc * sc)4164d861e5bSjruoho acpicpu_cap(struct acpicpu_softc *sc)
4174d861e5bSjruoho {
4189d3272e7Sjruoho uint32_t flags, cap = 0;
4194d861e5bSjruoho ACPI_STATUS rv;
4204d861e5bSjruoho
4214d861e5bSjruoho /*
4229d3272e7Sjruoho * Query and set machine-dependent capabilities.
4230fc4e4abSjruoho * Note that the Intel-specific _PDC method has
4240fc4e4abSjruoho * already been evaluated. It was furthermore
4259d3272e7Sjruoho * deprecated in the ACPI 3.0 in favor of _OSC.
4264d861e5bSjruoho */
4270fc4e4abSjruoho flags = acpi_md_pdc();
4289d3272e7Sjruoho rv = acpicpu_cap_osc(sc, flags, &cap);
4294d861e5bSjruoho
4309d3272e7Sjruoho if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
4314d861e5bSjruoho
4329d3272e7Sjruoho aprint_error_dev(sc->sc_dev, "failed to evaluate "
4330fc4e4abSjruoho "_OSC: %s\n", AcpiFormatException(rv));
4349d3272e7Sjruoho }
4359d3272e7Sjruoho
4360fc4e4abSjruoho return (cap != 0) ? cap : flags;
4374d861e5bSjruoho }
4384d861e5bSjruoho
4394d861e5bSjruoho static ACPI_STATUS
acpicpu_cap_osc(struct acpicpu_softc * sc,uint32_t flags,uint32_t * val)4409d3272e7Sjruoho acpicpu_cap_osc(struct acpicpu_softc *sc, uint32_t flags, uint32_t *val)
4414d861e5bSjruoho {
4429d3272e7Sjruoho ACPI_OBJECT_LIST arg;
4439d3272e7Sjruoho ACPI_OBJECT obj[4];
4449d3272e7Sjruoho ACPI_OBJECT *osc;
4454d861e5bSjruoho ACPI_BUFFER buf;
4464d861e5bSjruoho ACPI_STATUS rv;
4479d3272e7Sjruoho uint32_t cap[2];
4489d3272e7Sjruoho uint32_t *ptr;
4499d3272e7Sjruoho int i = 5;
4504d861e5bSjruoho
4519d3272e7Sjruoho static uint8_t intel_uuid[16] = {
4524d861e5bSjruoho 0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
4534d861e5bSjruoho 0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
4544d861e5bSjruoho };
4554d861e5bSjruoho
4569d3272e7Sjruoho cap[0] = ACPI_OSC_QUERY;
4579d3272e7Sjruoho cap[1] = flags;
4584d861e5bSjruoho
4599d3272e7Sjruoho again:
4609d3272e7Sjruoho arg.Count = 4;
4619d3272e7Sjruoho arg.Pointer = obj;
4624d861e5bSjruoho
4639d3272e7Sjruoho obj[0].Type = ACPI_TYPE_BUFFER;
4649d3272e7Sjruoho obj[0].Buffer.Length = sizeof(intel_uuid);
4659d3272e7Sjruoho obj[0].Buffer.Pointer = intel_uuid;
4664d861e5bSjruoho
4679d3272e7Sjruoho obj[1].Type = ACPI_TYPE_INTEGER;
4689d3272e7Sjruoho obj[1].Integer.Value = ACPICPU_PDC_REVID;
4694d861e5bSjruoho
4709d3272e7Sjruoho obj[2].Type = ACPI_TYPE_INTEGER;
4719d3272e7Sjruoho obj[2].Integer.Value = __arraycount(cap);
4724d861e5bSjruoho
4739d3272e7Sjruoho obj[3].Type = ACPI_TYPE_BUFFER;
4749d3272e7Sjruoho obj[3].Buffer.Length = sizeof(cap);
4759d3272e7Sjruoho obj[3].Buffer.Pointer = (void *)cap;
4764d861e5bSjruoho
4774d861e5bSjruoho buf.Pointer = NULL;
4784d861e5bSjruoho buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
4794d861e5bSjruoho
4809d3272e7Sjruoho rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OSC", &arg, &buf);
4814d861e5bSjruoho
4824d861e5bSjruoho if (ACPI_FAILURE(rv))
4839d3272e7Sjruoho goto out;
4844d861e5bSjruoho
4859d3272e7Sjruoho osc = buf.Pointer;
4864d861e5bSjruoho
4879d3272e7Sjruoho if (osc->Type != ACPI_TYPE_BUFFER) {
4884d861e5bSjruoho rv = AE_TYPE;
4894d861e5bSjruoho goto out;
4904d861e5bSjruoho }
4914d861e5bSjruoho
4929d3272e7Sjruoho if (osc->Buffer.Length != sizeof(cap)) {
4934d861e5bSjruoho rv = AE_BUFFER_OVERFLOW;
4944d861e5bSjruoho goto out;
4954d861e5bSjruoho }
4964d861e5bSjruoho
4979d3272e7Sjruoho ptr = (uint32_t *)osc->Buffer.Pointer;
4989d3272e7Sjruoho
4999d3272e7Sjruoho if ((ptr[0] & ACPI_OSC_ERROR) != 0) {
5009d3272e7Sjruoho rv = AE_ERROR;
5019d3272e7Sjruoho goto out;
5029d3272e7Sjruoho }
5039d3272e7Sjruoho
5049d3272e7Sjruoho if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) {
5059d3272e7Sjruoho rv = AE_BAD_PARAMETER;
5069d3272e7Sjruoho goto out;
5079d3272e7Sjruoho }
5089d3272e7Sjruoho
5099d3272e7Sjruoho /*
5109d3272e7Sjruoho * "It is strongly recommended that the OS evaluate
5119d3272e7Sjruoho * _OSC with the Query Support Flag set until _OSC
5129d3272e7Sjruoho * returns the Capabilities Masked bit clear, to
5139d3272e7Sjruoho * negotiate the set of features to be granted to
5149d3272e7Sjruoho * the OS for native support (ACPI 4.0, 6.2.10)."
5159d3272e7Sjruoho */
5169d3272e7Sjruoho if ((ptr[0] & ACPI_OSC_ERROR_MASKED) != 0 && i >= 0) {
5179d3272e7Sjruoho
5189d3272e7Sjruoho ACPI_FREE(buf.Pointer);
5199d3272e7Sjruoho i--;
5209d3272e7Sjruoho
5219d3272e7Sjruoho goto again;
5229d3272e7Sjruoho }
5239d3272e7Sjruoho
5249d3272e7Sjruoho if ((cap[0] & ACPI_OSC_QUERY) != 0) {
5259d3272e7Sjruoho
5269d3272e7Sjruoho ACPI_FREE(buf.Pointer);
5279d3272e7Sjruoho cap[0] &= ~ACPI_OSC_QUERY;
5289d3272e7Sjruoho
5299d3272e7Sjruoho goto again;
5309d3272e7Sjruoho }
5319d3272e7Sjruoho
5329d3272e7Sjruoho /*
5339d3272e7Sjruoho * It is permitted for _OSC to return all
5349d3272e7Sjruoho * bits cleared, but this is specified to
5359d3272e7Sjruoho * vary on per-device basis. Assume that
5369d3272e7Sjruoho * everything rather than nothing will be
537fcd28418Sjruoho * supported in this case; we do not need
5389d3272e7Sjruoho * the firmware to know the CPU features.
5399d3272e7Sjruoho */
5409d3272e7Sjruoho *val = (ptr[1] != 0) ? ptr[1] : cap[1];
5414d861e5bSjruoho
5424d861e5bSjruoho out:
5434d861e5bSjruoho if (buf.Pointer != NULL)
5444d861e5bSjruoho ACPI_FREE(buf.Pointer);
5454d861e5bSjruoho
5464d861e5bSjruoho return rv;
5474d861e5bSjruoho }
5484d861e5bSjruoho
5494d861e5bSjruoho static void
acpicpu_notify(ACPI_HANDLE hdl,uint32_t evt,void * aux)5504d861e5bSjruoho acpicpu_notify(ACPI_HANDLE hdl, uint32_t evt, void *aux)
5514d861e5bSjruoho {
5524d861e5bSjruoho ACPI_OSD_EXEC_CALLBACK func;
5534d861e5bSjruoho struct acpicpu_softc *sc;
5544d861e5bSjruoho device_t self = aux;
5554d861e5bSjruoho
5564d861e5bSjruoho sc = device_private(self);
5574d861e5bSjruoho
558e9a3c2e5Sjruoho if (sc->sc_cold != false)
559e9a3c2e5Sjruoho return;
560e9a3c2e5Sjruoho
561a5a73b2aSjruoho if (acpicpu_dynamic != true)
562a5a73b2aSjruoho return;
563a5a73b2aSjruoho
5644d861e5bSjruoho switch (evt) {
5654d861e5bSjruoho
5664d861e5bSjruoho case ACPICPU_C_NOTIFY:
5674d861e5bSjruoho
5684d861e5bSjruoho if ((sc->sc_flags & ACPICPU_FLAG_C) == 0)
5694d861e5bSjruoho return;
5704d861e5bSjruoho
5714d861e5bSjruoho func = acpicpu_cstate_callback;
5724d861e5bSjruoho break;
5734d861e5bSjruoho
5744d861e5bSjruoho case ACPICPU_P_NOTIFY:
5754d861e5bSjruoho
5764d861e5bSjruoho if ((sc->sc_flags & ACPICPU_FLAG_P) == 0)
5774d861e5bSjruoho return;
5784d861e5bSjruoho
57953e8f6c9Sjruoho func = acpicpu_pstate_callback;
5804d861e5bSjruoho break;
5814d861e5bSjruoho
5824d861e5bSjruoho case ACPICPU_T_NOTIFY:
5834d861e5bSjruoho
5844d861e5bSjruoho if ((sc->sc_flags & ACPICPU_FLAG_T) == 0)
5854d861e5bSjruoho return;
5864d861e5bSjruoho
5876b9ff107Sjruoho func = acpicpu_tstate_callback;
5884d861e5bSjruoho break;
5894d861e5bSjruoho
5904d861e5bSjruoho default:
5914d861e5bSjruoho aprint_error_dev(sc->sc_dev, "unknown notify: 0x%02X\n", evt);
5924d861e5bSjruoho return;
5934d861e5bSjruoho }
5944d861e5bSjruoho
5954d861e5bSjruoho (void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, sc->sc_dev);
5964d861e5bSjruoho }
5974d861e5bSjruoho
5984d861e5bSjruoho static bool
acpicpu_suspend(device_t self,const pmf_qual_t * qual)5994d861e5bSjruoho acpicpu_suspend(device_t self, const pmf_qual_t *qual)
6004d861e5bSjruoho {
6014d861e5bSjruoho struct acpicpu_softc *sc = device_private(self);
6024d861e5bSjruoho
6034d861e5bSjruoho if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
6044d861e5bSjruoho (void)acpicpu_cstate_suspend(self);
6054d861e5bSjruoho
60653e8f6c9Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
60753e8f6c9Sjruoho (void)acpicpu_pstate_suspend(self);
60853e8f6c9Sjruoho
6096b9ff107Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
6106b9ff107Sjruoho (void)acpicpu_tstate_suspend(self);
6116b9ff107Sjruoho
612c1f0324cSjruoho sc->sc_cold = true;
613c1f0324cSjruoho
6144d861e5bSjruoho return true;
6154d861e5bSjruoho }
6164d861e5bSjruoho
6174d861e5bSjruoho static bool
acpicpu_resume(device_t self,const pmf_qual_t * qual)6184d861e5bSjruoho acpicpu_resume(device_t self, const pmf_qual_t *qual)
6194d861e5bSjruoho {
6204d861e5bSjruoho struct acpicpu_softc *sc = device_private(self);
6218e61d414Sjruoho static const int handler = OSL_NOTIFY_HANDLER;
6224d861e5bSjruoho
623c1f0324cSjruoho sc->sc_cold = false;
624c1f0324cSjruoho
6254d861e5bSjruoho if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
6268e61d414Sjruoho (void)AcpiOsExecute(handler, acpicpu_cstate_resume, self);
6274d861e5bSjruoho
62853e8f6c9Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
6298e61d414Sjruoho (void)AcpiOsExecute(handler, acpicpu_pstate_resume, self);
63053e8f6c9Sjruoho
6316b9ff107Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
6328e61d414Sjruoho (void)AcpiOsExecute(handler, acpicpu_tstate_resume, self);
6336b9ff107Sjruoho
6344d861e5bSjruoho return true;
6354d861e5bSjruoho }
6364d861e5bSjruoho
637a080ec14Sjruoho static void
acpicpu_evcnt_attach(device_t self)638e98440f2Sjruoho acpicpu_evcnt_attach(device_t self)
639e98440f2Sjruoho {
640e98440f2Sjruoho struct acpicpu_softc *sc = device_private(self);
641e98440f2Sjruoho struct acpicpu_cstate *cs;
642e98440f2Sjruoho struct acpicpu_pstate *ps;
643e98440f2Sjruoho struct acpicpu_tstate *ts;
644e98440f2Sjruoho const char *str;
645e98440f2Sjruoho uint32_t i;
646e98440f2Sjruoho
647e98440f2Sjruoho for (i = 0; i < __arraycount(sc->sc_cstate); i++) {
648e98440f2Sjruoho
649e98440f2Sjruoho cs = &sc->sc_cstate[i];
650e98440f2Sjruoho
651e98440f2Sjruoho if (cs->cs_method == 0)
652e98440f2Sjruoho continue;
653e98440f2Sjruoho
654e98440f2Sjruoho str = "HALT";
655e98440f2Sjruoho
656e98440f2Sjruoho if (cs->cs_method == ACPICPU_C_STATE_FFH)
657e98440f2Sjruoho str = "MWAIT";
658e98440f2Sjruoho
659e98440f2Sjruoho if (cs->cs_method == ACPICPU_C_STATE_SYSIO)
660e98440f2Sjruoho str = "I/O";
661e98440f2Sjruoho
662e98440f2Sjruoho (void)snprintf(cs->cs_name, sizeof(cs->cs_name),
663e98440f2Sjruoho "C%d (%s)", i, str);
664e98440f2Sjruoho
665e98440f2Sjruoho evcnt_attach_dynamic(&cs->cs_evcnt, EVCNT_TYPE_MISC,
666e98440f2Sjruoho NULL, device_xname(sc->sc_dev), cs->cs_name);
667e98440f2Sjruoho }
668e98440f2Sjruoho
669e98440f2Sjruoho for (i = 0; i < sc->sc_pstate_count; i++) {
670e98440f2Sjruoho
671e98440f2Sjruoho ps = &sc->sc_pstate[i];
672e98440f2Sjruoho
673e98440f2Sjruoho if (ps->ps_freq == 0)
674e98440f2Sjruoho continue;
675e98440f2Sjruoho
676e98440f2Sjruoho (void)snprintf(ps->ps_name, sizeof(ps->ps_name),
677e98440f2Sjruoho "P%u (%u MHz)", i, ps->ps_freq);
678e98440f2Sjruoho
679e98440f2Sjruoho evcnt_attach_dynamic(&ps->ps_evcnt, EVCNT_TYPE_MISC,
680e98440f2Sjruoho NULL, device_xname(sc->sc_dev), ps->ps_name);
681e98440f2Sjruoho }
682e98440f2Sjruoho
683e98440f2Sjruoho for (i = 0; i < sc->sc_tstate_count; i++) {
684e98440f2Sjruoho
685e98440f2Sjruoho ts = &sc->sc_tstate[i];
686e98440f2Sjruoho
687e98440f2Sjruoho if (ts->ts_percent == 0)
688e98440f2Sjruoho continue;
689e98440f2Sjruoho
690e98440f2Sjruoho (void)snprintf(ts->ts_name, sizeof(ts->ts_name),
691e98440f2Sjruoho "T%u (%u %%)", i, ts->ts_percent);
692e98440f2Sjruoho
693e98440f2Sjruoho evcnt_attach_dynamic(&ts->ts_evcnt, EVCNT_TYPE_MISC,
694e98440f2Sjruoho NULL, device_xname(sc->sc_dev), ts->ts_name);
695e98440f2Sjruoho }
696e98440f2Sjruoho }
697e98440f2Sjruoho
698e98440f2Sjruoho static void
acpicpu_evcnt_detach(device_t self)699e98440f2Sjruoho acpicpu_evcnt_detach(device_t self)
700e98440f2Sjruoho {
701e98440f2Sjruoho struct acpicpu_softc *sc = device_private(self);
702e98440f2Sjruoho struct acpicpu_cstate *cs;
703e98440f2Sjruoho struct acpicpu_pstate *ps;
704e98440f2Sjruoho struct acpicpu_tstate *ts;
705e98440f2Sjruoho uint32_t i;
706e98440f2Sjruoho
707e98440f2Sjruoho for (i = 0; i < __arraycount(sc->sc_cstate); i++) {
708e98440f2Sjruoho
709e98440f2Sjruoho cs = &sc->sc_cstate[i];
710e98440f2Sjruoho
711e98440f2Sjruoho if (cs->cs_method != 0)
712e98440f2Sjruoho evcnt_detach(&cs->cs_evcnt);
713e98440f2Sjruoho }
714e98440f2Sjruoho
715e98440f2Sjruoho for (i = 0; i < sc->sc_pstate_count; i++) {
716e98440f2Sjruoho
717e98440f2Sjruoho ps = &sc->sc_pstate[i];
718e98440f2Sjruoho
719e98440f2Sjruoho if (ps->ps_freq != 0)
720e98440f2Sjruoho evcnt_detach(&ps->ps_evcnt);
721e98440f2Sjruoho }
722e98440f2Sjruoho
723e98440f2Sjruoho for (i = 0; i < sc->sc_tstate_count; i++) {
724e98440f2Sjruoho
725e98440f2Sjruoho ts = &sc->sc_tstate[i];
726e98440f2Sjruoho
727e98440f2Sjruoho if (ts->ts_percent != 0)
728e98440f2Sjruoho evcnt_detach(&ts->ts_evcnt);
729e98440f2Sjruoho }
730e98440f2Sjruoho }
731e98440f2Sjruoho
732e98440f2Sjruoho static void
acpicpu_debug_print(device_t self)733494badebSjruoho acpicpu_debug_print(device_t self)
734a080ec14Sjruoho {
735494badebSjruoho struct acpicpu_softc *sc = device_private(self);
736494badebSjruoho struct cpu_info *ci = sc->sc_ci;
737b9f7a5acSjruoho struct acpicpu_cstate *cs;
738b9f7a5acSjruoho struct acpicpu_pstate *ps;
739b9f7a5acSjruoho struct acpicpu_tstate *ts;
740b9f7a5acSjruoho static bool once = false;
741a080ec14Sjruoho struct acpicpu_dep *dep;
742b9f7a5acSjruoho uint32_t i, method;
743b9f7a5acSjruoho
744b9f7a5acSjruoho if (once != true) {
745b9f7a5acSjruoho
746b9f7a5acSjruoho for (i = 0; i < __arraycount(sc->sc_cstate); i++) {
747b9f7a5acSjruoho
748b9f7a5acSjruoho cs = &sc->sc_cstate[i];
749b9f7a5acSjruoho
750b9f7a5acSjruoho if (cs->cs_method == 0)
751b9f7a5acSjruoho continue;
752b9f7a5acSjruoho
753b9f7a5acSjruoho aprint_verbose_dev(sc->sc_dev, "C%d: %3s, "
7545bfb3adeSjruoho "lat %3u us, pow %5u mW%s\n", i,
755804fdee3Sjruoho acpicpu_debug_print_method_c(cs->cs_method),
756b9f7a5acSjruoho cs->cs_latency, cs->cs_power,
7575bfb3adeSjruoho (cs->cs_flags != 0) ? ", bus master check" : "");
758b9f7a5acSjruoho }
759b9f7a5acSjruoho
760b9f7a5acSjruoho method = sc->sc_pstate_control.reg_spaceid;
761b9f7a5acSjruoho
762b9f7a5acSjruoho for (i = 0; i < sc->sc_pstate_count; i++) {
763b9f7a5acSjruoho
764b9f7a5acSjruoho ps = &sc->sc_pstate[i];
765b9f7a5acSjruoho
766b9f7a5acSjruoho if (ps->ps_freq == 0)
767b9f7a5acSjruoho continue;
768b9f7a5acSjruoho
769b9f7a5acSjruoho aprint_verbose_dev(sc->sc_dev, "P%d: %3s, "
7705bfb3adeSjruoho "lat %3u us, pow %5u mW, %4u MHz%s\n", i,
771804fdee3Sjruoho acpicpu_debug_print_method_pt(method),
7725bfb3adeSjruoho ps->ps_latency, ps->ps_power, ps->ps_freq,
7735bfb3adeSjruoho (ps->ps_flags & ACPICPU_FLAG_P_TURBO) != 0 ?
7745bfb3adeSjruoho ", turbo boost" : "");
775b9f7a5acSjruoho }
776b9f7a5acSjruoho
777b9f7a5acSjruoho method = sc->sc_tstate_control.reg_spaceid;
778b9f7a5acSjruoho
779b9f7a5acSjruoho for (i = 0; i < sc->sc_tstate_count; i++) {
780b9f7a5acSjruoho
781b9f7a5acSjruoho ts = &sc->sc_tstate[i];
782b9f7a5acSjruoho
783b9f7a5acSjruoho if (ts->ts_percent == 0)
784b9f7a5acSjruoho continue;
785b9f7a5acSjruoho
786b9f7a5acSjruoho aprint_verbose_dev(sc->sc_dev, "T%u: %3s, "
787b9f7a5acSjruoho "lat %3u us, pow %5u mW, %3u %%\n", i,
788804fdee3Sjruoho acpicpu_debug_print_method_pt(method),
789b9f7a5acSjruoho ts->ts_latency, ts->ts_power, ts->ts_percent);
790b9f7a5acSjruoho }
791b9f7a5acSjruoho
792b9f7a5acSjruoho once = true;
793b9f7a5acSjruoho }
794a080ec14Sjruoho
795494badebSjruoho aprint_debug_dev(sc->sc_dev, "id %u, lapic id %u, "
796494badebSjruoho "cap 0x%04x, flags 0x%08x\n", ci->ci_acpiid,
797494badebSjruoho (uint32_t)ci->ci_cpuid, sc->sc_cap, sc->sc_flags);
798494badebSjruoho
799a080ec14Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_C_DEP) != 0) {
800a080ec14Sjruoho
801a080ec14Sjruoho dep = &sc->sc_cstate_dep;
802a080ec14Sjruoho
803a080ec14Sjruoho aprint_debug_dev(sc->sc_dev, "C-state coordination: "
804a080ec14Sjruoho "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
805a080ec14Sjruoho dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
806a080ec14Sjruoho }
807a080ec14Sjruoho
808a080ec14Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_P_DEP) != 0) {
809a080ec14Sjruoho
810a080ec14Sjruoho dep = &sc->sc_pstate_dep;
811a080ec14Sjruoho
812a080ec14Sjruoho aprint_debug_dev(sc->sc_dev, "P-state coordination: "
813a080ec14Sjruoho "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
814a080ec14Sjruoho dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
815a080ec14Sjruoho }
816a080ec14Sjruoho
817a080ec14Sjruoho if ((sc->sc_flags & ACPICPU_FLAG_T_DEP) != 0) {
818a080ec14Sjruoho
819a080ec14Sjruoho dep = &sc->sc_tstate_dep;
820a080ec14Sjruoho
821a080ec14Sjruoho aprint_debug_dev(sc->sc_dev, "T-state coordination: "
822a080ec14Sjruoho "%u CPUs, domain %u, type %s\n", dep->dep_ncpus,
823a080ec14Sjruoho dep->dep_domain, acpicpu_debug_print_dep(dep->dep_type));
824a080ec14Sjruoho }
825a080ec14Sjruoho }
826a080ec14Sjruoho
827a080ec14Sjruoho static const char *
acpicpu_debug_print_method_c(uint8_t val)828804fdee3Sjruoho acpicpu_debug_print_method_c(uint8_t val)
829b9f7a5acSjruoho {
830b9f7a5acSjruoho
831cc543157Sjruoho if (val == ACPICPU_C_STATE_FFH)
832b9f7a5acSjruoho return "FFH";
833b9f7a5acSjruoho
834cc543157Sjruoho if (val == ACPICPU_C_STATE_HALT)
835cc543157Sjruoho return "HLT";
836cc543157Sjruoho
837cc543157Sjruoho if (val == ACPICPU_C_STATE_SYSIO)
838b9f7a5acSjruoho return "I/O";
839b9f7a5acSjruoho
840804fdee3Sjruoho return "???";
841804fdee3Sjruoho }
842804fdee3Sjruoho
843804fdee3Sjruoho static const char *
acpicpu_debug_print_method_pt(uint8_t val)844804fdee3Sjruoho acpicpu_debug_print_method_pt(uint8_t val)
845804fdee3Sjruoho {
846*30d28f20Sjmcneill if (val == ACPI_ADR_SPACE_SYSTEM_MEMORY)
847*30d28f20Sjmcneill return "MMIO";
848804fdee3Sjruoho
849cc543157Sjruoho if (val == ACPI_ADR_SPACE_SYSTEM_IO)
850cc543157Sjruoho return "I/O";
851cc543157Sjruoho
852cc543157Sjruoho if (val == ACPI_ADR_SPACE_FIXED_HARDWARE)
853cc543157Sjruoho return "FFH";
854cc543157Sjruoho
855b9f7a5acSjruoho return "???";
856b9f7a5acSjruoho }
857b9f7a5acSjruoho
858b9f7a5acSjruoho static const char *
acpicpu_debug_print_dep(uint32_t val)859a080ec14Sjruoho acpicpu_debug_print_dep(uint32_t val)
860a080ec14Sjruoho {
861a080ec14Sjruoho
862a080ec14Sjruoho switch (val) {
863a080ec14Sjruoho
864a080ec14Sjruoho case ACPICPU_DEP_SW_ALL:
865a080ec14Sjruoho return "SW_ALL";
866a080ec14Sjruoho
867a080ec14Sjruoho case ACPICPU_DEP_SW_ANY:
868a080ec14Sjruoho return "SW_ANY";
869a080ec14Sjruoho
870a080ec14Sjruoho case ACPICPU_DEP_HW_ALL:
871a080ec14Sjruoho return "HW_ALL";
872a080ec14Sjruoho
873a080ec14Sjruoho default:
874a080ec14Sjruoho return "unknown";
875a080ec14Sjruoho }
876a080ec14Sjruoho }
877a080ec14Sjruoho
8784d861e5bSjruoho MODULE(MODULE_CLASS_DRIVER, acpicpu, NULL);
8794d861e5bSjruoho
8802b0b13f2Sjruoho #ifdef _MODULE
8812b0b13f2Sjruoho #include "ioconf.c"
8822b0b13f2Sjruoho #endif
8834d861e5bSjruoho
8844d861e5bSjruoho static int
acpicpu_modcmd(modcmd_t cmd,void * aux)8852b0b13f2Sjruoho acpicpu_modcmd(modcmd_t cmd, void *aux)
8864d861e5bSjruoho {
8872b0b13f2Sjruoho int rv = 0;
8884d861e5bSjruoho
8894d861e5bSjruoho switch (cmd) {
8904d861e5bSjruoho
8914d861e5bSjruoho case MODULE_CMD_INIT:
8924d861e5bSjruoho
8932b0b13f2Sjruoho #ifdef _MODULE
8942b0b13f2Sjruoho rv = config_init_component(cfdriver_ioconf_acpicpu,
8952b0b13f2Sjruoho cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu);
8962b0b13f2Sjruoho #endif
8972b0b13f2Sjruoho break;
8984d861e5bSjruoho
8994d861e5bSjruoho case MODULE_CMD_FINI:
9004d861e5bSjruoho
9012b0b13f2Sjruoho #ifdef _MODULE
9022b0b13f2Sjruoho rv = config_fini_component(cfdriver_ioconf_acpicpu,
9032b0b13f2Sjruoho cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu);
9042b0b13f2Sjruoho #endif
9052b0b13f2Sjruoho break;
9064d861e5bSjruoho
9074d861e5bSjruoho default:
9082b0b13f2Sjruoho rv = ENOTTY;
9094d861e5bSjruoho }
9104d861e5bSjruoho
9112b0b13f2Sjruoho return rv;
9122b0b13f2Sjruoho }
913