1*e9607ed6Sthorpej /* $NetBSD: apple_smc_acpi.c,v 1.5 2021/01/29 15:49:55 thorpej Exp $ */
2681af2a9Sriastradh
3681af2a9Sriastradh /*
4681af2a9Sriastradh * Apple System Management Controller: ACPI Attachment
5681af2a9Sriastradh */
6681af2a9Sriastradh
7681af2a9Sriastradh /*-
8b9d5e7eaSriastradh * Copyright (c) 2013 The NetBSD Foundation, Inc.
9681af2a9Sriastradh * All rights reserved.
10681af2a9Sriastradh *
11b9d5e7eaSriastradh * This code is derived from software contributed to The NetBSD Foundation
12b9d5e7eaSriastradh * by Taylor R. Campbell.
13b9d5e7eaSriastradh *
14681af2a9Sriastradh * Redistribution and use in source and binary forms, with or without
15681af2a9Sriastradh * modification, are permitted provided that the following conditions
16681af2a9Sriastradh * are met:
17681af2a9Sriastradh * 1. Redistributions of source code must retain the above copyright
18681af2a9Sriastradh * notice, this list of conditions and the following disclaimer.
19681af2a9Sriastradh * 2. Redistributions in binary form must reproduce the above copyright
20681af2a9Sriastradh * notice, this list of conditions and the following disclaimer in the
21681af2a9Sriastradh * documentation and/or other materials provided with the distribution.
22681af2a9Sriastradh *
23b9d5e7eaSriastradh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24b9d5e7eaSriastradh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25b9d5e7eaSriastradh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26b9d5e7eaSriastradh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27b9d5e7eaSriastradh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28b9d5e7eaSriastradh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29b9d5e7eaSriastradh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30b9d5e7eaSriastradh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31b9d5e7eaSriastradh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32b9d5e7eaSriastradh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33b9d5e7eaSriastradh * POSSIBILITY OF SUCH DAMAGE.
34681af2a9Sriastradh */
35681af2a9Sriastradh
36681af2a9Sriastradh #include <sys/cdefs.h>
37*e9607ed6Sthorpej __KERNEL_RCSID(0, "$NetBSD: apple_smc_acpi.c,v 1.5 2021/01/29 15:49:55 thorpej Exp $");
38681af2a9Sriastradh
39681af2a9Sriastradh #include <sys/types.h>
40681af2a9Sriastradh #include <sys/param.h>
412a6583a2Sriastradh #include <sys/bus.h>
422a6583a2Sriastradh #include <sys/module.h>
43681af2a9Sriastradh
44681af2a9Sriastradh #include <dev/acpi/acpireg.h>
45681af2a9Sriastradh #include <dev/acpi/acpivar.h>
46681af2a9Sriastradh
47681af2a9Sriastradh #include <dev/ic/apple_smcreg.h>
48681af2a9Sriastradh #include <dev/ic/apple_smcvar.h>
49681af2a9Sriastradh
50681af2a9Sriastradh #define _COMPONENT ACPI_RESOURCE_COMPONENT
51681af2a9Sriastradh ACPI_MODULE_NAME ("apple_smc_acpi")
52681af2a9Sriastradh
53681af2a9Sriastradh struct apple_smc_acpi_softc {
54681af2a9Sriastradh struct apple_smc_tag sc_smc;
55681af2a9Sriastradh };
56681af2a9Sriastradh
57681af2a9Sriastradh static int apple_smc_acpi_match(device_t, cfdata_t, void *);
58681af2a9Sriastradh static void apple_smc_acpi_attach(device_t, device_t, void *);
59681af2a9Sriastradh static int apple_smc_acpi_detach(device_t, int);
602a6583a2Sriastradh static int apple_smc_acpi_rescan(device_t, const char *, const int *);
612a6583a2Sriastradh static void apple_smc_acpi_child_detached(device_t, device_t);
622a6583a2Sriastradh
632a6583a2Sriastradh CFATTACH_DECL2_NEW(apple_smc_acpi, sizeof(struct apple_smc_acpi_softc),
642a6583a2Sriastradh apple_smc_acpi_match,
652a6583a2Sriastradh apple_smc_acpi_attach,
662a6583a2Sriastradh apple_smc_acpi_detach,
672a6583a2Sriastradh NULL /* activate */,
682a6583a2Sriastradh apple_smc_acpi_rescan,
692a6583a2Sriastradh apple_smc_acpi_child_detached);
70681af2a9Sriastradh
71*e9607ed6Sthorpej static const struct device_compatible_entry compat_data[] = {
72*e9607ed6Sthorpej { .compat = "APP0001" },
73*e9607ed6Sthorpej DEVICE_COMPAT_EOL
74681af2a9Sriastradh };
75681af2a9Sriastradh
76681af2a9Sriastradh static int
apple_smc_acpi_match(device_t parent,cfdata_t match,void * aux)77681af2a9Sriastradh apple_smc_acpi_match(device_t parent, cfdata_t match, void *aux)
78681af2a9Sriastradh {
79681af2a9Sriastradh struct acpi_attach_args *aa = aux;
80681af2a9Sriastradh
81*e9607ed6Sthorpej return acpi_compatible_match(aa, compat_data);
82681af2a9Sriastradh }
83681af2a9Sriastradh
84681af2a9Sriastradh static void
apple_smc_acpi_attach(device_t parent,device_t self,void * aux)85681af2a9Sriastradh apple_smc_acpi_attach(device_t parent, device_t self, void *aux)
86681af2a9Sriastradh {
87681af2a9Sriastradh struct apple_smc_acpi_softc *sc = device_private(self);
88681af2a9Sriastradh struct apple_smc_tag *smc = &sc->sc_smc;
89681af2a9Sriastradh struct acpi_attach_args *aa = aux;
90681af2a9Sriastradh struct acpi_resources res;
91681af2a9Sriastradh struct acpi_io *io;
92681af2a9Sriastradh int rv;
93681af2a9Sriastradh
94681af2a9Sriastradh smc->smc_dev = self;
95681af2a9Sriastradh
96681af2a9Sriastradh aprint_normal("\n");
97681af2a9Sriastradh aprint_naive("\n");
98681af2a9Sriastradh
99681af2a9Sriastradh rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
100681af2a9Sriastradh &res, &acpi_resource_parse_ops_default);
101681af2a9Sriastradh if (ACPI_FAILURE(rv)) {
102681af2a9Sriastradh aprint_error_dev(self, "couldn't parse SMC resources: %s\n",
103681af2a9Sriastradh AcpiFormatException(rv));
104681af2a9Sriastradh goto out0;
105681af2a9Sriastradh }
106681af2a9Sriastradh
107681af2a9Sriastradh io = acpi_res_io(&res, 0);
108681af2a9Sriastradh if (io == NULL) {
109681af2a9Sriastradh aprint_error_dev(self, "no I/O resource\n");
110681af2a9Sriastradh goto out1;
111681af2a9Sriastradh }
112681af2a9Sriastradh
113681af2a9Sriastradh if (io->ar_length < APPLE_SMC_REGSIZE) {
114681af2a9Sriastradh aprint_error_dev(self, "I/O resources too small: %"PRId32"\n",
115681af2a9Sriastradh io->ar_length);
116681af2a9Sriastradh goto out1;
117681af2a9Sriastradh }
118681af2a9Sriastradh
119681af2a9Sriastradh if (bus_space_map(aa->aa_iot, io->ar_base, io->ar_length, 0,
120681af2a9Sriastradh &smc->smc_bsh) != 0) {
121681af2a9Sriastradh aprint_error_dev(self, "unable to map I/O registers\n");
122681af2a9Sriastradh goto out1;
123681af2a9Sriastradh }
124681af2a9Sriastradh
125681af2a9Sriastradh smc->smc_bst = aa->aa_iot;
126681af2a9Sriastradh smc->smc_size = io->ar_length;
127681af2a9Sriastradh
128681af2a9Sriastradh apple_smc_attach(smc);
129681af2a9Sriastradh
130681af2a9Sriastradh out1: acpi_resource_cleanup(&res);
131681af2a9Sriastradh out0: return;
132681af2a9Sriastradh }
133681af2a9Sriastradh
134681af2a9Sriastradh static int
apple_smc_acpi_detach(device_t self,int flags)135681af2a9Sriastradh apple_smc_acpi_detach(device_t self, int flags)
136681af2a9Sriastradh {
137681af2a9Sriastradh struct apple_smc_acpi_softc *sc = device_private(self);
138681af2a9Sriastradh struct apple_smc_tag *smc = &sc->sc_smc;
139681af2a9Sriastradh int error;
140681af2a9Sriastradh
141681af2a9Sriastradh if (smc->smc_size != 0) {
142681af2a9Sriastradh error = apple_smc_detach(smc, flags);
143681af2a9Sriastradh if (error)
144681af2a9Sriastradh return error;
145681af2a9Sriastradh
146681af2a9Sriastradh bus_space_unmap(smc->smc_bst, smc->smc_bsh, smc->smc_size);
147681af2a9Sriastradh smc->smc_size = 0;
148681af2a9Sriastradh }
149681af2a9Sriastradh
150681af2a9Sriastradh return 0;
151681af2a9Sriastradh }
1522a6583a2Sriastradh
1532a6583a2Sriastradh static int
apple_smc_acpi_rescan(device_t self,const char * ifattr,const int * locs)1542a6583a2Sriastradh apple_smc_acpi_rescan(device_t self, const char *ifattr, const int *locs)
1552a6583a2Sriastradh {
1562a6583a2Sriastradh struct apple_smc_acpi_softc *const sc = device_private(self);
1572a6583a2Sriastradh
1582a6583a2Sriastradh return apple_smc_rescan(&sc->sc_smc, ifattr, locs);
1592a6583a2Sriastradh }
1602a6583a2Sriastradh
1612a6583a2Sriastradh static void
apple_smc_acpi_child_detached(device_t self,device_t child)1622a6583a2Sriastradh apple_smc_acpi_child_detached(device_t self, device_t child)
1632a6583a2Sriastradh {
1642a6583a2Sriastradh struct apple_smc_acpi_softc *const sc = device_private(self);
1652a6583a2Sriastradh
1662a6583a2Sriastradh apple_smc_child_detached(&sc->sc_smc, child);
1672a6583a2Sriastradh }
1682a6583a2Sriastradh
1692a6583a2Sriastradh MODULE(MODULE_CLASS_DRIVER, apple_smc_acpi, "apple_smc");
1702a6583a2Sriastradh
1712a6583a2Sriastradh #ifdef _MODULE
1722a6583a2Sriastradh #include "ioconf.c"
1732a6583a2Sriastradh #endif
1742a6583a2Sriastradh
1752a6583a2Sriastradh static int
apple_smc_acpi_modcmd(modcmd_t cmd,void * arg __unused)1762a6583a2Sriastradh apple_smc_acpi_modcmd(modcmd_t cmd, void *arg __unused)
1772a6583a2Sriastradh {
178983bdf6dSriastradh #ifdef _MODULE
1792a6583a2Sriastradh int error;
180983bdf6dSriastradh #endif
1812a6583a2Sriastradh
1822a6583a2Sriastradh switch (cmd) {
1832a6583a2Sriastradh case MODULE_CMD_INIT:
1842a6583a2Sriastradh #ifdef _MODULE
1852a6583a2Sriastradh error = config_init_component(cfdriver_ioconf_apple_smc_acpi,
1862a6583a2Sriastradh cfattach_ioconf_apple_smc_acpi,
1872a6583a2Sriastradh cfdata_ioconf_apple_smc_acpi);
1882a6583a2Sriastradh if (error)
1892a6583a2Sriastradh return error;
1902a6583a2Sriastradh #endif
1912a6583a2Sriastradh return 0;
1922a6583a2Sriastradh
1932a6583a2Sriastradh case MODULE_CMD_FINI:
1942a6583a2Sriastradh #ifdef _MODULE
1952a6583a2Sriastradh error = config_fini_component(cfdriver_ioconf_apple_smc_acpi,
1962a6583a2Sriastradh cfattach_ioconf_apple_smc_acpi,
1972a6583a2Sriastradh cfdata_ioconf_apple_smc_acpi);
1982a6583a2Sriastradh if (error)
1992a6583a2Sriastradh return error;
2002a6583a2Sriastradh #endif
2012a6583a2Sriastradh return 0;
2022a6583a2Sriastradh
2032a6583a2Sriastradh default:
2042a6583a2Sriastradh return ENOTTY;
2052a6583a2Sriastradh }
2062a6583a2Sriastradh }
207