]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/gpio/gpiobus.c
Import tzdata 2018c
[FreeBSD/FreeBSD.git] / sys / dev / gpio / gpiobus.c
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$");
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
54 static void gpiobus_print_pins(struct gpiobus_ivar *, char *, size_t);
55 static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int);
56 static int gpiobus_probe(device_t);
57 static int gpiobus_attach(device_t);
58 static int gpiobus_detach(device_t);
59 static int gpiobus_suspend(device_t);
60 static int gpiobus_resume(device_t);
61 static void gpiobus_probe_nomatch(device_t, device_t);
62 static int gpiobus_print_child(device_t, device_t);
63 static int gpiobus_child_location_str(device_t, device_t, char *, size_t);
64 static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t);
65 static device_t gpiobus_add_child(device_t, u_int, const char *, int);
66 static void gpiobus_hinted_child(device_t, const char *, int);
67
68 /*
69  * GPIOBUS interface
70  */
71 static int gpiobus_acquire_bus(device_t, device_t, int);
72 static void gpiobus_release_bus(device_t, device_t);
73 static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t);
74 static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*);
75 static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*);
76 static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int);
77 static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*);
78 static 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
87 struct resource *
88 gpio_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
112 struct resource *
113 gpio_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
121 int
122 gpio_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
138 static void
139 gpiobus_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
181 device_t
182 gpiobus_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
201 int
202 gpiobus_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
216 int
217 gpiobus_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
249 int
250 gpiobus_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
268 void
269 gpiobus_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
282 int
283 gpiobus_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 */
305 int
306 gpiobus_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
328 static int
329 gpiobus_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
366 static int
367 gpiobus_probe(device_t dev)
368 {
369         device_set_desc(dev, "GPIO bus");
370
371         return (BUS_PROBE_GENERIC);
372 }
373
374 static int
375 gpiobus_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  */
396 static int
397 gpiobus_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
436 static int
437 gpiobus_suspend(device_t dev)
438 {
439
440         return (bus_generic_suspend(dev));
441 }
442
443 static int
444 gpiobus_resume(device_t dev)
445 {
446
447         return (bus_generic_resume(dev));
448 }
449
450 static void
451 gpiobus_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
467 static int
468 gpiobus_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
491 static int
492 gpiobus_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
507 static int
508 gpiobus_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
516 static device_t
517 gpiobus_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
536 static void
537 gpiobus_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
559 static int
560 gpiobus_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
577 static struct resource *
578 gpiobus_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
619 static int
620 gpiobus_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
634 static struct resource_list *
635 gpiobus_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
644 static int
645 gpiobus_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
670 static void
671 gpiobus_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
692 static int
693 gpiobus_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
710 static int
711 gpiobus_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
723 static int
724 gpiobus_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
736 static int
737 gpiobus_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
749 static int
750 gpiobus_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
762 static int
763 gpiobus_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
774 static int
775 gpiobus_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
792 static int
793 gpiobus_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
811 static 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
852 driver_t gpiobus_driver = {
853         "gpiobus",
854         gpiobus_methods,
855         sizeof(struct gpiobus_softc)
856 };
857
858 devclass_t      gpiobus_devclass;
859
860 EARLY_DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0,
861     BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
862 MODULE_VERSION(gpiobus, 1);