gpiobus.c revision 285784
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 285784 2015-07-22 04:18:33Z 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 = malloc(sizeof(*sc->sc_pins) * sc->sc_npins, M_DEVBUF,
189	    M_NOWAIT | M_ZERO);
190	if (sc->sc_pins == 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, 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) {
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[pin].mapped) {
246		device_printf(bus, "warning: pin %d is already mapped\n", pin);
247		return (-1);
248	}
249	sc->sc_pins[pin].mapped = 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. */
279		if (gpiobus_map_pin(sc->sc_busdev, i) != 0) {
280			gpiobus_free_ivars(devi);
281			return (EINVAL);
282		}
283		devi->pins[npins++] = i;
284		/* Use the child name as pin name. */
285		GPIOBUS_PIN_SETNAME(sc->sc_busdev, i,
286		    device_get_nameunit(child));
287	}
288
289	return (0);
290}
291
292static int
293gpiobus_probe(device_t dev)
294{
295	device_set_desc(dev, "GPIO bus");
296
297	return (BUS_PROBE_GENERIC);
298}
299
300static int
301gpiobus_attach(device_t dev)
302{
303	int err;
304
305	err = gpiobus_init_softc(dev);
306	if (err != 0)
307		return (err);
308
309	/*
310	 * Get parent's pins and mark them as unmapped
311	 */
312	bus_generic_probe(dev);
313	bus_enumerate_hinted_children(dev);
314
315	return (bus_generic_attach(dev));
316}
317
318/*
319 * Since this is not a self-enumerating bus, and since we always add
320 * children in attach, we have to always delete children here.
321 */
322static int
323gpiobus_detach(device_t dev)
324{
325	struct gpiobus_softc *sc;
326	struct gpiobus_ivar *devi;
327	device_t *devlist;
328	int i, err, ndevs;
329
330	sc = GPIOBUS_SOFTC(dev);
331	KASSERT(mtx_initialized(&sc->sc_mtx),
332	    ("gpiobus mutex not initialized"));
333	GPIOBUS_LOCK_DESTROY(sc);
334
335	if ((err = bus_generic_detach(dev)) != 0)
336		return (err);
337
338	if ((err = device_get_children(dev, &devlist, &ndevs)) != 0)
339		return (err);
340	for (i = 0; i < ndevs; i++) {
341		device_delete_child(dev, devlist[i]);
342		devi = GPIOBUS_IVAR(devlist[i]);
343		gpiobus_free_ivars(devi);
344	}
345	free(devlist, M_TEMP);
346	if (sc->sc_pins) {
347		for (i = 0; i < sc->sc_npins; i++) {
348			if (sc->sc_pins[i].name != NULL)
349				free(sc->sc_pins[i].name, M_DEVBUF);
350			sc->sc_pins[i].name = NULL;
351		}
352		free(sc->sc_pins, M_DEVBUF);
353		sc->sc_pins = NULL;
354	}
355
356	return (0);
357}
358
359static int
360gpiobus_suspend(device_t dev)
361{
362
363	return (bus_generic_suspend(dev));
364}
365
366static int
367gpiobus_resume(device_t dev)
368{
369
370	return (bus_generic_resume(dev));
371}
372
373static void
374gpiobus_probe_nomatch(device_t dev, device_t child)
375{
376	char pins[128];
377	struct gpiobus_ivar *devi;
378
379	devi = GPIOBUS_IVAR(child);
380	memset(pins, 0, sizeof(pins));
381	gpiobus_print_pins(devi, pins, sizeof(pins));
382	device_printf(dev, "<unknown device> at pin(s) %s", pins);
383	resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
384	printf("\n");
385}
386
387static int
388gpiobus_print_child(device_t dev, device_t child)
389{
390	char pins[128];
391	int retval = 0;
392	struct gpiobus_ivar *devi;
393
394	devi = GPIOBUS_IVAR(child);
395	memset(pins, 0, sizeof(pins));
396	retval += bus_print_child_header(dev, child);
397	if (devi->npins > 0) {
398		if (devi->npins > 1)
399			retval += printf(" at pins ");
400		else
401			retval += printf(" at pin ");
402		gpiobus_print_pins(devi, pins, sizeof(pins));
403		retval += printf("%s", pins);
404	}
405	resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld");
406	retval += bus_print_child_footer(dev, child);
407
408	return (retval);
409}
410
411static int
412gpiobus_child_location_str(device_t bus, device_t child, char *buf,
413    size_t buflen)
414{
415	struct gpiobus_ivar *devi;
416
417	devi = GPIOBUS_IVAR(child);
418	strlcpy(buf, "pin(s)=", buflen);
419	gpiobus_print_pins(devi, buf, buflen);
420
421	return (0);
422}
423
424static int
425gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf,
426    size_t buflen)
427{
428
429	*buf = '\0';
430	return (0);
431}
432
433static device_t
434gpiobus_add_child(device_t dev, u_int order, const char *name, int unit)
435{
436	device_t child;
437	struct gpiobus_ivar *devi;
438
439	child = device_add_child_ordered(dev, order, name, unit);
440	if (child == NULL)
441		return (child);
442	devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
443	if (devi == NULL) {
444		device_delete_child(dev, child);
445		return (0);
446	}
447	resource_list_init(&devi->rl);
448	device_set_ivars(child, devi);
449
450	return (child);
451}
452
453static void
454gpiobus_hinted_child(device_t bus, const char *dname, int dunit)
455{
456	struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus);
457	struct gpiobus_ivar *devi;
458	device_t child;
459	int irq, pins;
460
461	child = BUS_ADD_CHILD(bus, 0, dname, dunit);
462	devi = GPIOBUS_IVAR(child);
463	resource_int_value(dname, dunit, "pins", &pins);
464	if (gpiobus_parse_pins(sc, child, pins))
465		device_delete_child(bus, child);
466	if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
467		if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0)
468			device_printf(bus,
469			    "warning: bus_set_resource() failed\n");
470	}
471}
472
473static int
474gpiobus_set_resource(device_t dev, device_t child, int type, int rid,
475    u_long start, u_long count)
476{
477	struct gpiobus_ivar *devi;
478	struct resource_list_entry *rle;
479
480	dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n",
481	    __func__, dev, child, type, rid, (void *)(intptr_t)start, count);
482	devi = GPIOBUS_IVAR(child);
483	rle = resource_list_add(&devi->rl, type, rid, start,
484	    start + count - 1, count);
485	if (rle == NULL)
486		return (ENXIO);
487
488	return (0);
489}
490
491static struct resource *
492gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid,
493    u_long start, u_long end, u_long count, u_int flags)
494{
495	struct gpiobus_softc *sc;
496	struct resource *rv;
497	struct resource_list *rl;
498	struct resource_list_entry *rle;
499	int isdefault;
500
501	if (type != SYS_RES_IRQ)
502		return (NULL);
503	isdefault = (start == 0UL && end == ~0UL && count == 1);
504	rle = NULL;
505	if (isdefault) {
506		rl = BUS_GET_RESOURCE_LIST(bus, child);
507		if (rl == NULL)
508			return (NULL);
509		rle = resource_list_find(rl, type, *rid);
510		if (rle == NULL)
511			return (NULL);
512		if (rle->res != NULL)
513			panic("%s: resource entry is busy", __func__);
514		start = rle->start;
515		count = rle->count;
516		end = rle->end;
517	}
518	sc = device_get_softc(bus);
519	rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags,
520	    child);
521	if (rv == NULL)
522		return (NULL);
523	rman_set_rid(rv, *rid);
524	if ((flags & RF_ACTIVE) != 0 &&
525	    bus_activate_resource(child, type, *rid, rv) != 0) {
526		rman_release_resource(rv);
527		return (NULL);
528	}
529
530	return (rv);
531}
532
533static int
534gpiobus_release_resource(device_t bus __unused, device_t child, int type,
535    int rid, struct resource *r)
536{
537	int error;
538
539	if (rman_get_flags(r) & RF_ACTIVE) {
540		error = bus_deactivate_resource(child, type, rid, r);
541		if (error)
542			return (error);
543	}
544
545	return (rman_release_resource(r));
546}
547
548static struct resource_list *
549gpiobus_get_resource_list(device_t bus __unused, device_t child)
550{
551	struct gpiobus_ivar *ivar;
552
553	ivar = GPIOBUS_IVAR(child);
554
555	return (&ivar->rl);
556}
557
558static int
559gpiobus_acquire_bus(device_t busdev, device_t child, int how)
560{
561	struct gpiobus_softc *sc;
562
563	sc = device_get_softc(busdev);
564	GPIOBUS_ASSERT_UNLOCKED(sc);
565	GPIOBUS_LOCK(sc);
566	if (sc->sc_owner != NULL) {
567		if (how == GPIOBUS_DONTWAIT) {
568			GPIOBUS_UNLOCK(sc);
569			return (EWOULDBLOCK);
570		}
571		while (sc->sc_owner != NULL)
572			mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0);
573	}
574	sc->sc_owner = child;
575	GPIOBUS_UNLOCK(sc);
576
577	return (0);
578}
579
580static void
581gpiobus_release_bus(device_t busdev, device_t child)
582{
583	struct gpiobus_softc *sc;
584
585	sc = device_get_softc(busdev);
586	GPIOBUS_ASSERT_UNLOCKED(sc);
587	GPIOBUS_LOCK(sc);
588	if (sc->sc_owner == NULL)
589		panic("gpiobus: releasing unowned bus.");
590	if (sc->sc_owner != child)
591		panic("gpiobus: you don't own the bus. game over.");
592	sc->sc_owner = NULL;
593	wakeup(sc);
594	GPIOBUS_UNLOCK(sc);
595}
596
597static int
598gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin,
599    uint32_t flags)
600{
601	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
602	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
603	uint32_t caps;
604
605	if (pin >= devi->npins)
606		return (EINVAL);
607	if (GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], &caps) != 0)
608		return (EINVAL);
609	if (gpio_check_flags(caps, flags) != 0)
610		return (EINVAL);
611
612	return (GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags));
613}
614
615static int
616gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin,
617    uint32_t *flags)
618{
619	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
620	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
621
622	if (pin >= devi->npins)
623		return (EINVAL);
624
625	return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags);
626}
627
628static int
629gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin,
630    uint32_t *caps)
631{
632	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
633	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
634
635	if (pin >= devi->npins)
636		return (EINVAL);
637
638	return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps);
639}
640
641static int
642gpiobus_pin_set(device_t dev, device_t child, uint32_t pin,
643    unsigned int value)
644{
645	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
646	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
647
648	if (pin >= devi->npins)
649		return (EINVAL);
650
651	return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value);
652}
653
654static int
655gpiobus_pin_get(device_t dev, device_t child, uint32_t pin,
656    unsigned int *value)
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_GET(sc->sc_dev, devi->pins[pin], value);
665}
666
667static int
668gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin)
669{
670	struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev);
671	struct gpiobus_ivar *devi = GPIOBUS_IVAR(child);
672
673	if (pin >= devi->npins)
674		return (EINVAL);
675
676	return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]);
677}
678
679static int
680gpiobus_pin_getname(device_t dev, uint32_t pin, char *name)
681{
682	struct gpiobus_softc *sc;
683
684	sc = GPIOBUS_SOFTC(dev);
685	if (pin > sc->sc_npins)
686		return (EINVAL);
687	/* Did we have a name for this pin ? */
688	if (sc->sc_pins[pin].name != NULL) {
689		memcpy(name, sc->sc_pins[pin].name, GPIOMAXNAME);
690		return (0);
691	}
692
693	/* Return the default pin name. */
694	return (GPIO_PIN_GETNAME(device_get_parent(dev), pin, name));
695}
696
697static int
698gpiobus_pin_setname(device_t dev, uint32_t pin, const char *name)
699{
700	struct gpiobus_softc *sc;
701
702	sc = GPIOBUS_SOFTC(dev);
703	if (pin > sc->sc_npins)
704		return (EINVAL);
705	if (name == NULL)
706		return (EINVAL);
707	/* Save the pin name. */
708	if (sc->sc_pins[pin].name == NULL)
709		sc->sc_pins[pin].name = malloc(GPIOMAXNAME, M_DEVBUF,
710		    M_WAITOK | M_ZERO);
711	strlcpy(sc->sc_pins[pin].name, name, GPIOMAXNAME);
712
713	return (0);
714}
715
716static device_method_t gpiobus_methods[] = {
717	/* Device interface */
718	DEVMETHOD(device_probe,		gpiobus_probe),
719	DEVMETHOD(device_attach,	gpiobus_attach),
720	DEVMETHOD(device_detach,	gpiobus_detach),
721	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
722	DEVMETHOD(device_suspend,	gpiobus_suspend),
723	DEVMETHOD(device_resume,	gpiobus_resume),
724
725	/* Bus interface */
726	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
727	DEVMETHOD(bus_config_intr,	bus_generic_config_intr),
728	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
729	DEVMETHOD(bus_set_resource,	gpiobus_set_resource),
730	DEVMETHOD(bus_alloc_resource,	gpiobus_alloc_resource),
731	DEVMETHOD(bus_release_resource,	gpiobus_release_resource),
732	DEVMETHOD(bus_activate_resource,	bus_generic_activate_resource),
733	DEVMETHOD(bus_deactivate_resource,	bus_generic_deactivate_resource),
734	DEVMETHOD(bus_get_resource_list,	gpiobus_get_resource_list),
735	DEVMETHOD(bus_add_child,	gpiobus_add_child),
736	DEVMETHOD(bus_probe_nomatch,	gpiobus_probe_nomatch),
737	DEVMETHOD(bus_print_child,	gpiobus_print_child),
738	DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str),
739	DEVMETHOD(bus_child_location_str, gpiobus_child_location_str),
740	DEVMETHOD(bus_hinted_child,	gpiobus_hinted_child),
741
742	/* GPIO protocol */
743	DEVMETHOD(gpiobus_acquire_bus,	gpiobus_acquire_bus),
744	DEVMETHOD(gpiobus_release_bus,	gpiobus_release_bus),
745	DEVMETHOD(gpiobus_pin_getflags,	gpiobus_pin_getflags),
746	DEVMETHOD(gpiobus_pin_getcaps,	gpiobus_pin_getcaps),
747	DEVMETHOD(gpiobus_pin_setflags,	gpiobus_pin_setflags),
748	DEVMETHOD(gpiobus_pin_get,	gpiobus_pin_get),
749	DEVMETHOD(gpiobus_pin_set,	gpiobus_pin_set),
750	DEVMETHOD(gpiobus_pin_toggle,	gpiobus_pin_toggle),
751	DEVMETHOD(gpiobus_pin_getname,	gpiobus_pin_getname),
752	DEVMETHOD(gpiobus_pin_setname,	gpiobus_pin_setname),
753
754	DEVMETHOD_END
755};
756
757driver_t gpiobus_driver = {
758	"gpiobus",
759	gpiobus_methods,
760	sizeof(struct gpiobus_softc)
761};
762
763devclass_t	gpiobus_devclass;
764
765DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0);
766MODULE_VERSION(gpiobus, 1);
767