Home | History | Annotate | Line # | Download | only in acpi
acpi_cpu.c revision 1.25.4.1
      1  1.25.4.1    bouyer /* $NetBSD: acpi_cpu.c,v 1.25.4.1 2011/02/17 12:00:09 bouyer Exp $ */
      2       1.1    jruoho 
      3       1.1    jruoho /*-
      4       1.1    jruoho  * Copyright (c) 2010 Jukka Ruohonen <jruohonen (at) iki.fi>
      5       1.1    jruoho  * All rights reserved.
      6       1.1    jruoho  *
      7       1.1    jruoho  * Redistribution and use in source and binary forms, with or without
      8       1.1    jruoho  * modification, are permitted provided that the following conditions
      9       1.1    jruoho  * are met:
     10       1.1    jruoho  *
     11       1.1    jruoho  * 1. Redistributions of source code must retain the above copyright
     12       1.1    jruoho  *    notice, this list of conditions and the following disclaimer.
     13       1.1    jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     14       1.1    jruoho  *    notice, this list of conditions and the following disclaimer in the
     15       1.1    jruoho  *    documentation and/or other materials provided with the distribution.
     16       1.1    jruoho  *
     17       1.1    jruoho  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     18       1.1    jruoho  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19       1.1    jruoho  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20       1.1    jruoho  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     21       1.1    jruoho  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22       1.1    jruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23       1.1    jruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24       1.1    jruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25       1.1    jruoho  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26       1.1    jruoho  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27       1.1    jruoho  * SUCH DAMAGE.
     28       1.1    jruoho  */
     29       1.1    jruoho #include <sys/cdefs.h>
     30  1.25.4.1    bouyer __KERNEL_RCSID(0, "$NetBSD: acpi_cpu.c,v 1.25.4.1 2011/02/17 12:00:09 bouyer Exp $");
     31       1.1    jruoho 
     32       1.1    jruoho #include <sys/param.h>
     33       1.1    jruoho #include <sys/cpu.h>
     34       1.1    jruoho #include <sys/kernel.h>
     35       1.1    jruoho #include <sys/kmem.h>
     36       1.1    jruoho #include <sys/module.h>
     37      1.10    jruoho #include <sys/mutex.h>
     38       1.1    jruoho #include <sys/once.h>
     39      1.24    jruoho #include <sys/sysctl.h>
     40       1.1    jruoho 
     41       1.1    jruoho #include <dev/acpi/acpireg.h>
     42       1.1    jruoho #include <dev/acpi/acpivar.h>
     43       1.1    jruoho #include <dev/acpi/acpi_cpu.h>
     44       1.1    jruoho 
     45       1.1    jruoho #include <machine/acpi_machdep.h>
     46       1.1    jruoho 
     47       1.1    jruoho #define _COMPONENT	  ACPI_BUS_COMPONENT
     48       1.1    jruoho ACPI_MODULE_NAME	  ("acpi_cpu")
     49       1.1    jruoho 
     50       1.1    jruoho static int		  acpicpu_match(device_t, cfdata_t, void *);
     51       1.1    jruoho static void		  acpicpu_attach(device_t, device_t, void *);
     52       1.1    jruoho static int		  acpicpu_detach(device_t, int);
     53       1.1    jruoho static int		  acpicpu_once_attach(void);
     54       1.1    jruoho static int		  acpicpu_once_detach(void);
     55      1.20    jruoho static void		  acpicpu_prestart(device_t);
     56      1.17    jruoho static void		  acpicpu_start(device_t);
     57      1.24    jruoho static void		  acpicpu_sysctl(device_t);
     58       1.1    jruoho 
     59       1.1    jruoho static int		  acpicpu_object(ACPI_HANDLE, struct acpicpu_object *);
     60       1.1    jruoho static cpuid_t		  acpicpu_id(uint32_t);
     61       1.1    jruoho static uint32_t		  acpicpu_cap(struct acpicpu_softc *);
     62      1.21    jruoho static ACPI_STATUS	  acpicpu_cap_pdc(struct acpicpu_softc *, uint32_t);
     63      1.21    jruoho static ACPI_STATUS	  acpicpu_cap_osc(struct acpicpu_softc *,
     64      1.21    jruoho 					  uint32_t, uint32_t *);
     65       1.1    jruoho static void		  acpicpu_notify(ACPI_HANDLE, uint32_t, void *);
     66       1.1    jruoho static bool		  acpicpu_suspend(device_t, const pmf_qual_t *);
     67       1.1    jruoho static bool		  acpicpu_resume(device_t, const pmf_qual_t *);
     68       1.1    jruoho 
     69      1.25    jruoho extern uint32_t		  acpi_cpus;
     70       1.1    jruoho struct acpicpu_softc	**acpicpu_sc = NULL;
     71      1.24    jruoho static struct sysctllog	 *acpicpu_log = NULL;
     72      1.24    jruoho static bool		  acpicpu_dynamic = true;
     73      1.24    jruoho static bool		  acpicpu_passive = true;
     74       1.1    jruoho 
     75       1.1    jruoho static const char * const acpicpu_hid[] = {
     76       1.1    jruoho 	"ACPI0007",
     77       1.1    jruoho 	NULL
     78       1.1    jruoho };
     79       1.1    jruoho 
     80       1.1    jruoho CFATTACH_DECL_NEW(acpicpu, sizeof(struct acpicpu_softc),
     81       1.1    jruoho     acpicpu_match, acpicpu_attach, acpicpu_detach, NULL);
     82       1.1    jruoho 
     83       1.1    jruoho static int
     84       1.1    jruoho acpicpu_match(device_t parent, cfdata_t match, void *aux)
     85       1.1    jruoho {
     86       1.1    jruoho 	struct acpi_attach_args *aa = aux;
     87       1.3  christos 	struct acpicpu_object ao;
     88       1.5    jruoho 	int rv;
     89       1.1    jruoho 
     90       1.1    jruoho 	if (aa->aa_node->ad_type != ACPI_TYPE_PROCESSOR)
     91       1.1    jruoho 		return 0;
     92       1.1    jruoho 
     93       1.1    jruoho 	if (acpi_match_hid(aa->aa_node->ad_devinfo, acpicpu_hid) != 0)
     94       1.1    jruoho 		return 1;
     95       1.1    jruoho 
     96       1.5    jruoho 	rv = acpicpu_object(aa->aa_node->ad_handle, &ao);
     97       1.5    jruoho 
     98       1.5    jruoho 	if (rv != 0 || acpicpu_id(ao.ao_procid) == 0xFFFFFF)
     99       1.3  christos 		return 0;
    100       1.5    jruoho 
    101       1.3  christos 	return 1;
    102       1.1    jruoho }
    103       1.1    jruoho 
    104       1.1    jruoho static void
    105       1.1    jruoho acpicpu_attach(device_t parent, device_t self, void *aux)
    106       1.1    jruoho {
    107       1.1    jruoho 	struct acpicpu_softc *sc = device_private(self);
    108       1.1    jruoho 	struct acpi_attach_args *aa = aux;
    109       1.1    jruoho 	static ONCE_DECL(once_attach);
    110       1.1    jruoho 	int rv;
    111       1.1    jruoho 
    112       1.1    jruoho 	rv = acpicpu_object(aa->aa_node->ad_handle, &sc->sc_object);
    113       1.1    jruoho 
    114       1.5    jruoho 	if (rv != 0)
    115       1.1    jruoho 		return;
    116       1.1    jruoho 
    117       1.1    jruoho 	rv = RUN_ONCE(&once_attach, acpicpu_once_attach);
    118       1.1    jruoho 
    119       1.1    jruoho 	if (rv != 0)
    120       1.1    jruoho 		return;
    121       1.1    jruoho 
    122       1.1    jruoho 	sc->sc_dev = self;
    123      1.17    jruoho 	sc->sc_cold = true;
    124       1.1    jruoho 	sc->sc_node = aa->aa_node;
    125       1.1    jruoho 	sc->sc_cpuid = acpicpu_id(sc->sc_object.ao_procid);
    126       1.1    jruoho 
    127       1.1    jruoho 	if (sc->sc_cpuid == 0xFFFFFF) {
    128       1.1    jruoho 		aprint_error(": invalid CPU ID\n");
    129       1.1    jruoho 		return;
    130       1.1    jruoho 	}
    131       1.1    jruoho 
    132       1.1    jruoho 	if (acpicpu_sc[sc->sc_cpuid] != NULL) {
    133       1.6    jruoho 		aprint_error(": already attached\n");
    134       1.1    jruoho 		return;
    135       1.1    jruoho 	}
    136       1.1    jruoho 
    137      1.21    jruoho 	aprint_naive("\n");
    138      1.21    jruoho 	aprint_normal(": ACPI CPU\n");
    139      1.21    jruoho 
    140      1.25    jruoho 	acpi_cpus++;
    141       1.1    jruoho 	acpicpu_sc[sc->sc_cpuid] = sc;
    142       1.1    jruoho 
    143       1.1    jruoho 	sc->sc_cap = acpicpu_cap(sc);
    144       1.1    jruoho 	sc->sc_flags |= acpicpu_md_quirks();
    145       1.1    jruoho 
    146      1.10    jruoho 	mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE);
    147      1.10    jruoho 
    148       1.1    jruoho 	acpicpu_cstate_attach(self);
    149      1.12    jruoho 	acpicpu_pstate_attach(self);
    150      1.15    jruoho 	acpicpu_tstate_attach(self);
    151      1.12    jruoho 
    152      1.20    jruoho 	(void)config_defer(self, acpicpu_prestart);
    153       1.1    jruoho 	(void)acpi_register_notify(sc->sc_node, acpicpu_notify);
    154       1.1    jruoho 	(void)pmf_device_register(self, acpicpu_suspend, acpicpu_resume);
    155       1.1    jruoho }
    156       1.1    jruoho 
    157       1.1    jruoho static int
    158       1.1    jruoho acpicpu_detach(device_t self, int flags)
    159       1.1    jruoho {
    160       1.1    jruoho 	struct acpicpu_softc *sc = device_private(self);
    161       1.1    jruoho 	static ONCE_DECL(once_detach);
    162       1.1    jruoho 	int rv = 0;
    163       1.1    jruoho 
    164      1.14    jruoho 	sc->sc_cold = true;
    165       1.1    jruoho 	acpi_deregister_notify(sc->sc_node);
    166       1.1    jruoho 
    167       1.1    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
    168       1.1    jruoho 		rv = acpicpu_cstate_detach(self);
    169       1.1    jruoho 
    170       1.1    jruoho 	if (rv != 0)
    171       1.1    jruoho 		return rv;
    172       1.1    jruoho 
    173      1.12    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
    174      1.12    jruoho 		rv = acpicpu_pstate_detach(self);
    175      1.12    jruoho 
    176      1.12    jruoho 	if (rv != 0)
    177      1.12    jruoho 		return rv;
    178      1.12    jruoho 
    179      1.15    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
    180      1.15    jruoho 		rv = acpicpu_tstate_detach(self);
    181      1.15    jruoho 
    182      1.15    jruoho 	if (rv != 0)
    183      1.15    jruoho 		return rv;
    184      1.15    jruoho 
    185       1.1    jruoho 	rv = RUN_ONCE(&once_detach, acpicpu_once_detach);
    186       1.1    jruoho 
    187       1.1    jruoho 	if (rv != 0)
    188       1.1    jruoho 		return rv;
    189       1.1    jruoho 
    190      1.10    jruoho 	mutex_destroy(&sc->sc_mtx);
    191      1.25    jruoho 	acpi_cpus--;
    192      1.10    jruoho 
    193       1.1    jruoho 	return 0;
    194       1.1    jruoho }
    195       1.1    jruoho 
    196       1.1    jruoho static int
    197       1.1    jruoho acpicpu_once_attach(void)
    198       1.1    jruoho {
    199       1.1    jruoho 	struct acpicpu_softc *sc;
    200       1.1    jruoho 	unsigned int i;
    201       1.1    jruoho 
    202       1.1    jruoho 	acpicpu_sc = kmem_zalloc(maxcpus * sizeof(*sc), KM_SLEEP);
    203       1.1    jruoho 
    204       1.1    jruoho 	if (acpicpu_sc == NULL)
    205       1.1    jruoho 		return ENOMEM;
    206       1.1    jruoho 
    207       1.1    jruoho 	for (i = 0; i < maxcpus; i++)
    208       1.1    jruoho 		acpicpu_sc[i] = NULL;
    209       1.1    jruoho 
    210       1.1    jruoho 	return 0;
    211       1.1    jruoho }
    212       1.1    jruoho 
    213       1.1    jruoho static int
    214       1.1    jruoho acpicpu_once_detach(void)
    215       1.1    jruoho {
    216       1.1    jruoho 	struct acpicpu_softc *sc;
    217       1.1    jruoho 
    218      1.17    jruoho 	if (acpicpu_sc != NULL)
    219      1.17    jruoho 		kmem_free(acpicpu_sc, maxcpus * sizeof(*sc));
    220       1.1    jruoho 
    221      1.24    jruoho 	if (acpicpu_log != NULL)
    222      1.24    jruoho 		sysctl_teardown(&acpicpu_log);
    223      1.24    jruoho 
    224      1.17    jruoho 	return 0;
    225      1.17    jruoho }
    226       1.1    jruoho 
    227      1.17    jruoho static void
    228      1.20    jruoho acpicpu_prestart(device_t self)
    229      1.17    jruoho {
    230      1.17    jruoho 	struct acpicpu_softc *sc = device_private(self);
    231      1.17    jruoho 	static bool once = false;
    232      1.17    jruoho 
    233      1.17    jruoho 	if (once != false) {
    234      1.17    jruoho 		sc->sc_cold = false;
    235      1.17    jruoho 		return;
    236      1.17    jruoho 	}
    237      1.17    jruoho 
    238      1.20    jruoho 	once = true;
    239      1.20    jruoho 
    240      1.20    jruoho 	(void)config_interrupts(self, acpicpu_start);
    241      1.20    jruoho }
    242      1.20    jruoho 
    243      1.20    jruoho static void
    244      1.20    jruoho acpicpu_start(device_t self)
    245      1.20    jruoho {
    246      1.20    jruoho 	struct acpicpu_softc *sc = device_private(self);
    247      1.20    jruoho 
    248      1.17    jruoho 	/*
    249      1.17    jruoho 	 * Run the state-specific initialization
    250      1.17    jruoho 	 * routines. These should be called only
    251      1.20    jruoho 	 * once, after interrupts are enabled and
    252      1.20    jruoho 	 * all ACPI CPUs have attached.
    253      1.17    jruoho 	 */
    254      1.17    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
    255      1.17    jruoho 		acpicpu_cstate_start(self);
    256      1.17    jruoho 
    257      1.17    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
    258      1.17    jruoho 		acpicpu_pstate_start(self);
    259      1.17    jruoho 
    260      1.17    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
    261      1.17    jruoho 		acpicpu_tstate_start(self);
    262      1.17    jruoho 
    263      1.24    jruoho 	acpicpu_sysctl(self);
    264      1.24    jruoho 
    265      1.17    jruoho 	aprint_debug_dev(sc->sc_dev, "ACPI CPUs started (cap "
    266      1.17    jruoho 	    "0x%02x, flags 0x%06x)\n", sc->sc_cap, sc->sc_flags);
    267      1.17    jruoho 
    268      1.17    jruoho 	sc->sc_cold = false;
    269       1.1    jruoho }
    270       1.1    jruoho 
    271      1.24    jruoho static void
    272      1.24    jruoho acpicpu_sysctl(device_t self)
    273      1.24    jruoho {
    274      1.24    jruoho 	const struct sysctlnode *node;
    275      1.24    jruoho 	int err;
    276      1.24    jruoho 
    277      1.24    jruoho 	err = sysctl_createv(&acpicpu_log, 0, NULL, &node,
    278      1.24    jruoho 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
    279      1.24    jruoho 	    NULL, 0, NULL, 0, CTL_HW, CTL_EOL);
    280      1.24    jruoho 
    281      1.24    jruoho 	if (err != 0)
    282      1.24    jruoho 		goto fail;
    283      1.24    jruoho 
    284      1.24    jruoho 	err = sysctl_createv(&acpicpu_log, 0, &node, &node,
    285      1.24    jruoho 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "acpi", NULL,
    286      1.24    jruoho 	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
    287      1.24    jruoho 
    288      1.24    jruoho 	if (err != 0)
    289      1.24    jruoho 		goto fail;
    290      1.24    jruoho 
    291      1.24    jruoho 	err = sysctl_createv(&acpicpu_log, 0, &node, &node,
    292      1.24    jruoho 	    0, CTLTYPE_NODE, "cpu", SYSCTL_DESCR("ACPI CPU"),
    293      1.24    jruoho 	    NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
    294      1.24    jruoho 
    295      1.24    jruoho 	if (err != 0)
    296      1.24    jruoho 		goto fail;
    297      1.24    jruoho 
    298      1.24    jruoho 	err = sysctl_createv(&acpicpu_log, 0, &node, NULL,
    299      1.24    jruoho 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "dynamic",
    300      1.24    jruoho 	    SYSCTL_DESCR("Dynamic states"), NULL, 0,
    301      1.24    jruoho 	    &acpicpu_dynamic, 0, CTL_CREATE, CTL_EOL);
    302      1.24    jruoho 
    303      1.24    jruoho 	if (err != 0)
    304      1.24    jruoho 		goto fail;
    305      1.24    jruoho 
    306      1.24    jruoho 	err = sysctl_createv(&acpicpu_log, 0, &node, NULL,
    307      1.24    jruoho 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "passive",
    308      1.24    jruoho 	    SYSCTL_DESCR("Passive cooling"), NULL, 0,
    309      1.24    jruoho 	    &acpicpu_passive, 0, CTL_CREATE, CTL_EOL);
    310      1.24    jruoho 
    311      1.24    jruoho 	if (err != 0)
    312      1.24    jruoho 		goto fail;
    313      1.24    jruoho 
    314      1.24    jruoho 	return;
    315      1.24    jruoho 
    316      1.24    jruoho fail:
    317      1.24    jruoho 	aprint_error_dev(self, "failed to initialize sysctl (err %d)\n", err);
    318      1.24    jruoho }
    319      1.24    jruoho 
    320       1.1    jruoho static int
    321       1.1    jruoho acpicpu_object(ACPI_HANDLE hdl, struct acpicpu_object *ao)
    322       1.1    jruoho {
    323       1.1    jruoho 	ACPI_OBJECT *obj;
    324       1.1    jruoho 	ACPI_BUFFER buf;
    325       1.1    jruoho 	ACPI_STATUS rv;
    326       1.1    jruoho 
    327       1.1    jruoho 	rv = acpi_eval_struct(hdl, NULL, &buf);
    328       1.1    jruoho 
    329       1.1    jruoho 	if (ACPI_FAILURE(rv))
    330       1.8    jruoho 		return 1;
    331       1.1    jruoho 
    332       1.1    jruoho 	obj = buf.Pointer;
    333       1.1    jruoho 
    334       1.1    jruoho 	if (obj->Type != ACPI_TYPE_PROCESSOR) {
    335       1.1    jruoho 		rv = AE_TYPE;
    336       1.1    jruoho 		goto out;
    337       1.1    jruoho 	}
    338       1.1    jruoho 
    339       1.1    jruoho 	if (obj->Processor.ProcId > (uint32_t)maxcpus) {
    340       1.1    jruoho 		rv = AE_LIMIT;
    341       1.1    jruoho 		goto out;
    342       1.1    jruoho 	}
    343       1.1    jruoho 
    344       1.1    jruoho 	KDASSERT((uint64_t)obj->Processor.PblkAddress < UINT32_MAX);
    345       1.1    jruoho 
    346       1.1    jruoho 	if (ao != NULL) {
    347       1.1    jruoho 		ao->ao_procid = obj->Processor.ProcId;
    348       1.1    jruoho 		ao->ao_pblklen = obj->Processor.PblkLength;
    349       1.1    jruoho 		ao->ao_pblkaddr = obj->Processor.PblkAddress;
    350       1.1    jruoho 	}
    351       1.1    jruoho 
    352       1.1    jruoho out:
    353       1.1    jruoho 	if (buf.Pointer != NULL)
    354       1.1    jruoho 		ACPI_FREE(buf.Pointer);
    355       1.1    jruoho 
    356       1.5    jruoho 	return ACPI_FAILURE(rv) ? 1 : 0;
    357       1.1    jruoho }
    358       1.1    jruoho 
    359       1.1    jruoho static cpuid_t
    360       1.1    jruoho acpicpu_id(uint32_t id)
    361       1.1    jruoho {
    362       1.1    jruoho 	CPU_INFO_ITERATOR cii;
    363       1.1    jruoho 	struct cpu_info *ci;
    364       1.1    jruoho 
    365       1.1    jruoho 	for (CPU_INFO_FOREACH(cii, ci)) {
    366       1.5    jruoho 
    367      1.11    jruoho 		if (id == ci->ci_acpiid)
    368       1.4    cegger 			return id;
    369       1.1    jruoho 	}
    370       1.1    jruoho 
    371       1.1    jruoho 	return 0xFFFFFF;
    372       1.1    jruoho }
    373       1.1    jruoho 
    374       1.1    jruoho static uint32_t
    375       1.1    jruoho acpicpu_cap(struct acpicpu_softc *sc)
    376       1.1    jruoho {
    377      1.21    jruoho 	uint32_t flags, cap = 0;
    378      1.21    jruoho 	const char *str;
    379       1.1    jruoho 	ACPI_STATUS rv;
    380       1.1    jruoho 
    381       1.1    jruoho 	/*
    382      1.21    jruoho 	 * Query and set machine-dependent capabilities.
    383      1.21    jruoho 	 * Note that the Intel-specific _PDC method was
    384      1.21    jruoho 	 * deprecated in the ACPI 3.0 in favor of _OSC.
    385       1.1    jruoho 	 */
    386      1.21    jruoho 	flags = acpicpu_md_cap();
    387      1.21    jruoho 	rv = acpicpu_cap_osc(sc, flags, &cap);
    388       1.1    jruoho 
    389      1.21    jruoho 	if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
    390      1.21    jruoho 		str = "_OSC";
    391      1.21    jruoho 		goto fail;
    392      1.21    jruoho 	}
    393       1.1    jruoho 
    394      1.21    jruoho 	rv = acpicpu_cap_pdc(sc, flags);
    395       1.1    jruoho 
    396      1.21    jruoho 	if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND) {
    397      1.21    jruoho 		str = "_PDC";
    398      1.21    jruoho 		goto fail;
    399      1.21    jruoho 	}
    400       1.1    jruoho 
    401      1.21    jruoho 	if (cap == 0)
    402      1.21    jruoho 		cap = flags;
    403       1.1    jruoho 
    404      1.21    jruoho 	return cap;
    405       1.1    jruoho 
    406      1.21    jruoho fail:
    407      1.21    jruoho 	aprint_error_dev(sc->sc_dev, "failed to evaluate "
    408      1.21    jruoho 	    "%s: %s\n", str, AcpiFormatException(rv));
    409       1.1    jruoho 
    410      1.21    jruoho 	return 0;
    411       1.1    jruoho }
    412       1.1    jruoho 
    413      1.21    jruoho static ACPI_STATUS
    414      1.21    jruoho acpicpu_cap_pdc(struct acpicpu_softc *sc, uint32_t flags)
    415       1.1    jruoho {
    416      1.21    jruoho 	ACPI_OBJECT_LIST arg;
    417      1.21    jruoho 	ACPI_OBJECT obj;
    418      1.21    jruoho 	uint32_t cap[3];
    419      1.21    jruoho 
    420      1.21    jruoho 	arg.Count = 1;
    421      1.21    jruoho 	arg.Pointer = &obj;
    422       1.1    jruoho 
    423       1.1    jruoho 	cap[0] = ACPICPU_PDC_REVID;
    424       1.1    jruoho 	cap[1] = 1;
    425      1.21    jruoho 	cap[2] = flags;
    426       1.1    jruoho 
    427       1.1    jruoho 	obj.Type = ACPI_TYPE_BUFFER;
    428       1.1    jruoho 	obj.Buffer.Length = sizeof(cap);
    429      1.21    jruoho 	obj.Buffer.Pointer = (void *)cap;
    430       1.1    jruoho 
    431      1.21    jruoho 	return AcpiEvaluateObject(sc->sc_node->ad_handle, "_PDC", &arg, NULL);
    432       1.1    jruoho }
    433       1.1    jruoho 
    434       1.1    jruoho static ACPI_STATUS
    435      1.21    jruoho acpicpu_cap_osc(struct acpicpu_softc *sc, uint32_t flags, uint32_t *val)
    436       1.1    jruoho {
    437      1.21    jruoho 	ACPI_OBJECT_LIST arg;
    438      1.21    jruoho 	ACPI_OBJECT obj[4];
    439      1.21    jruoho 	ACPI_OBJECT *osc;
    440       1.1    jruoho 	ACPI_BUFFER buf;
    441       1.1    jruoho 	ACPI_STATUS rv;
    442      1.21    jruoho 	uint32_t cap[2];
    443      1.21    jruoho 	uint32_t *ptr;
    444      1.21    jruoho 	int i = 5;
    445       1.1    jruoho 
    446      1.21    jruoho 	static uint8_t intel_uuid[16] = {
    447       1.1    jruoho 		0x16, 0xA6, 0x77, 0x40, 0x0C, 0x29, 0xBE, 0x47,
    448       1.1    jruoho 		0x9E, 0xBD, 0xD8, 0x70, 0x58, 0x71, 0x39, 0x53
    449       1.1    jruoho 	};
    450       1.1    jruoho 
    451      1.21    jruoho 	cap[0] = ACPI_OSC_QUERY;
    452      1.21    jruoho 	cap[1] = flags;
    453       1.1    jruoho 
    454      1.21    jruoho again:
    455      1.21    jruoho 	arg.Count = 4;
    456      1.21    jruoho 	arg.Pointer = obj;
    457      1.21    jruoho 
    458      1.21    jruoho 	obj[0].Type = ACPI_TYPE_BUFFER;
    459      1.21    jruoho 	obj[0].Buffer.Length = sizeof(intel_uuid);
    460      1.21    jruoho 	obj[0].Buffer.Pointer = intel_uuid;
    461      1.21    jruoho 
    462      1.21    jruoho 	obj[1].Type = ACPI_TYPE_INTEGER;
    463      1.21    jruoho 	obj[1].Integer.Value = ACPICPU_PDC_REVID;
    464      1.21    jruoho 
    465      1.21    jruoho 	obj[2].Type = ACPI_TYPE_INTEGER;
    466      1.21    jruoho 	obj[2].Integer.Value = __arraycount(cap);
    467      1.21    jruoho 
    468      1.21    jruoho 	obj[3].Type = ACPI_TYPE_BUFFER;
    469      1.21    jruoho 	obj[3].Buffer.Length = sizeof(cap);
    470      1.21    jruoho 	obj[3].Buffer.Pointer = (void *)cap;
    471       1.1    jruoho 
    472       1.1    jruoho 	buf.Pointer = NULL;
    473       1.1    jruoho 	buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    474       1.1    jruoho 
    475      1.21    jruoho 	rv = AcpiEvaluateObject(sc->sc_node->ad_handle, "_OSC", &arg, &buf);
    476       1.1    jruoho 
    477       1.1    jruoho 	if (ACPI_FAILURE(rv))
    478      1.21    jruoho 		goto out;
    479       1.1    jruoho 
    480      1.21    jruoho 	osc = buf.Pointer;
    481       1.1    jruoho 
    482      1.21    jruoho 	if (osc->Type != ACPI_TYPE_BUFFER) {
    483       1.1    jruoho 		rv = AE_TYPE;
    484       1.1    jruoho 		goto out;
    485       1.1    jruoho 	}
    486       1.1    jruoho 
    487      1.21    jruoho 	if (osc->Buffer.Length != sizeof(cap)) {
    488       1.1    jruoho 		rv = AE_BUFFER_OVERFLOW;
    489       1.1    jruoho 		goto out;
    490       1.1    jruoho 	}
    491       1.1    jruoho 
    492      1.21    jruoho 	ptr = (uint32_t *)osc->Buffer.Pointer;
    493      1.21    jruoho 
    494      1.21    jruoho 	if ((ptr[0] & ACPI_OSC_ERROR) != 0) {
    495      1.21    jruoho 		rv = AE_ERROR;
    496      1.21    jruoho 		goto out;
    497      1.21    jruoho 	}
    498      1.21    jruoho 
    499      1.21    jruoho 	if ((ptr[0] & (ACPI_OSC_ERROR_REV | ACPI_OSC_ERROR_UUID)) != 0) {
    500      1.21    jruoho 		rv = AE_BAD_PARAMETER;
    501      1.21    jruoho 		goto out;
    502      1.21    jruoho 	}
    503      1.21    jruoho 
    504      1.21    jruoho 	/*
    505      1.21    jruoho 	 * "It is strongly recommended that the OS evaluate
    506      1.21    jruoho 	 *  _OSC with the Query Support Flag set until _OSC
    507      1.21    jruoho 	 *  returns the Capabilities Masked bit clear, to
    508      1.21    jruoho 	 *  negotiate the set of features to be granted to
    509      1.21    jruoho 	 *  the OS for native support (ACPI 4.0, 6.2.10)."
    510      1.21    jruoho 	 */
    511      1.21    jruoho 	if ((ptr[0] & ACPI_OSC_ERROR_MASKED) != 0 && i >= 0) {
    512       1.1    jruoho 
    513       1.1    jruoho 		ACPI_FREE(buf.Pointer);
    514      1.21    jruoho 		i--;
    515       1.1    jruoho 
    516      1.21    jruoho 		goto again;
    517      1.21    jruoho 	}
    518       1.1    jruoho 
    519      1.21    jruoho 	if ((cap[0] & ACPI_OSC_QUERY) != 0) {
    520       1.1    jruoho 
    521      1.21    jruoho 		ACPI_FREE(buf.Pointer);
    522      1.21    jruoho 		cap[0] &= ~ACPI_OSC_QUERY;
    523       1.1    jruoho 
    524      1.21    jruoho 		goto again;
    525      1.21    jruoho 	}
    526       1.1    jruoho 
    527      1.21    jruoho 	/*
    528      1.21    jruoho 	 * It is permitted for _OSC to return all
    529      1.21    jruoho 	 * bits cleared, but this is specified to
    530      1.21    jruoho 	 * vary on per-device basis. Assume that
    531      1.21    jruoho 	 * everything rather than nothing will be
    532      1.23    jruoho 	 * supported in this case; we do not need
    533      1.21    jruoho 	 * the firmware to know the CPU features.
    534      1.21    jruoho 	 */
    535      1.21    jruoho 	*val = (ptr[1] != 0) ? ptr[1] : cap[1];
    536       1.1    jruoho 
    537      1.21    jruoho out:
    538      1.21    jruoho 	if (buf.Pointer != NULL)
    539      1.21    jruoho 		ACPI_FREE(buf.Pointer);
    540       1.1    jruoho 
    541      1.21    jruoho 	return rv;
    542       1.1    jruoho }
    543       1.1    jruoho 
    544       1.1    jruoho static void
    545       1.1    jruoho acpicpu_notify(ACPI_HANDLE hdl, uint32_t evt, void *aux)
    546       1.1    jruoho {
    547       1.1    jruoho 	ACPI_OSD_EXEC_CALLBACK func;
    548       1.1    jruoho 	struct acpicpu_softc *sc;
    549       1.1    jruoho 	device_t self = aux;
    550       1.1    jruoho 
    551       1.1    jruoho 	sc = device_private(self);
    552       1.1    jruoho 
    553      1.16    jruoho 	if (sc->sc_cold != false)
    554      1.16    jruoho 		return;
    555      1.16    jruoho 
    556      1.24    jruoho 	if (acpicpu_dynamic != true)
    557      1.24    jruoho 		return;
    558      1.24    jruoho 
    559       1.1    jruoho 	switch (evt) {
    560       1.1    jruoho 
    561       1.1    jruoho 	case ACPICPU_C_NOTIFY:
    562       1.1    jruoho 
    563       1.1    jruoho 		if ((sc->sc_flags & ACPICPU_FLAG_C) == 0)
    564       1.1    jruoho 			return;
    565       1.1    jruoho 
    566       1.1    jruoho 		func = acpicpu_cstate_callback;
    567       1.1    jruoho 		break;
    568       1.1    jruoho 
    569       1.1    jruoho 	case ACPICPU_P_NOTIFY:
    570       1.1    jruoho 
    571       1.1    jruoho 		if ((sc->sc_flags & ACPICPU_FLAG_P) == 0)
    572       1.1    jruoho 			return;
    573       1.1    jruoho 
    574      1.12    jruoho 		func = acpicpu_pstate_callback;
    575       1.1    jruoho 		break;
    576       1.1    jruoho 
    577       1.1    jruoho 	case ACPICPU_T_NOTIFY:
    578       1.1    jruoho 
    579       1.1    jruoho 		if ((sc->sc_flags & ACPICPU_FLAG_T) == 0)
    580       1.1    jruoho 			return;
    581       1.1    jruoho 
    582      1.15    jruoho 		func = acpicpu_tstate_callback;
    583       1.1    jruoho 		break;
    584       1.1    jruoho 
    585       1.1    jruoho 	default:
    586       1.1    jruoho 		aprint_error_dev(sc->sc_dev,  "unknown notify: 0x%02X\n", evt);
    587       1.1    jruoho 		return;
    588       1.1    jruoho 	}
    589       1.1    jruoho 
    590       1.1    jruoho 	(void)AcpiOsExecute(OSL_NOTIFY_HANDLER, func, sc->sc_dev);
    591       1.1    jruoho }
    592       1.1    jruoho 
    593       1.1    jruoho static bool
    594       1.1    jruoho acpicpu_suspend(device_t self, const pmf_qual_t *qual)
    595       1.1    jruoho {
    596       1.1    jruoho 	struct acpicpu_softc *sc = device_private(self);
    597       1.1    jruoho 
    598       1.1    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
    599       1.1    jruoho 		(void)acpicpu_cstate_suspend(self);
    600       1.1    jruoho 
    601      1.12    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
    602      1.12    jruoho 		(void)acpicpu_pstate_suspend(self);
    603      1.12    jruoho 
    604      1.15    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
    605      1.15    jruoho 		(void)acpicpu_tstate_suspend(self);
    606      1.15    jruoho 
    607      1.18    jruoho 	sc->sc_cold = true;
    608      1.18    jruoho 
    609       1.1    jruoho 	return true;
    610       1.1    jruoho }
    611       1.1    jruoho 
    612       1.1    jruoho static bool
    613       1.1    jruoho acpicpu_resume(device_t self, const pmf_qual_t *qual)
    614       1.1    jruoho {
    615       1.1    jruoho 	struct acpicpu_softc *sc = device_private(self);
    616       1.1    jruoho 
    617      1.18    jruoho 	sc->sc_cold = false;
    618      1.18    jruoho 
    619       1.1    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_C) != 0)
    620       1.1    jruoho 		(void)acpicpu_cstate_resume(self);
    621       1.1    jruoho 
    622      1.12    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_P) != 0)
    623      1.12    jruoho 		(void)acpicpu_pstate_resume(self);
    624      1.12    jruoho 
    625      1.15    jruoho 	if ((sc->sc_flags & ACPICPU_FLAG_T) != 0)
    626      1.15    jruoho 		(void)acpicpu_tstate_resume(self);
    627      1.15    jruoho 
    628       1.1    jruoho 	return true;
    629       1.1    jruoho }
    630       1.1    jruoho 
    631       1.1    jruoho MODULE(MODULE_CLASS_DRIVER, acpicpu, NULL);
    632       1.1    jruoho 
    633  1.25.4.1    bouyer #ifdef _MODULE
    634  1.25.4.1    bouyer #include "ioconf.c"
    635  1.25.4.1    bouyer #endif
    636       1.1    jruoho 
    637       1.1    jruoho static int
    638  1.25.4.1    bouyer acpicpu_modcmd(modcmd_t cmd, void *aux)
    639       1.1    jruoho {
    640  1.25.4.1    bouyer 	int rv = 0;
    641       1.1    jruoho 
    642       1.1    jruoho 	switch (cmd) {
    643       1.1    jruoho 
    644       1.1    jruoho 	case MODULE_CMD_INIT:
    645       1.1    jruoho 
    646  1.25.4.1    bouyer #ifdef _MODULE
    647  1.25.4.1    bouyer 		rv = config_init_component(cfdriver_ioconf_acpicpu,
    648  1.25.4.1    bouyer 		    cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu);
    649  1.25.4.1    bouyer #endif
    650  1.25.4.1    bouyer 		break;
    651       1.1    jruoho 
    652       1.1    jruoho 	case MODULE_CMD_FINI:
    653       1.1    jruoho 
    654  1.25.4.1    bouyer #ifdef _MODULE
    655  1.25.4.1    bouyer 		rv = config_fini_component(cfdriver_ioconf_acpicpu,
    656  1.25.4.1    bouyer 		    cfattach_ioconf_acpicpu, cfdata_ioconf_acpicpu);
    657  1.25.4.1    bouyer #endif
    658  1.25.4.1    bouyer 		break;
    659       1.1    jruoho 
    660       1.1    jruoho 	default:
    661  1.25.4.1    bouyer 		rv = ENOTTY;
    662       1.1    jruoho 	}
    663       1.1    jruoho 
    664  1.25.4.1    bouyer 	return rv;
    665  1.25.4.1    bouyer }
    666