xref: /netbsd-src/sys/dev/acpi/apple_smc_acpi.c (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 /*	$NetBSD: apple_smc_acpi.c,v 1.3 2014/04/01 17:49:40 riastradh Exp $	*/
2 
3 /*
4  * Apple System Management Controller: ACPI Attachment
5  */
6 
7 /*-
8  * Copyright (c) 2013 Taylor R. Campbell
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: apple_smc_acpi.c,v 1.3 2014/04/01 17:49:40 riastradh Exp $");
35 
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/module.h>
40 
41 #include <dev/acpi/acpireg.h>
42 #include <dev/acpi/acpivar.h>
43 
44 #include <dev/ic/apple_smcreg.h>
45 #include <dev/ic/apple_smcvar.h>
46 
47 #define _COMPONENT		ACPI_RESOURCE_COMPONENT
48 ACPI_MODULE_NAME		("apple_smc_acpi")
49 
50 struct apple_smc_acpi_softc {
51 	struct apple_smc_tag	sc_smc;
52 };
53 
54 static int	apple_smc_acpi_match(device_t, cfdata_t, void *);
55 static void	apple_smc_acpi_attach(device_t, device_t, void *);
56 static int	apple_smc_acpi_detach(device_t, int);
57 static int	apple_smc_acpi_rescan(device_t, const char *, const int *);
58 static void	apple_smc_acpi_child_detached(device_t, device_t);
59 
60 CFATTACH_DECL2_NEW(apple_smc_acpi, sizeof(struct apple_smc_acpi_softc),
61     apple_smc_acpi_match,
62     apple_smc_acpi_attach,
63     apple_smc_acpi_detach,
64     NULL /* activate */,
65     apple_smc_acpi_rescan,
66     apple_smc_acpi_child_detached);
67 
68 static const char *const apple_smc_ids[] = {
69 	"APP0001",
70 	NULL
71 };
72 
73 static int
74 apple_smc_acpi_match(device_t parent, cfdata_t match, void *aux)
75 {
76 	struct acpi_attach_args *aa = aux;
77 
78 	if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
79 		return 0;
80 
81 	if (!acpi_match_hid(aa->aa_node->ad_devinfo, apple_smc_ids))
82 		return 0;
83 
84 	return 1;
85 }
86 
87 static void
88 apple_smc_acpi_attach(device_t parent, device_t self, void *aux)
89 {
90 	struct apple_smc_acpi_softc *sc = device_private(self);
91 	struct apple_smc_tag *smc = &sc->sc_smc;
92 	struct acpi_attach_args *aa = aux;
93 	struct acpi_resources res;
94 	struct acpi_io *io;
95 	int rv;
96 
97 	smc->smc_dev = self;
98 
99 	aprint_normal("\n");
100 	aprint_naive("\n");
101 
102 	rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
103 	    &res, &acpi_resource_parse_ops_default);
104 	if (ACPI_FAILURE(rv)) {
105 		aprint_error_dev(self, "couldn't parse SMC resources: %s\n",
106 		    AcpiFormatException(rv));
107 		goto out0;
108 	}
109 
110 	io = acpi_res_io(&res, 0);
111 	if (io == NULL) {
112 		aprint_error_dev(self, "no I/O resource\n");
113 		goto out1;
114 	}
115 
116 	if (io->ar_length < APPLE_SMC_REGSIZE) {
117 		aprint_error_dev(self, "I/O resources too small: %"PRId32"\n",
118 		    io->ar_length);
119 		goto out1;
120 	}
121 
122 	if (bus_space_map(aa->aa_iot, io->ar_base, io->ar_length, 0,
123 		&smc->smc_bsh) != 0) {
124 		aprint_error_dev(self, "unable to map I/O registers\n");
125 		goto out1;
126 	}
127 
128 	smc->smc_bst = aa->aa_iot;
129 	smc->smc_size = io->ar_length;
130 
131 	apple_smc_attach(smc);
132 
133 out1:	acpi_resource_cleanup(&res);
134 out0:	return;
135 }
136 
137 static int
138 apple_smc_acpi_detach(device_t self, int flags)
139 {
140 	struct apple_smc_acpi_softc *sc = device_private(self);
141 	struct apple_smc_tag *smc = &sc->sc_smc;
142 	int error;
143 
144 	if (smc->smc_size != 0) {
145 		error = apple_smc_detach(smc, flags);
146 		if (error)
147 			return error;
148 
149 		bus_space_unmap(smc->smc_bst, smc->smc_bsh, smc->smc_size);
150 		smc->smc_size = 0;
151 	}
152 
153 	return 0;
154 }
155 
156 static int
157 apple_smc_acpi_rescan(device_t self, const char *ifattr, const int *locs)
158 {
159 	struct apple_smc_acpi_softc *const sc = device_private(self);
160 
161 	return apple_smc_rescan(&sc->sc_smc, ifattr, locs);
162 }
163 
164 static void
165 apple_smc_acpi_child_detached(device_t self, device_t child)
166 {
167 	struct apple_smc_acpi_softc *const sc = device_private(self);
168 
169 	apple_smc_child_detached(&sc->sc_smc, child);
170 }
171 
172 MODULE(MODULE_CLASS_DRIVER, apple_smc_acpi, "apple_smc");
173 
174 #ifdef _MODULE
175 #include "ioconf.c"
176 #endif
177 
178 static int
179 apple_smc_acpi_modcmd(modcmd_t cmd, void *arg __unused)
180 {
181 #ifdef _MODULE
182 	int error;
183 #endif
184 
185 	switch (cmd) {
186 	case MODULE_CMD_INIT:
187 #ifdef _MODULE
188 		error = config_init_component(cfdriver_ioconf_apple_smc_acpi,
189 		    cfattach_ioconf_apple_smc_acpi,
190 		    cfdata_ioconf_apple_smc_acpi);
191 		if (error)
192 			return error;
193 #endif
194 		return 0;
195 
196 	case MODULE_CMD_FINI:
197 #ifdef _MODULE
198 		error = config_fini_component(cfdriver_ioconf_apple_smc_acpi,
199 		    cfattach_ioconf_apple_smc_acpi,
200 		    cfdata_ioconf_apple_smc_acpi);
201 		if (error)
202 			return error;
203 #endif
204 		return 0;
205 
206 	default:
207 		return ENOTTY;
208 	}
209 }
210