]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/allwinner/a10_gpio.c
Copy needed include files from EDK2. This is a minimal set gleened
[FreeBSD/FreeBSD.git] / sys / arm / allwinner / a10_gpio.c
1 /*-
2  * Copyright (c) 2013 Ganbold Tsagaankhuu <ganbold@freebsd.org>
3  * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
4  * Copyright (c) 2012 Luiz Otavio O Souza.
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
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/rman.h>
39 #include <sys/lock.h>
40 #include <sys/mutex.h>
41 #include <sys/gpio.h>
42
43 #include <machine/bus.h>
44 #include <machine/resource.h>
45 #include <machine/intr.h>
46
47 #include <dev/gpio/gpiobusvar.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
50 #include <dev/fdt/fdt_pinctrl.h>
51
52 #include <arm/allwinner/aw_machdep.h>
53 #include <arm/allwinner/allwinner_pinctrl.h>
54 #include <dev/extres/clk/clk.h>
55 #include <dev/extres/hwreset/hwreset.h>
56
57 #if defined(__aarch64__)
58 #include "opt_soc.h"
59 #endif
60
61 #include "gpio_if.h"
62
63 #define A10_GPIO_DEFAULT_CAPS   (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     \
64     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
65
66 #define A10_GPIO_NONE           0
67 #define A10_GPIO_PULLUP         1
68 #define A10_GPIO_PULLDOWN       2
69
70 #define A10_GPIO_INPUT          0
71 #define A10_GPIO_OUTPUT         1
72
73 #define AW_GPIO_DRV_MASK        0x3
74 #define AW_GPIO_PUD_MASK        0x3
75
76 #define AW_PINCTRL      1
77 #define AW_R_PINCTRL    2
78
79 /* Defined in a10_padconf.c */
80 #ifdef SOC_ALLWINNER_A10
81 extern const struct allwinner_padconf a10_padconf;
82 #endif
83
84 /* Defined in a13_padconf.c */
85 #ifdef SOC_ALLWINNER_A13
86 extern const struct allwinner_padconf a13_padconf;
87 #endif
88
89 /* Defined in a20_padconf.c */
90 #ifdef SOC_ALLWINNER_A20
91 extern const struct allwinner_padconf a20_padconf;
92 #endif
93
94 /* Defined in a31_padconf.c */
95 #ifdef SOC_ALLWINNER_A31
96 extern const struct allwinner_padconf a31_padconf;
97 #endif
98
99 /* Defined in a31s_padconf.c */
100 #ifdef SOC_ALLWINNER_A31S
101 extern const struct allwinner_padconf a31s_padconf;
102 #endif
103
104 #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
105 extern const struct allwinner_padconf a31_r_padconf;
106 #endif
107
108 /* Defined in a33_padconf.c */
109 #ifdef SOC_ALLWINNER_A33
110 extern const struct allwinner_padconf a33_padconf;
111 #endif
112
113 /* Defined in h3_padconf.c */
114 #ifdef SOC_ALLWINNER_H3
115 extern const struct allwinner_padconf h3_padconf;
116 extern const struct allwinner_padconf h3_r_padconf;
117 #endif
118
119 /* Defined in a83t_padconf.c */
120 #ifdef SOC_ALLWINNER_A83T
121 extern const struct allwinner_padconf a83t_padconf;
122 extern const struct allwinner_padconf a83t_r_padconf;
123 #endif
124
125 /* Defined in a64_padconf.c */
126 #ifdef SOC_ALLWINNER_A64
127 extern const struct allwinner_padconf a64_padconf;
128 extern const struct allwinner_padconf a64_r_padconf;
129 #endif
130
131 static struct ofw_compat_data compat_data[] = {
132 #ifdef SOC_ALLWINNER_A10
133         {"allwinner,sun4i-a10-pinctrl",         (uintptr_t)&a10_padconf},
134 #endif
135 #ifdef SOC_ALLWINNER_A13
136         {"allwinner,sun5i-a13-pinctrl",         (uintptr_t)&a13_padconf},
137 #endif
138 #ifdef SOC_ALLWINNER_A20
139         {"allwinner,sun7i-a20-pinctrl",         (uintptr_t)&a20_padconf},
140 #endif
141 #ifdef SOC_ALLWINNER_A31
142         {"allwinner,sun6i-a31-pinctrl",         (uintptr_t)&a31_padconf},
143 #endif
144 #ifdef SOC_ALLWINNER_A31S
145         {"allwinner,sun6i-a31s-pinctrl",        (uintptr_t)&a31s_padconf},
146 #endif
147 #if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
148         {"allwinner,sun6i-a31-r-pinctrl",       (uintptr_t)&a31_r_padconf},
149 #endif
150 #ifdef SOC_ALLWINNER_A33
151         {"allwinner,sun6i-a33-pinctrl",         (uintptr_t)&a33_padconf},
152 #endif
153 #ifdef SOC_ALLWINNER_A83T
154         {"allwinner,sun8i-a83t-pinctrl",        (uintptr_t)&a83t_padconf},
155         {"allwinner,sun8i-a83t-r-pinctrl",      (uintptr_t)&a83t_r_padconf},
156 #endif
157 #ifdef SOC_ALLWINNER_H3
158         {"allwinner,sun8i-h3-pinctrl",          (uintptr_t)&h3_padconf},
159         {"allwinner,sun8i-h3-r-pinctrl",        (uintptr_t)&h3_r_padconf},
160 #endif
161 #ifdef SOC_ALLWINNER_A64
162         {"allwinner,sun50i-a64-pinctrl",        (uintptr_t)&a64_padconf},
163         {"allwinner,sun50i-a64-r-pinctrl",      (uintptr_t)&a64_r_padconf},
164 #endif
165         {NULL,  0}
166 };
167
168 struct a10_gpio_softc {
169         device_t                sc_dev;
170         device_t                sc_busdev;
171         struct mtx              sc_mtx;
172         struct resource *       sc_mem_res;
173         struct resource *       sc_irq_res;
174         bus_space_tag_t         sc_bst;
175         bus_space_handle_t      sc_bsh;
176         void *                  sc_intrhand;
177         const struct allwinner_padconf *        padconf;
178 };
179
180 #define A10_GPIO_LOCK(_sc)              mtx_lock_spin(&(_sc)->sc_mtx)
181 #define A10_GPIO_UNLOCK(_sc)            mtx_unlock_spin(&(_sc)->sc_mtx)
182 #define A10_GPIO_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
183
184 #define A10_GPIO_GP_CFG(_bank, _idx)    0x00 + ((_bank) * 0x24) + ((_idx) << 2)
185 #define A10_GPIO_GP_DAT(_bank)          0x10 + ((_bank) * 0x24)
186 #define A10_GPIO_GP_DRV(_bank, _idx)    0x14 + ((_bank) * 0x24) + ((_idx) << 2)
187 #define A10_GPIO_GP_PUL(_bank, _idx)    0x1c + ((_bank) * 0x24) + ((_idx) << 2)
188
189 #define A10_GPIO_GP_INT_CFG0            0x200
190 #define A10_GPIO_GP_INT_CFG1            0x204
191 #define A10_GPIO_GP_INT_CFG2            0x208
192 #define A10_GPIO_GP_INT_CFG3            0x20c
193
194 #define A10_GPIO_GP_INT_CTL             0x210
195 #define A10_GPIO_GP_INT_STA             0x214
196 #define A10_GPIO_GP_INT_DEB             0x218
197
198 #define A10_GPIO_WRITE(_sc, _off, _val)         \
199     bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
200 #define A10_GPIO_READ(_sc, _off)                \
201     bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
202
203 static uint32_t
204 a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
205 {
206         uint32_t bank, func, offset;
207
208         /* Must be called with lock held. */
209         A10_GPIO_LOCK_ASSERT(sc);
210
211         if (pin > sc->padconf->npins)
212                 return (0);
213         bank = sc->padconf->pins[pin].port;
214         pin = sc->padconf->pins[pin].pin;
215         offset = ((pin & 0x07) << 2);
216
217         func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
218
219         return ((func >> offset) & 0x7);
220 }
221
222 static int
223 a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
224 {
225         uint32_t bank, data, offset;
226
227         /* Check if the function exists in the padconf data */
228         if (sc->padconf->pins[pin].functions[f] == NULL)
229                 return (EINVAL);
230
231         /* Must be called with lock held. */
232         A10_GPIO_LOCK_ASSERT(sc);
233
234         bank = sc->padconf->pins[pin].port;
235         pin = sc->padconf->pins[pin].pin;
236         offset = ((pin & 0x07) << 2);
237
238         data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
239         data &= ~(7 << offset);
240         data |= (f << offset);
241         A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data);
242
243         return (0);
244 }
245
246 static uint32_t
247 a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin)
248 {
249         uint32_t bank, offset, val;
250
251         /* Must be called with lock held. */
252         A10_GPIO_LOCK_ASSERT(sc);
253
254         bank = sc->padconf->pins[pin].port;
255         pin = sc->padconf->pins[pin].pin;
256         offset = ((pin & 0x0f) << 1);
257
258         val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
259
260         return ((val >> offset) & AW_GPIO_PUD_MASK);
261 }
262
263 static void
264 a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
265 {
266         uint32_t bank, offset, val;
267
268         /* Must be called with lock held. */
269         A10_GPIO_LOCK_ASSERT(sc);
270
271         bank = sc->padconf->pins[pin].port;
272         pin = sc->padconf->pins[pin].pin;
273         offset = ((pin & 0x0f) << 1);
274
275         val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
276         val &= ~(AW_GPIO_PUD_MASK << offset);
277         val |= (state << offset);
278         A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
279 }
280
281 static uint32_t
282 a10_gpio_get_drv(struct a10_gpio_softc *sc, uint32_t pin)
283 {
284         uint32_t bank, offset, val;
285
286         /* Must be called with lock held. */
287         A10_GPIO_LOCK_ASSERT(sc);
288
289         bank = sc->padconf->pins[pin].port;
290         pin = sc->padconf->pins[pin].pin;
291         offset = ((pin & 0x0f) << 1);
292
293         val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
294
295         return ((val >> offset) & AW_GPIO_DRV_MASK);
296 }
297
298 static void
299 a10_gpio_set_drv(struct a10_gpio_softc *sc, uint32_t pin, uint32_t drive)
300 {
301         uint32_t bank, offset, val;
302
303         /* Must be called with lock held. */
304         A10_GPIO_LOCK_ASSERT(sc);
305
306         bank = sc->padconf->pins[pin].port;
307         pin = sc->padconf->pins[pin].pin;
308         offset = ((pin & 0x0f) << 1);
309
310         val = A10_GPIO_READ(sc, A10_GPIO_GP_DRV(bank, pin >> 4));
311         val &= ~(AW_GPIO_DRV_MASK << offset);
312         val |= (drive << offset);
313         A10_GPIO_WRITE(sc, A10_GPIO_GP_DRV(bank, pin >> 4), val);
314 }
315
316 static int
317 a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
318 {
319         int err = 0;
320
321         /* Must be called with lock held. */
322         A10_GPIO_LOCK_ASSERT(sc);
323
324         /* Manage input/output. */
325         if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
326                 if (flags & GPIO_PIN_OUTPUT)
327                         err = a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT);
328                 else
329                         err = a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
330         }
331
332         if (err)
333                 return (err);
334
335         /* Manage Pull-up/pull-down. */
336         if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
337                 if (flags & GPIO_PIN_PULLUP)
338                         a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
339                 else
340                         a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
341         } else
342                 a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
343
344         return (0);
345 }
346
347 static device_t
348 a10_gpio_get_bus(device_t dev)
349 {
350         struct a10_gpio_softc *sc;
351
352         sc = device_get_softc(dev);
353
354         return (sc->sc_busdev);
355 }
356
357 static int
358 a10_gpio_pin_max(device_t dev, int *maxpin)
359 {
360         struct a10_gpio_softc *sc;
361
362         sc = device_get_softc(dev);
363
364         *maxpin = sc->padconf->npins - 1;
365         return (0);
366 }
367
368 static int
369 a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
370 {
371         struct a10_gpio_softc *sc;
372
373         sc = device_get_softc(dev);
374         if (pin >= sc->padconf->npins)
375                 return (EINVAL);
376
377         *caps = A10_GPIO_DEFAULT_CAPS;
378
379         return (0);
380 }
381
382 static int
383 a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
384 {
385         struct a10_gpio_softc *sc;
386         uint32_t func;
387         uint32_t pud;
388
389         sc = device_get_softc(dev);
390         if (pin >= sc->padconf->npins)
391                 return (EINVAL);
392
393         A10_GPIO_LOCK(sc);
394         func = a10_gpio_get_function(sc, pin);
395         switch (func) {
396         case A10_GPIO_INPUT:
397                 *flags = GPIO_PIN_INPUT;
398                 break;
399         case A10_GPIO_OUTPUT:
400                 *flags = GPIO_PIN_OUTPUT;
401                 break;
402         default:
403                 *flags = 0;
404                 break;
405         }
406
407         pud = a10_gpio_get_pud(sc, pin);
408         switch (pud) {
409         case A10_GPIO_PULLDOWN:
410                 *flags |= GPIO_PIN_PULLDOWN;
411                 break;
412         case A10_GPIO_PULLUP:
413                 *flags |= GPIO_PIN_PULLUP;
414                 break;
415         default:
416                 break;
417         }
418
419         A10_GPIO_UNLOCK(sc);
420
421         return (0);
422 }
423
424 static int
425 a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
426 {
427         struct a10_gpio_softc *sc;
428
429         sc = device_get_softc(dev);
430         if (pin >= sc->padconf->npins)
431                 return (EINVAL);
432
433         snprintf(name, GPIOMAXNAME - 1, "%s",
434             sc->padconf->pins[pin].name);
435         name[GPIOMAXNAME - 1] = '\0';
436
437         return (0);
438 }
439
440 static int
441 a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
442 {
443         struct a10_gpio_softc *sc;
444         int err;
445
446         sc = device_get_softc(dev);
447         if (pin > sc->padconf->npins)
448                 return (EINVAL);
449
450         A10_GPIO_LOCK(sc);
451         err = a10_gpio_pin_configure(sc, pin, flags);
452         A10_GPIO_UNLOCK(sc);
453
454         return (err);
455 }
456
457 static int
458 a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
459 {
460         struct a10_gpio_softc *sc;
461         uint32_t bank, data;
462
463         sc = device_get_softc(dev);
464         if (pin > sc->padconf->npins)
465                 return (EINVAL);
466
467         bank = sc->padconf->pins[pin].port;
468         pin = sc->padconf->pins[pin].pin;
469
470         A10_GPIO_LOCK(sc);
471         data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
472         if (value)
473                 data |= (1 << pin);
474         else
475                 data &= ~(1 << pin);
476         A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
477         A10_GPIO_UNLOCK(sc);
478
479         return (0);
480 }
481
482 static int
483 a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
484 {
485         struct a10_gpio_softc *sc;
486         uint32_t bank, reg_data;
487
488         sc = device_get_softc(dev);
489         if (pin > sc->padconf->npins)
490                 return (EINVAL);
491
492         bank = sc->padconf->pins[pin].port;
493         pin = sc->padconf->pins[pin].pin;
494
495         A10_GPIO_LOCK(sc);
496         reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
497         A10_GPIO_UNLOCK(sc);
498         *val = (reg_data & (1 << pin)) ? 1 : 0;
499
500         return (0);
501 }
502
503 static int
504 a10_gpio_pin_toggle(device_t dev, uint32_t pin)
505 {
506         struct a10_gpio_softc *sc;
507         uint32_t bank, data;
508
509         sc = device_get_softc(dev);
510         if (pin > sc->padconf->npins)
511                 return (EINVAL);
512
513         bank = sc->padconf->pins[pin].port;
514         pin = sc->padconf->pins[pin].pin;
515
516         A10_GPIO_LOCK(sc);
517         data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
518         if (data & (1 << pin))
519                 data &= ~(1 << pin);
520         else
521                 data |= (1 << pin);
522         A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
523         A10_GPIO_UNLOCK(sc);
524
525         return (0);
526 }
527
528 static int
529 aw_find_pinnum_by_name(struct a10_gpio_softc *sc, const char *pinname)
530 {
531         int i;
532
533         for (i = 0; i < sc->padconf->npins; i++)
534                 if (!strcmp(pinname, sc->padconf->pins[i].name))
535                         return i;
536
537         return (-1);
538 }
539
540 static int
541 aw_find_pin_func(struct a10_gpio_softc *sc, int pin, const char *func)
542 {
543         int i;
544
545         for (i = 0; i < AW_MAX_FUNC_BY_PIN; i++)
546                 if (sc->padconf->pins[pin].functions[i] &&
547                     !strcmp(func, sc->padconf->pins[pin].functions[i]))
548                         return (i);
549
550         return (-1);
551 }
552
553 static int
554 aw_fdt_configure_pins(device_t dev, phandle_t cfgxref)
555 {
556         struct a10_gpio_softc *sc;
557         phandle_t node;
558         const char **pinlist = NULL;
559         char *pin_function = NULL;
560         uint32_t pin_drive, pin_pull;
561         int pins_nb, pin_num, pin_func, i, ret;
562
563         sc = device_get_softc(dev);
564         node = OF_node_from_xref(cfgxref);
565         ret = 0;
566
567         /* Getting all prop for configuring pins */
568         pins_nb = ofw_bus_string_list_to_array(node, "allwinner,pins", &pinlist);
569         if (pins_nb <= 0)
570                 return (ENOENT);
571         if (OF_getprop_alloc(node, "allwinner,function",
572                              sizeof(*pin_function),
573                              (void **)&pin_function) == -1) {
574                 ret = ENOENT;
575                 goto out;
576         }
577         if (OF_getencprop(node, "allwinner,drive",
578                           &pin_drive, sizeof(pin_drive)) == -1) {
579                 ret = ENOENT;
580                 goto out;
581         }
582         if (OF_getencprop(node, "allwinner,pull",
583                           &pin_pull, sizeof(pin_pull)) == -1) {
584                 ret = ENOENT;
585                 goto out;
586         }
587
588         /* Configure each pin to the correct function, drive and pull */
589         for (i = 0; i < pins_nb; i++) {
590                 pin_num = aw_find_pinnum_by_name(sc, pinlist[i]);
591                 if (pin_num == -1) {
592                         ret = ENOENT;
593                         goto out;
594                 }
595                 pin_func = aw_find_pin_func(sc, pin_num, pin_function);
596                 if (pin_func == -1) {
597                         ret = ENOENT;
598                         goto out;
599                 }
600
601                 A10_GPIO_LOCK(sc);
602
603                 if (a10_gpio_get_function(sc, pin_num) != pin_func)
604                         a10_gpio_set_function(sc, pin_num, pin_func);
605                 if (a10_gpio_get_drv(sc, pin_num) != pin_drive)
606                         a10_gpio_set_drv(sc, pin_num, pin_drive);
607                 if (a10_gpio_get_pud(sc, pin_num) != pin_pull &&
608                         (pin_pull == A10_GPIO_PULLUP ||
609                             pin_pull == A10_GPIO_PULLDOWN))
610                         a10_gpio_set_pud(sc, pin_num, pin_pull);
611                 A10_GPIO_UNLOCK(sc);
612         }
613
614  out:
615         OF_prop_free(pinlist);
616         OF_prop_free(pin_function);
617         return (ret);
618 }
619
620 static int
621 a10_gpio_probe(device_t dev)
622 {
623
624         if (!ofw_bus_status_okay(dev))
625                 return (ENXIO);
626
627         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
628                 return (ENXIO);
629
630         device_set_desc(dev, "Allwinner GPIO/Pinmux controller");
631         return (BUS_PROBE_DEFAULT);
632 }
633
634 static int
635 a10_gpio_attach(device_t dev)
636 {
637         int rid, error;
638         phandle_t gpio;
639         struct a10_gpio_softc *sc;
640         clk_t clk;
641         hwreset_t rst;
642
643         sc = device_get_softc(dev);
644         sc->sc_dev = dev;
645
646         mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);
647
648         rid = 0;
649         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
650             RF_ACTIVE);
651         if (!sc->sc_mem_res) {
652                 device_printf(dev, "cannot allocate memory window\n");
653                 goto fail;
654         }
655
656         sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
657         sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
658
659         rid = 0;
660         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
661             RF_ACTIVE);
662         if (!sc->sc_irq_res) {
663                 device_printf(dev, "cannot allocate interrupt\n");
664                 goto fail;
665         }
666
667         /* Find our node. */
668         gpio = ofw_bus_get_node(sc->sc_dev);
669         if (!OF_hasprop(gpio, "gpio-controller"))
670                 /* Node is not a GPIO controller. */
671                 goto fail;
672
673         /* Use the right pin data for the current SoC */
674         sc->padconf = (struct allwinner_padconf *)ofw_bus_search_compatible(dev,
675             compat_data)->ocd_data;
676
677         if (hwreset_get_by_ofw_idx(dev, 0, 0, &rst) == 0) {
678                 error = hwreset_deassert(rst);
679                 if (error != 0) {
680                         device_printf(dev, "cannot de-assert reset\n");
681                         return (error);
682                 }
683         }
684
685         if (clk_get_by_ofw_index(dev, 0, 0, &clk) == 0) {
686                 error = clk_enable(clk);
687                 if (error != 0) {
688                         device_printf(dev, "could not enable clock\n");
689                         return (error);
690                 }
691         }
692
693         sc->sc_busdev = gpiobus_attach_bus(dev);
694         if (sc->sc_busdev == NULL)
695                 goto fail;
696
697         /*
698          * Register as a pinctrl device
699          */
700         fdt_pinctrl_register(dev, "allwinner,pins");
701         fdt_pinctrl_configure_tree(dev);
702
703         return (0);
704
705 fail:
706         if (sc->sc_irq_res)
707                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
708         if (sc->sc_mem_res)
709                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
710         mtx_destroy(&sc->sc_mtx);
711
712         return (ENXIO);
713 }
714
715 static int
716 a10_gpio_detach(device_t dev)
717 {
718
719         return (EBUSY);
720 }
721
722 static phandle_t
723 a10_gpio_get_node(device_t dev, device_t bus)
724 {
725
726         /* We only have one child, the GPIO bus, which needs our own node. */
727         return (ofw_bus_get_node(dev));
728 }
729
730 static int
731 a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
732     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
733 {
734         struct a10_gpio_softc *sc;
735         int i;
736
737         sc = device_get_softc(bus);
738
739         /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
740         for (i = 0; i < sc->padconf->npins; i++)
741                 if (sc->padconf->pins[i].port == gpios[0] &&
742                     sc->padconf->pins[i].pin == gpios[1]) {
743                         *pin = i;
744                         break;
745                 }
746         *flags = gpios[gcells - 1];
747
748         return (0);
749 }
750
751 static device_method_t a10_gpio_methods[] = {
752         /* Device interface */
753         DEVMETHOD(device_probe,         a10_gpio_probe),
754         DEVMETHOD(device_attach,        a10_gpio_attach),
755         DEVMETHOD(device_detach,        a10_gpio_detach),
756
757         /* GPIO protocol */
758         DEVMETHOD(gpio_get_bus,         a10_gpio_get_bus),
759         DEVMETHOD(gpio_pin_max,         a10_gpio_pin_max),
760         DEVMETHOD(gpio_pin_getname,     a10_gpio_pin_getname),
761         DEVMETHOD(gpio_pin_getflags,    a10_gpio_pin_getflags),
762         DEVMETHOD(gpio_pin_getcaps,     a10_gpio_pin_getcaps),
763         DEVMETHOD(gpio_pin_setflags,    a10_gpio_pin_setflags),
764         DEVMETHOD(gpio_pin_get,         a10_gpio_pin_get),
765         DEVMETHOD(gpio_pin_set,         a10_gpio_pin_set),
766         DEVMETHOD(gpio_pin_toggle,      a10_gpio_pin_toggle),
767         DEVMETHOD(gpio_map_gpios,       a10_gpio_map_gpios),
768
769         /* ofw_bus interface */
770         DEVMETHOD(ofw_bus_get_node,     a10_gpio_get_node),
771
772         /* fdt_pinctrl interface */
773         DEVMETHOD(fdt_pinctrl_configure,aw_fdt_configure_pins),
774
775         DEVMETHOD_END
776 };
777
778 static devclass_t a10_gpio_devclass;
779
780 static driver_t a10_gpio_driver = {
781         "gpio",
782         a10_gpio_methods,
783         sizeof(struct a10_gpio_softc),
784 };
785
786 EARLY_DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0,
787     BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);