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