Deleted Added
full compact
gpiobus.c (279620) gpiobus.c (279622)
1/*-
2 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/gpio/gpiobus.c 279620 2015-03-05 01:49:58Z loos $");
28__FBSDID("$FreeBSD: head/sys/dev/gpio/gpiobus.c 279622 2015-03-05 03:11:47Z loos $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/gpio.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37
38#include <dev/gpio/gpiobusvar.h>
39
40#include "gpiobus_if.h"
41
42#undef GPIOBUS_DEBUG
43#ifdef GPIOBUS_DEBUG
44#define dprintf printf
45#else
46#define dprintf(x, arg...)
47#endif
48
49static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t);
50static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int);
51static int gpiobus_probe(device_t);
52static int gpiobus_attach(device_t);
53static int gpiobus_detach(device_t);
54static int gpiobus_suspend(device_t);
55static int gpiobus_resume(device_t);
56static void gpiobus_probe_nomatch(device_t, device_t);
57static int gpiobus_print_child(device_t, device_t);
58static int gpiobus_child_location_str(device_t, device_t, char *, size_t);
59static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t);
60static device_t gpiobus_add_child(device_t, u_int, const char *, int);
61static void gpiobus_hinted_child(device_t, const char *, int);
62
63/*
64 * GPIOBUS interface
65 */
66static int gpiobus_acquire_bus(device_t, device_t, int);
67static void gpiobus_release_bus(device_t, device_t);
68static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t);
69static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*);
70static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*);
71static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int);
72static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
73static int gpiobus_pin_toggle(device_t, device_t, uint32_t);
74
75int
76gpio_check_flags(uint32_t caps, uint32_t flags)
77{
78
79 /* Check for unwanted flags. */
80 if ((flags & caps) == 0 || (flags & caps) != flags)
81 return (EINVAL);
82 /* Cannot mix input/output together. */
83 if (flags & GPIO_PIN_INPUT && flags & GPIO_PIN_OUTPUT)
84 return (EINVAL);
85 /* Cannot mix pull-up/pull-down together. */
86 if (flags & GPIO_PIN_PULLUP && flags & GPIO_PIN_PULLDOWN)
87 return (EINVAL);
88
89 return (0);
90}
91
92static void
93gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen)
94{
95 char tmp[128];
96 int i, range_start, range_stop, need_coma;
97
98 if (devi->npins == 0)
99 return;
100
101 need_coma = 0;
102 range_start = range_stop = devi->pins[0];
103 for (i = 1; i < devi->npins; i++) {
104 if (devi->pins[i] != (range_stop + 1)) {
105 if (need_coma)
106 strlcat(buf, ",", buflen);
107 memset(tmp, 0, sizeof(tmp));
108 if (range_start != range_stop)
109 snprintf(tmp, sizeof(tmp) - 1, "%d-%d",
110 range_start, range_stop);
111 else
112 snprintf(tmp, sizeof(tmp) - 1, "%d",
113 range_start);
114 strlcat(buf, tmp, buflen);
115
116 range_start = range_stop = devi->pins[i];
117 need_coma = 1;
118 }
119 else
120 range_stop++;
121 }
122
123 if (need_coma)
124 strlcat(buf, ",", buflen);
125 memset(tmp, 0, sizeof(tmp));
126 if (range_start != range_stop)
127 snprintf(tmp, sizeof(tmp) - 1, "%d-%d",
128 range_start, range_stop);
129 else
130 snprintf(tmp, sizeof(tmp) - 1, "%d",
131 range_start);
132 strlcat(buf, tmp, buflen);
133}
134
135device_t
136gpiobus_attach_bus(device_t dev)
137{
138 device_t busdev;
139
140 busdev = device_add_child(dev, "gpiobus", -1);
141 if (busdev == NULL)
142 return (NULL);
143 if (device_add_child(dev, "gpioc", -1) == NULL) {
144 device_delete_child(dev, busdev);
145 return (NULL);
146 }
147#ifdef FDT
148 ofw_gpiobus_register_provider(dev);
149#endif
150 bus_generic_attach(dev);
151
152 return (busdev);
153}
154
155int
156gpiobus_detach_bus(device_t dev)
157{
158
159#ifdef FDT
160 ofw_gpiobus_unregister_provider(dev);
161#endif
162
163 return (bus_generic_detach(dev));
164}
165
166int
167gpiobus_init_softc(device_t dev)
168{
169 struct gpiobus_softc *sc;
170
171 sc = GPIOBUS_SOFTC(dev);
172 sc->sc_busdev = dev;
173 sc->sc_dev = device_get_parent(dev);
174 sc->sc_intr_rman.rm_type = RMAN_ARRAY;
175 sc->sc_intr_rman.rm_descr = "GPIO Interrupts";
176 if (rman_init(&sc->sc_intr_rman) != 0 ||
177 rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0)
178 panic("%s: failed to set up rman.", __func__);
179
180 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
181 return (ENXIO);
182
183 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
184
185 /* Pins = GPIO_PIN_MAX() + 1 */
186 sc->sc_npins++;
187
188 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
189 M_NOWAIT | M_ZERO);
190 if (sc->sc_pins_mapped == NULL)
191 return (ENOMEM);
192
193 /* Initialize the bus lock. */
194 GPIOBUS_LOCK_INIT(sc);
195
196 return (0);
197}
198
199int
200gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
201{
202
203 /* Allocate pins and flags memory. */
204 devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
205 M_NOWAIT | M_ZERO);
206 if (devi->pins == NULL)
207 return (ENOMEM);
208 devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
209 M_NOWAIT | M_ZERO);
210 if (devi->flags == NULL) {
211 free(devi->pins, M_DEVBUF);
212 return (ENOMEM);
213 }
214
215 return (0);
216}
217
218void
219gpiobus_free_ivars(struct gpiobus_ivar *devi)
220{
221
222 if (devi->flags) {
223 free(devi->flags, M_DEVBUF);
224 devi->flags = NULL;
225 }
226 if (devi->pins) {
227 free(devi->pins, M_DEVBUF);
228 devi->pins = NULL;
229 }
230}
231
232int
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/bus.h>
33#include <sys/gpio.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37
38#include <dev/gpio/gpiobusvar.h>
39
40#include "gpiobus_if.h"
41
42#undef GPIOBUS_DEBUG
43#ifdef GPIOBUS_DEBUG
44#define dprintf printf
45#else
46#define dprintf(x, arg...)
47#endif
48
49static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t);
50static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int);
51static int gpiobus_probe(device_t);
52static int gpiobus_attach(device_t);
53static int gpiobus_detach(device_t);
54static int gpiobus_suspend(device_t);
55static int gpiobus_resume(device_t);
56static void gpiobus_probe_nomatch(device_t, device_t);
57static int gpiobus_print_child(device_t, device_t);
58static int gpiobus_child_location_str(device_t, device_t, char *, size_t);
59static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t);
60static device_t gpiobus_add_child(device_t, u_int, const char *, int);
61static void gpiobus_hinted_child(device_t, const char *, int);
62
63/*
64 * GPIOBUS interface
65 */
66static int gpiobus_acquire_bus(device_t, device_t, int);
67static void gpiobus_release_bus(device_t, device_t);
68static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t);
69static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*);
70static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*);
71static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int);
72static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
73static int gpiobus_pin_toggle(device_t, device_t, uint32_t);
74
75int
76gpio_check_flags(uint32_t caps, uint32_t flags)
77{
78
79 /* Check for unwanted flags. */
80 if ((flags & caps) == 0 || (flags & caps) != flags)
81 return (EINVAL);
82 /* Cannot mix input/output together. */
83 if (flags & GPIO_PIN_INPUT && flags & GPIO_PIN_OUTPUT)
84 return (EINVAL);
85 /* Cannot mix pull-up/pull-down together. */
86 if (flags & GPIO_PIN_PULLUP && flags & GPIO_PIN_PULLDOWN)
87 return (EINVAL);
88
89 return (0);
90}
91
92static void
93gpiobus_print_pins(struct gpiobus_ivar *devi, char *buf, size_t buflen)
94{
95 char tmp[128];
96 int i, range_start, range_stop, need_coma;
97
98 if (devi->npins == 0)
99 return;
100
101 need_coma = 0;
102 range_start = range_stop = devi->pins[0];
103 for (i = 1; i < devi->npins; i++) {
104 if (devi->pins[i] != (range_stop + 1)) {
105 if (need_coma)
106 strlcat(buf, ",", buflen);
107 memset(tmp, 0, sizeof(tmp));
108 if (range_start != range_stop)
109 snprintf(tmp, sizeof(tmp) - 1, "%d-%d",
110 range_start, range_stop);
111 else
112 snprintf(tmp, sizeof(tmp) - 1, "%d",
113 range_start);
114 strlcat(buf, tmp, buflen);
115
116 range_start = range_stop = devi->pins[i];
117 need_coma = 1;
118 }
119 else
120 range_stop++;
121 }
122
123 if (need_coma)
124 strlcat(buf, ",", buflen);
125 memset(tmp, 0, sizeof(tmp));
126 if (range_start != range_stop)
127 snprintf(tmp, sizeof(tmp) - 1, "%d-%d",
128 range_start, range_stop);
129 else
130 snprintf(tmp, sizeof(tmp) - 1, "%d",
131 range_start);
132 strlcat(buf, tmp, buflen);
133}
134
135device_t
136gpiobus_attach_bus(device_t dev)
137{
138 device_t busdev;
139
140 busdev = device_add_child(dev, "gpiobus", -1);
141 if (busdev == NULL)
142 return (NULL);
143 if (device_add_child(dev, "gpioc", -1) == NULL) {
144 device_delete_child(dev, busdev);
145 return (NULL);
146 }
147#ifdef FDT
148 ofw_gpiobus_register_provider(dev);
149#endif
150 bus_generic_attach(dev);
151
152 return (busdev);
153}
154
155int
156gpiobus_detach_bus(device_t dev)
157{
158
159#ifdef FDT
160 ofw_gpiobus_unregister_provider(dev);
161#endif
162
163 return (bus_generic_detach(dev));
164}
165
166int
167gpiobus_init_softc(device_t dev)
168{
169 struct gpiobus_softc *sc;
170
171 sc = GPIOBUS_SOFTC(dev);
172 sc->sc_busdev = dev;
173 sc->sc_dev = device_get_parent(dev);
174 sc->sc_intr_rman.rm_type = RMAN_ARRAY;
175 sc->sc_intr_rman.rm_descr = "GPIO Interrupts";
176 if (rman_init(&sc->sc_intr_rman) != 0 ||
177 rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0)
178 panic("%s: failed to set up rman.", __func__);
179
180 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0)
181 return (ENXIO);
182
183 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins"));
184
185 /* Pins = GPIO_PIN_MAX() + 1 */
186 sc->sc_npins++;
187
188 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF,
189 M_NOWAIT | M_ZERO);
190 if (sc->sc_pins_mapped == NULL)
191 return (ENOMEM);
192
193 /* Initialize the bus lock. */
194 GPIOBUS_LOCK_INIT(sc);
195
196 return (0);
197}
198
199int
200gpiobus_alloc_ivars(struct gpiobus_ivar *devi)
201{
202
203 /* Allocate pins and flags memory. */
204 devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
205 M_NOWAIT | M_ZERO);
206 if (devi->pins == NULL)
207 return (ENOMEM);
208 devi->flags = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF,
209 M_NOWAIT | M_ZERO);
210 if (devi->flags == NULL) {
211 free(devi->pins, M_DEVBUF);
212 return (ENOMEM);
213 }
214
215 return (0);
216}
217
218void
219gpiobus_free_ivars(struct gpiobus_ivar *devi)
220{
221
222 if (devi->flags) {
223 free(devi->flags, M_DEVBUF);
224 devi->flags = NULL;
225 }
226 if (devi->pins) {
227 free(devi->pins, M_DEVBUF);
228 devi->pins = NULL;
229 }
230}
231
232int
233gpiobus_map_pin(device_t bus, device_t child, uint32_t pin)
233gpiobus_map_pin(device_t bus, uint32_t pin)
234{
235 struct gpiobus_softc *sc;
236
237 sc = device_get_softc(bus);
238 /* Consistency check. */
239 if (pin >= sc->sc_npins) {
234{
235 struct gpiobus_softc *sc;
236
237 sc = device_get_softc(bus);
238 /* Consistency check. */
239 if (pin >= sc->sc_npins) {
240 device_printf(child,
240 device_printf(bus,
241 "invalid pin %d, max: %d\n", pin, sc->sc_npins - 1);
242 return (-1);
243 }
244 /* Mark pin as mapped and give warning if it's already mapped. */
245 if (sc->sc_pins_mapped[pin]) {
241 "invalid pin %d, max: %d\n", pin, sc->sc_npins - 1);
242 return (-1);
243 }
244 /* Mark pin as mapped and give warning if it's already mapped. */
245 if (sc->sc_pins_mapped[pin]) {
246 device_printf(child,
247 "warning: pin %d is already mapped\n", pin);
246 device_printf(bus, "warning: pin %d is already mapped\n", pin);
248 return (-1);
249 }
250 sc->sc_pins_mapped[pin] = 1;
251
252 return (0);
253}
254
255static int
256gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
257{
258 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
259 int i, npins;
260
261 npins = 0;
262 for (i = 0; i < 32; i++) {
263 if (mask & (1 << i))
264 npins++;
265 }
266 if (npins == 0) {
267 device_printf(child, "empty pin mask\n");
268 return (EINVAL);
269 }
270 devi->npins = npins;
271 if (gpiobus_alloc_ivars(devi) != 0) {
272 device_printf(child, "cannot allocate device ivars\n");
273 return (EINVAL);
274 }
275 npins = 0;
276 for (i = 0; i < 32; i++) {
277 if ((mask & (1 << i)) == 0)
278 continue;
279 /* Reserve the GPIO pin. */
247 return (-1);
248 }
249 sc->sc_pins_mapped[pin] = 1;
250
251 return (0);
252}
253
254static int
255gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask)
256{
257 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
258 int i, npins;
259
260 npins = 0;
261 for (i = 0; i < 32; i++) {
262 if (mask & (1 << i))
263 npins++;
264 }
265 if (npins == 0) {
266 device_printf(child, "empty pin mask\n");
267 return (EINVAL);
268 }
269 devi->npins = npins;
270 if (gpiobus_alloc_ivars(devi) != 0) {
271 device_printf(child, "cannot allocate device ivars\n");
272 return (EINVAL);
273 }
274 npins = 0;
275 for (i = 0; i < 32; i++) {
276 if ((mask & (1 << i)) == 0)
277 continue;
278 /* Reserve the GPIO pin. */
280 if (gpiobus_map_pin(sc->sc_busdev, child, i) != 0) {
279 if (gpiobus_map_pin(sc->sc_busdev, i) != 0) {
281 gpiobus_free_ivars(devi);
282 return (EINVAL);
283 }
284 devi->pins[npins++] = i;
285 }
286
287 return (0);
288}
289
290static int
291gpiobus_probe(device_t dev)
292{
293 device_set_desc(dev, "GPIO bus");
294
295 return (BUS_PROBE_GENERIC);
296}
297
298static int
299gpiobus_attach(device_t dev)
300{
301 int err;
302
303 err = gpiobus_init_softc(dev);
304 if (err != 0)
305 return (err);
306
307 /*
308 * Get parent's pins and mark them as unmapped
309 */
310 bus_generic_probe(dev);
311 bus_enumerate_hinted_children(dev);
312
313 return (bus_generic_attach(dev));
314}
315
316/*
317 * Since this is not a self-enumerating bus, and since we always add
318 * children in attach, we have to always delete children here.
319 */
320static int
321gpiobus_detach(device_t dev)
322{
323 struct gpiobus_softc *sc;
324 struct gpiobus_ivar *devi;
325 device_t *devlist;
326 int i, err, ndevs;
327
328 sc = GPIOBUS_SOFTC(dev);
329 KASSERT(mtx_initialized(&sc->sc_mtx),
330 ("gpiobus mutex not initialized"));
331 GPIOBUS_LOCK_DESTROY(sc);
332
333 if ((err = bus_generic_detach(dev)) != 0)
334 return (err);
335
336 if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
337 return (err);
338 for (i = 0; i < ndevs; i++) {
339 device_delete_child(dev, devlist[i]);
340 devi = GPIOBUS_IVAR(devlist[i]);
341 gpiobus_free_ivars(devi);
342 }
343 free(devlist, M_TEMP);
344
345 if (sc->sc_pins_mapped) {
346 free(sc->sc_pins_mapped, M_DEVBUF);
347 sc->sc_pins_mapped = NULL;
348 }
349
350 return (0);
351}
352
353static int
354gpiobus_suspend(device_t dev)
355{
356
357 return (bus_generic_suspend(dev));
358}
359
360static int
361gpiobus_resume(device_t dev)
362{
363
364 return (bus_generic_resume(dev));
365}
366
367static void
368gpiobus_probe_nomatch(device_t dev, device_t child)
369{
370 char pins[128];
371 struct gpiobus_ivar *devi;
372
373 devi = GPIOBUS_IVAR(child);
374 memset(pins, 0, sizeof(pins));
375 gpiobus_print_pins(devi, pins, sizeof(pins));
376 device_printf(dev, "<unknown device> at pin(s) %s", pins);
377 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
378 printf("\n");
379}
380
381static int
382gpiobus_print_child(device_t dev, device_t child)
383{
384 char pins[128];
385 int retval = 0;
386 struct gpiobus_ivar *devi;
387
388 devi = GPIOBUS_IVAR(child);
389 memset(pins, 0, sizeof(pins));
390 retval += bus_print_child_header(dev, child);
391 retval += printf(" at pin(s) ");
392 gpiobus_print_pins(devi, pins, sizeof(pins));
393 retval += printf("%s", pins);
394 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
395 retval += bus_print_child_footer(dev, child);
396
397 return (retval);
398}
399
400static int
401gpiobus_child_location_str(device_t bus, device_t child, char *buf,
402 size_t buflen)
403{
404 struct gpiobus_ivar *devi;
405
406 devi = GPIOBUS_IVAR(child);
407 strlcpy(buf, "pin(s)=", buflen);
408 gpiobus_print_pins(devi, buf, buflen);
409
410 return (0);
411}
412
413static int
414gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
415 size_t buflen)
416{
417
418 *buf = '\0';
419 return (0);
420}
421
422static device_t
423gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
424{
425 device_t child;
426 struct gpiobus_ivar *devi;
427
428 child = device_add_child_ordered(dev, order, name, unit);
429 if (child == NULL)
430 return (child);
431 devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
432 if (devi == NULL) {
433 device_delete_child(dev, child);
434 return (0);
435 }
436 resource_list_init(&devi->rl);
437 device_set_ivars(child, devi);
438
439 return (child);
440}
441
442static void
443gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
444{
445 struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
446 struct gpiobus_ivar *devi;
447 device_t child;
448 int irq, pins;
449
450 child = BUS_ADD_CHILD(bus, 0, dname, dunit);
451 devi = GPIOBUS_IVAR(child);
452 resource_int_value(dname, dunit, "pins", &pins);
453 if (gpiobus_parse_pins(sc, child, pins))
454 device_delete_child(bus, child);
455 if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
456 if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
457 device_printf(bus,
458 "warning: bus_set_resource() failed\n");
459 }
460}
461
462static int
463gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
464 u_long start, u_long count)
465{
466 struct gpiobus_ivar *devi;
467 struct resource_list_entry *rle;
468
469 dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
470 __func__, dev, child, type, rid, (void *)(intptr_t)start, count);
471 devi = GPIOBUS_IVAR(child);
472 rle = resource_list_add(&devi->rl, type, rid, start,
473 start + count - 1, count);
474 if (rle == NULL)
475 return (ENXIO);
476
477 return (0);
478}
479
480static struct resource *
481gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
482 u_long start, u_long end, u_long count, u_int flags)
483{
484 struct gpiobus_softc *sc;
485 struct resource *rv;
486 struct resource_list *rl;
487 struct resource_list_entry *rle;
488 int isdefault;
489
490 if (type != SYS_RES_IRQ)
491 return (NULL);
492 isdefault = (start == 0UL && end == ~0UL && count == 1);
493 rle = NULL;
494 if (isdefault) {
495 rl = BUS_GET_RESOURCE_LIST(bus, child);
496 if (rl == NULL)
497 return (NULL);
498 rle = resource_list_find(rl, type, *rid);
499 if (rle == NULL)
500 return (NULL);
501 if (rle->res != NULL)
502 panic("%s: resource entry is busy", __func__);
503 start = rle->start;
504 count = rle->count;
505 end = rle->end;
506 }
507 sc = device_get_softc(bus);
508 rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags,
509 child);
510 if (rv == NULL)
511 return (NULL);
512 rman_set_rid(rv, *rid);
513 if ((flags & RF_ACTIVE) != 0 &&
514 bus_activate_resource(child, type, *rid, rv) != 0) {
515 rman_release_resource(rv);
516 return (NULL);
517 }
518
519 return (rv);
520}
521
522static int
523gpiobus_release_resource(device_t bus __unused, device_t child, int type,
524 int rid, struct resource *r)
525{
526 int error;
527
528 if (rman_get_flags(r) & RF_ACTIVE) {
529 error = bus_deactivate_resource(child, type, rid, r);
530 if (error)
531 return (error);
532 }
533
534 return (rman_release_resource(r));
535}
536
537static struct resource_list *
538gpiobus_get_resource_list(device_t bus __unused, device_t child)
539{
540 struct gpiobus_ivar *ivar;
541
542 ivar = GPIOBUS_IVAR(child);
543
544 return (&ivar->rl);
545}
546
547static int
548gpiobus_acquire_bus(device_t busdev, device_t child, int how)
549{
550 struct gpiobus_softc *sc;
551
552 sc = device_get_softc(busdev);
553 GPIOBUS_ASSERT_UNLOCKED(sc);
554 GPIOBUS_LOCK(sc);
555 if (sc->sc_owner != NULL) {
556 if (how == GPIOBUS_DONTWAIT) {
557 GPIOBUS_UNLOCK(sc);
558 return (EWOULDBLOCK);
559 }
560 while (sc->sc_owner != NULL)
561 mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0);
562 }
563 sc->sc_owner = child;
564 GPIOBUS_UNLOCK(sc);
565
566 return (0);
567}
568
569static void
570gpiobus_release_bus(device_t busdev, device_t child)
571{
572 struct gpiobus_softc *sc;
573
574 sc = device_get_softc(busdev);
575 GPIOBUS_ASSERT_UNLOCKED(sc);
576 GPIOBUS_LOCK(sc);
577 if (sc->sc_owner == NULL)
578 panic("gpiobus: releasing unowned bus.");
579 if (sc->sc_owner != child)
580 panic("gpiobus: you don't own the bus. game over.");
581 sc->sc_owner = NULL;
582 wakeup(sc);
583 GPIOBUS_UNLOCK(sc);
584}
585
586static int
587gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin,
588 uint32_t flags)
589{
590 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
591 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
592 uint32_t caps;
593
594 if (pin >= devi->npins)
595 return (EINVAL);
596 if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0)
597 return (EINVAL);
598 if (gpio_check_flags(caps, flags) != 0)
599 return (EINVAL);
600
601 return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags));
602}
603
604static int
605gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin,
606 uint32_t *flags)
607{
608 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
609 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
610
611 if (pin >= devi->npins)
612 return (EINVAL);
613
614 return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags);
615}
616
617static int
618gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin,
619 uint32_t *caps)
620{
621 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
622 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
623
624 if (pin >= devi->npins)
625 return (EINVAL);
626
627 return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps);
628}
629
630static int
631gpiobus_pin_set(device_t dev, device_t child, uint32_t pin,
632 unsigned int value)
633{
634 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
635 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
636
637 if (pin >= devi->npins)
638 return (EINVAL);
639
640 return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value);
641}
642
643static int
644gpiobus_pin_get(device_t dev, device_t child, uint32_t pin,
645 unsigned int *value)
646{
647 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
648 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
649
650 if (pin >= devi->npins)
651 return (EINVAL);
652
653 return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value);
654}
655
656static int
657gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin)
658{
659 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
660 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
661
662 if (pin >= devi->npins)
663 return (EINVAL);
664
665 return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]);
666}
667
668static device_method_t gpiobus_methods[] = {
669 /* Device interface */
670 DEVMETHOD(device_probe, gpiobus_probe),
671 DEVMETHOD(device_attach, gpiobus_attach),
672 DEVMETHOD(device_detach, gpiobus_detach),
673 DEVMETHOD(device_shutdown, bus_generic_shutdown),
674 DEVMETHOD(device_suspend, gpiobus_suspend),
675 DEVMETHOD(device_resume, gpiobus_resume),
676
677 /* Bus interface */
678 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
679 DEVMETHOD(bus_config_intr, bus_generic_config_intr),
680 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
681 DEVMETHOD(bus_set_resource, gpiobus_set_resource),
682 DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource),
683 DEVMETHOD(bus_release_resource, gpiobus_release_resource),
684 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
685 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
686 DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list),
687 DEVMETHOD(bus_add_child, gpiobus_add_child),
688 DEVMETHOD(bus_probe_nomatch, gpiobus_probe_nomatch),
689 DEVMETHOD(bus_print_child, gpiobus_print_child),
690 DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
691 DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
692 DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
693
694 /* GPIO protocol */
695 DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
696 DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus),
697 DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags),
698 DEVMETHOD(gpiobus_pin_getcaps, gpiobus_pin_getcaps),
699 DEVMETHOD(gpiobus_pin_setflags, gpiobus_pin_setflags),
700 DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get),
701 DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set),
702 DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle),
703
704 DEVMETHOD_END
705};
706
707driver_t gpiobus_driver = {
708 "gpiobus",
709 gpiobus_methods,
710 sizeof(struct gpiobus_softc)
711};
712
713devclass_t gpiobus_devclass;
714
715DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0);
716MODULE_VERSION(gpiobus, 1);
280 gpiobus_free_ivars(devi);
281 return (EINVAL);
282 }
283 devi->pins[npins++] = i;
284 }
285
286 return (0);
287}
288
289static int
290gpiobus_probe(device_t dev)
291{
292 device_set_desc(dev, "GPIO bus");
293
294 return (BUS_PROBE_GENERIC);
295}
296
297static int
298gpiobus_attach(device_t dev)
299{
300 int err;
301
302 err = gpiobus_init_softc(dev);
303 if (err != 0)
304 return (err);
305
306 /*
307 * Get parent's pins and mark them as unmapped
308 */
309 bus_generic_probe(dev);
310 bus_enumerate_hinted_children(dev);
311
312 return (bus_generic_attach(dev));
313}
314
315/*
316 * Since this is not a self-enumerating bus, and since we always add
317 * children in attach, we have to always delete children here.
318 */
319static int
320gpiobus_detach(device_t dev)
321{
322 struct gpiobus_softc *sc;
323 struct gpiobus_ivar *devi;
324 device_t *devlist;
325 int i, err, ndevs;
326
327 sc = GPIOBUS_SOFTC(dev);
328 KASSERT(mtx_initialized(&sc->sc_mtx),
329 ("gpiobus mutex not initialized"));
330 GPIOBUS_LOCK_DESTROY(sc);
331
332 if ((err = bus_generic_detach(dev)) != 0)
333 return (err);
334
335 if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
336 return (err);
337 for (i = 0; i < ndevs; i++) {
338 device_delete_child(dev, devlist[i]);
339 devi = GPIOBUS_IVAR(devlist[i]);
340 gpiobus_free_ivars(devi);
341 }
342 free(devlist, M_TEMP);
343
344 if (sc->sc_pins_mapped) {
345 free(sc->sc_pins_mapped, M_DEVBUF);
346 sc->sc_pins_mapped = NULL;
347 }
348
349 return (0);
350}
351
352static int
353gpiobus_suspend(device_t dev)
354{
355
356 return (bus_generic_suspend(dev));
357}
358
359static int
360gpiobus_resume(device_t dev)
361{
362
363 return (bus_generic_resume(dev));
364}
365
366static void
367gpiobus_probe_nomatch(device_t dev, device_t child)
368{
369 char pins[128];
370 struct gpiobus_ivar *devi;
371
372 devi = GPIOBUS_IVAR(child);
373 memset(pins, 0, sizeof(pins));
374 gpiobus_print_pins(devi, pins, sizeof(pins));
375 device_printf(dev, "<unknown device> at pin(s) %s", pins);
376 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
377 printf("\n");
378}
379
380static int
381gpiobus_print_child(device_t dev, device_t child)
382{
383 char pins[128];
384 int retval = 0;
385 struct gpiobus_ivar *devi;
386
387 devi = GPIOBUS_IVAR(child);
388 memset(pins, 0, sizeof(pins));
389 retval += bus_print_child_header(dev, child);
390 retval += printf(" at pin(s) ");
391 gpiobus_print_pins(devi, pins, sizeof(pins));
392 retval += printf("%s", pins);
393 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
394 retval += bus_print_child_footer(dev, child);
395
396 return (retval);
397}
398
399static int
400gpiobus_child_location_str(device_t bus, device_t child, char *buf,
401 size_t buflen)
402{
403 struct gpiobus_ivar *devi;
404
405 devi = GPIOBUS_IVAR(child);
406 strlcpy(buf, "pin(s)=", buflen);
407 gpiobus_print_pins(devi, buf, buflen);
408
409 return (0);
410}
411
412static int
413gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
414 size_t buflen)
415{
416
417 *buf = '\0';
418 return (0);
419}
420
421static device_t
422gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
423{
424 device_t child;
425 struct gpiobus_ivar *devi;
426
427 child = device_add_child_ordered(dev, order, name, unit);
428 if (child == NULL)
429 return (child);
430 devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
431 if (devi == NULL) {
432 device_delete_child(dev, child);
433 return (0);
434 }
435 resource_list_init(&devi->rl);
436 device_set_ivars(child, devi);
437
438 return (child);
439}
440
441static void
442gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
443{
444 struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
445 struct gpiobus_ivar *devi;
446 device_t child;
447 int irq, pins;
448
449 child = BUS_ADD_CHILD(bus, 0, dname, dunit);
450 devi = GPIOBUS_IVAR(child);
451 resource_int_value(dname, dunit, "pins", &pins);
452 if (gpiobus_parse_pins(sc, child, pins))
453 device_delete_child(bus, child);
454 if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
455 if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
456 device_printf(bus,
457 "warning: bus_set_resource() failed\n");
458 }
459}
460
461static int
462gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
463 u_long start, u_long count)
464{
465 struct gpiobus_ivar *devi;
466 struct resource_list_entry *rle;
467
468 dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
469 __func__, dev, child, type, rid, (void *)(intptr_t)start, count);
470 devi = GPIOBUS_IVAR(child);
471 rle = resource_list_add(&devi->rl, type, rid, start,
472 start + count - 1, count);
473 if (rle == NULL)
474 return (ENXIO);
475
476 return (0);
477}
478
479static struct resource *
480gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
481 u_long start, u_long end, u_long count, u_int flags)
482{
483 struct gpiobus_softc *sc;
484 struct resource *rv;
485 struct resource_list *rl;
486 struct resource_list_entry *rle;
487 int isdefault;
488
489 if (type != SYS_RES_IRQ)
490 return (NULL);
491 isdefault = (start == 0UL && end == ~0UL && count == 1);
492 rle = NULL;
493 if (isdefault) {
494 rl = BUS_GET_RESOURCE_LIST(bus, child);
495 if (rl == NULL)
496 return (NULL);
497 rle = resource_list_find(rl, type, *rid);
498 if (rle == NULL)
499 return (NULL);
500 if (rle->res != NULL)
501 panic("%s: resource entry is busy", __func__);
502 start = rle->start;
503 count = rle->count;
504 end = rle->end;
505 }
506 sc = device_get_softc(bus);
507 rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags,
508 child);
509 if (rv == NULL)
510 return (NULL);
511 rman_set_rid(rv, *rid);
512 if ((flags & RF_ACTIVE) != 0 &&
513 bus_activate_resource(child, type, *rid, rv) != 0) {
514 rman_release_resource(rv);
515 return (NULL);
516 }
517
518 return (rv);
519}
520
521static int
522gpiobus_release_resource(device_t bus __unused, device_t child, int type,
523 int rid, struct resource *r)
524{
525 int error;
526
527 if (rman_get_flags(r) & RF_ACTIVE) {
528 error = bus_deactivate_resource(child, type, rid, r);
529 if (error)
530 return (error);
531 }
532
533 return (rman_release_resource(r));
534}
535
536static struct resource_list *
537gpiobus_get_resource_list(device_t bus __unused, device_t child)
538{
539 struct gpiobus_ivar *ivar;
540
541 ivar = GPIOBUS_IVAR(child);
542
543 return (&ivar->rl);
544}
545
546static int
547gpiobus_acquire_bus(device_t busdev, device_t child, int how)
548{
549 struct gpiobus_softc *sc;
550
551 sc = device_get_softc(busdev);
552 GPIOBUS_ASSERT_UNLOCKED(sc);
553 GPIOBUS_LOCK(sc);
554 if (sc->sc_owner != NULL) {
555 if (how == GPIOBUS_DONTWAIT) {
556 GPIOBUS_UNLOCK(sc);
557 return (EWOULDBLOCK);
558 }
559 while (sc->sc_owner != NULL)
560 mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0);
561 }
562 sc->sc_owner = child;
563 GPIOBUS_UNLOCK(sc);
564
565 return (0);
566}
567
568static void
569gpiobus_release_bus(device_t busdev, device_t child)
570{
571 struct gpiobus_softc *sc;
572
573 sc = device_get_softc(busdev);
574 GPIOBUS_ASSERT_UNLOCKED(sc);
575 GPIOBUS_LOCK(sc);
576 if (sc->sc_owner == NULL)
577 panic("gpiobus: releasing unowned bus.");
578 if (sc->sc_owner != child)
579 panic("gpiobus: you don't own the bus. game over.");
580 sc->sc_owner = NULL;
581 wakeup(sc);
582 GPIOBUS_UNLOCK(sc);
583}
584
585static int
586gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin,
587 uint32_t flags)
588{
589 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
590 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
591 uint32_t caps;
592
593 if (pin >= devi->npins)
594 return (EINVAL);
595 if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0)
596 return (EINVAL);
597 if (gpio_check_flags(caps, flags) != 0)
598 return (EINVAL);
599
600 return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags));
601}
602
603static int
604gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin,
605 uint32_t *flags)
606{
607 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
608 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
609
610 if (pin >= devi->npins)
611 return (EINVAL);
612
613 return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags);
614}
615
616static int
617gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin,
618 uint32_t *caps)
619{
620 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
621 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
622
623 if (pin >= devi->npins)
624 return (EINVAL);
625
626 return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps);
627}
628
629static int
630gpiobus_pin_set(device_t dev, device_t child, uint32_t pin,
631 unsigned int value)
632{
633 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
634 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
635
636 if (pin >= devi->npins)
637 return (EINVAL);
638
639 return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value);
640}
641
642static int
643gpiobus_pin_get(device_t dev, device_t child, uint32_t pin,
644 unsigned int *value)
645{
646 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
647 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
648
649 if (pin >= devi->npins)
650 return (EINVAL);
651
652 return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value);
653}
654
655static int
656gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin)
657{
658 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
659 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
660
661 if (pin >= devi->npins)
662 return (EINVAL);
663
664 return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]);
665}
666
667static device_method_t gpiobus_methods[] = {
668 /* Device interface */
669 DEVMETHOD(device_probe, gpiobus_probe),
670 DEVMETHOD(device_attach, gpiobus_attach),
671 DEVMETHOD(device_detach, gpiobus_detach),
672 DEVMETHOD(device_shutdown, bus_generic_shutdown),
673 DEVMETHOD(device_suspend, gpiobus_suspend),
674 DEVMETHOD(device_resume, gpiobus_resume),
675
676 /* Bus interface */
677 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
678 DEVMETHOD(bus_config_intr, bus_generic_config_intr),
679 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
680 DEVMETHOD(bus_set_resource, gpiobus_set_resource),
681 DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource),
682 DEVMETHOD(bus_release_resource, gpiobus_release_resource),
683 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
684 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
685 DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list),
686 DEVMETHOD(bus_add_child, gpiobus_add_child),
687 DEVMETHOD(bus_probe_nomatch, gpiobus_probe_nomatch),
688 DEVMETHOD(bus_print_child, gpiobus_print_child),
689 DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
690 DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
691 DEVMETHOD(bus_hinted_child, gpiobus_hinted_child),
692
693 /* GPIO protocol */
694 DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus),
695 DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus),
696 DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags),
697 DEVMETHOD(gpiobus_pin_getcaps, gpiobus_pin_getcaps),
698 DEVMETHOD(gpiobus_pin_setflags, gpiobus_pin_setflags),
699 DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get),
700 DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set),
701 DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle),
702
703 DEVMETHOD_END
704};
705
706driver_t gpiobus_driver = {
707 "gpiobus",
708 gpiobus_methods,
709 sizeof(struct gpiobus_softc)
710};
711
712devclass_t gpiobus_devclass;
713
714DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0);
715MODULE_VERSION(gpiobus, 1);