]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/allwinner/a10_gpio.c
Merge OpenSSL 1.0.2f.
[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/cpu.h>
45 #include <machine/cpufunc.h>
46 #include <machine/resource.h>
47 #include <machine/intr.h>
48
49 #include <dev/fdt/fdt_common.h>
50 #include <dev/gpio/gpiobusvar.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
53
54 #include "gpio_if.h"
55 #include "a10_gpio.h"
56
57 /*
58  * A10 have 9 banks of gpio.
59  * 32 pins per bank:
60  * PA0 - PA17 | PB0 - PB23 | PC0 - PC24
61  * PD0 - PD27 | PE0 - PE31 | PF0 - PF5
62  * PG0 - PG9 | PH0 - PH27 | PI0 - PI12
63  */
64
65 #define A10_GPIO_PINS           288
66 #define A10_GPIO_DEFAULT_CAPS   (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |     \
67     GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
68
69 #define A10_GPIO_NONE           0
70 #define A10_GPIO_PULLUP         1
71 #define A10_GPIO_PULLDOWN       2
72
73 #define A10_GPIO_INPUT          0
74 #define A10_GPIO_OUTPUT         1
75
76 struct a10_gpio_softc {
77         device_t                sc_dev;
78         device_t                sc_busdev;
79         struct mtx              sc_mtx;
80         struct resource *       sc_mem_res;
81         struct resource *       sc_irq_res;
82         bus_space_tag_t         sc_bst;
83         bus_space_handle_t      sc_bsh;
84         void *                  sc_intrhand;
85 };
86
87 #define A10_GPIO_LOCK(_sc)              mtx_lock_spin(&(_sc)->sc_mtx)
88 #define A10_GPIO_UNLOCK(_sc)            mtx_unlock_spin(&(_sc)->sc_mtx)
89 #define A10_GPIO_LOCK_ASSERT(_sc)       mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
90
91 #define A10_GPIO_GP_CFG(_bank, _idx)    0x00 + ((_bank) * 0x24) + ((_idx) << 2)
92 #define A10_GPIO_GP_DAT(_bank)          0x10 + ((_bank) * 0x24)
93 #define A10_GPIO_GP_DRV(_bank, _idx)    0x14 + ((_bank) * 0x24) + ((_idx) << 2)
94 #define A10_GPIO_GP_PUL(_bank, _idx)    0x1c + ((_bank) * 0x24) + ((_idx) << 2)
95
96 #define A10_GPIO_GP_INT_CFG0            0x200
97 #define A10_GPIO_GP_INT_CFG1            0x204
98 #define A10_GPIO_GP_INT_CFG2            0x208
99 #define A10_GPIO_GP_INT_CFG3            0x20c
100
101 #define A10_GPIO_GP_INT_CTL             0x210
102 #define A10_GPIO_GP_INT_STA             0x214
103 #define A10_GPIO_GP_INT_DEB             0x218
104
105 static struct a10_gpio_softc *a10_gpio_sc;
106
107 #define A10_GPIO_WRITE(_sc, _off, _val)         \
108     bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
109 #define A10_GPIO_READ(_sc, _off)                \
110     bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
111
112 static uint32_t
113 a10_gpio_get_function(struct a10_gpio_softc *sc, uint32_t pin)
114 {
115         uint32_t bank, func, offset;
116
117         /* Must be called with lock held. */
118         A10_GPIO_LOCK_ASSERT(sc);
119
120         bank = pin / 32;
121         pin = pin % 32;
122         offset = ((pin & 0x07) << 2);
123
124         func = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
125         switch ((func >> offset) & 0x7) {
126         case A10_GPIO_INPUT:
127                 return (GPIO_PIN_INPUT);
128         case A10_GPIO_OUTPUT:
129                 return (GPIO_PIN_OUTPUT);
130         }
131
132         return (0);
133 }
134
135 static void
136 a10_gpio_set_function(struct a10_gpio_softc *sc, uint32_t pin, uint32_t f)
137 {
138         uint32_t bank, data, offset;
139
140         /* Must be called with lock held. */
141         A10_GPIO_LOCK_ASSERT(sc);
142
143         bank = pin / 32;
144         pin = pin % 32;
145         offset = ((pin & 0x07) << 2);
146
147         data = A10_GPIO_READ(sc, A10_GPIO_GP_CFG(bank, pin >> 3));
148         data &= ~(7 << offset);
149         data |= (f << offset);
150         A10_GPIO_WRITE(sc, A10_GPIO_GP_CFG(bank, pin >> 3), data);
151 }
152
153 static uint32_t
154 a10_gpio_get_pud(struct a10_gpio_softc *sc, uint32_t pin)
155 {
156         uint32_t bank, offset, val;
157
158         /* Must be called with lock held. */
159         A10_GPIO_LOCK_ASSERT(sc);
160
161         bank = pin / 32;
162         pin = pin % 32;
163         offset = ((pin & 0x0f) << 1);
164
165         val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
166         switch ((val >> offset) & 0x3) {
167         case A10_GPIO_PULLDOWN:
168                 return (GPIO_PIN_PULLDOWN);
169         case A10_GPIO_PULLUP:
170                 return (GPIO_PIN_PULLUP);
171         }
172
173         return (0);
174 }
175
176 static void
177 a10_gpio_set_pud(struct a10_gpio_softc *sc, uint32_t pin, uint32_t state)
178 {
179         uint32_t bank, offset, val;
180
181         /* Must be called with lock held. */
182         A10_GPIO_LOCK_ASSERT(sc);
183
184         bank = pin / 32;
185         pin = pin % 32;
186         offset = ((pin & 0x0f) << 1);
187
188         val = A10_GPIO_READ(sc, A10_GPIO_GP_PUL(bank, pin >> 4));
189         val &= ~(0x03 << offset);
190         val |= (state << offset);
191         A10_GPIO_WRITE(sc, A10_GPIO_GP_PUL(bank, pin >> 4), val);
192 }
193
194 static void
195 a10_gpio_pin_configure(struct a10_gpio_softc *sc, uint32_t pin, uint32_t flags)
196 {
197
198         /* Must be called with lock held. */
199         A10_GPIO_LOCK_ASSERT(sc);
200
201         /* Manage input/output. */
202         if (flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
203                 if (flags & GPIO_PIN_OUTPUT)
204                         a10_gpio_set_function(sc, pin, A10_GPIO_OUTPUT);
205                 else
206                         a10_gpio_set_function(sc, pin, A10_GPIO_INPUT);
207         }
208
209         /* Manage Pull-up/pull-down. */
210         if (flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) {
211                 if (flags & GPIO_PIN_PULLUP)
212                         a10_gpio_set_pud(sc, pin, A10_GPIO_PULLUP);
213                 else
214                         a10_gpio_set_pud(sc, pin, A10_GPIO_PULLDOWN);
215         } else 
216                 a10_gpio_set_pud(sc, pin, A10_GPIO_NONE);
217 }
218
219 static device_t
220 a10_gpio_get_bus(device_t dev)
221 {
222         struct a10_gpio_softc *sc;
223
224         sc = device_get_softc(dev);
225
226         return (sc->sc_busdev);
227 }
228
229 static int
230 a10_gpio_pin_max(device_t dev, int *maxpin)
231 {
232
233         *maxpin = A10_GPIO_PINS - 1;
234         return (0);
235 }
236
237 static int
238 a10_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
239 {
240
241         if (pin >= A10_GPIO_PINS)
242                 return (EINVAL);
243
244         *caps = A10_GPIO_DEFAULT_CAPS;
245
246         return (0);
247 }
248
249 static int
250 a10_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
251 {
252         struct a10_gpio_softc *sc;
253
254         if (pin >= A10_GPIO_PINS)
255                 return (EINVAL);
256
257         sc = device_get_softc(dev);
258         A10_GPIO_LOCK(sc);
259         *flags = a10_gpio_get_function(sc, pin);
260         *flags |= a10_gpio_get_pud(sc, pin);
261         A10_GPIO_UNLOCK(sc);
262
263         return (0);
264 }
265
266 static int
267 a10_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
268 {
269         uint32_t bank;
270
271         if (pin >= A10_GPIO_PINS)
272                 return (EINVAL);
273
274         bank = pin / 32;
275         snprintf(name, GPIOMAXNAME - 1, "pin %d (P%c%d)",
276             pin, bank + 'A', pin % 32);
277         name[GPIOMAXNAME - 1] = '\0';
278
279         return (0);
280 }
281
282 static int
283 a10_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
284 {
285         struct a10_gpio_softc *sc;
286
287         if (pin >= A10_GPIO_PINS)
288                 return (EINVAL);
289
290         sc = device_get_softc(dev);
291         A10_GPIO_LOCK(sc);
292         a10_gpio_pin_configure(sc, pin, flags);
293         A10_GPIO_UNLOCK(sc);
294
295         return (0);
296 }
297
298 static int
299 a10_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
300 {
301         struct a10_gpio_softc *sc;
302         uint32_t bank, data;
303
304         if (pin >= A10_GPIO_PINS)
305                 return (EINVAL);
306
307         bank = pin / 32;
308         pin = pin % 32;
309
310         sc = device_get_softc(dev);
311         A10_GPIO_LOCK(sc);
312         data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
313         if (value)
314                 data |= (1 << pin);
315         else
316                 data &= ~(1 << pin);
317         A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
318         A10_GPIO_UNLOCK(sc);
319
320         return (0);
321 }
322
323 static int
324 a10_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
325 {
326         struct a10_gpio_softc *sc;
327         uint32_t bank, reg_data;
328
329         if (pin >= A10_GPIO_PINS)
330                 return (EINVAL);
331
332         bank = pin / 32;
333         pin = pin % 32;
334
335         sc = device_get_softc(dev);
336         A10_GPIO_LOCK(sc);
337         reg_data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
338         A10_GPIO_UNLOCK(sc);
339         *val = (reg_data & (1 << pin)) ? 1 : 0;
340
341         return (0);
342 }
343
344 static int
345 a10_gpio_pin_toggle(device_t dev, uint32_t pin)
346 {
347         struct a10_gpio_softc *sc;
348         uint32_t bank, data;
349
350         if (pin >= A10_GPIO_PINS)
351                 return (EINVAL);
352
353         bank = pin / 32;
354         pin = pin % 32;
355
356         sc = device_get_softc(dev);
357         A10_GPIO_LOCK(sc);
358         data = A10_GPIO_READ(sc, A10_GPIO_GP_DAT(bank));
359         if (data & (1 << pin))
360                 data &= ~(1 << pin);
361         else
362                 data |= (1 << pin);
363         A10_GPIO_WRITE(sc, A10_GPIO_GP_DAT(bank), data);
364         A10_GPIO_UNLOCK(sc);
365
366         return (0);
367 }
368
369 static int
370 a10_gpio_probe(device_t dev)
371 {
372
373         if (!ofw_bus_status_okay(dev))
374                 return (ENXIO);
375
376         if (!ofw_bus_is_compatible(dev, "allwinner,sun4i-gpio"))
377                 return (ENXIO);
378
379         device_set_desc(dev, "Allwinner GPIO controller");
380         return (BUS_PROBE_DEFAULT);
381 }
382
383 static int
384 a10_gpio_attach(device_t dev)
385 {
386         int rid;
387         phandle_t gpio;
388         struct a10_gpio_softc *sc;
389
390         sc = device_get_softc(dev);
391         sc->sc_dev = dev;
392
393         mtx_init(&sc->sc_mtx, "a10 gpio", "gpio", MTX_SPIN);
394
395         rid = 0;
396         sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
397             RF_ACTIVE);
398         if (!sc->sc_mem_res) {
399                 device_printf(dev, "cannot allocate memory window\n");
400                 goto fail;
401         }
402
403         sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
404         sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
405
406         rid = 0;
407         sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
408             RF_ACTIVE);
409         if (!sc->sc_irq_res) {
410                 device_printf(dev, "cannot allocate interrupt\n");
411                 goto fail;
412         }
413
414         /* Find our node. */
415         gpio = ofw_bus_get_node(sc->sc_dev);
416         if (!OF_hasprop(gpio, "gpio-controller"))
417                 /* Node is not a GPIO controller. */
418                 goto fail;
419
420         a10_gpio_sc = sc;
421         sc->sc_busdev = gpiobus_attach_bus(dev);
422         if (sc->sc_busdev == NULL)
423                 goto fail;
424
425         return (0);
426
427 fail:
428         if (sc->sc_irq_res)
429                 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
430         if (sc->sc_mem_res)
431                 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
432         mtx_destroy(&sc->sc_mtx);
433
434         return (ENXIO);
435 }
436
437 static int
438 a10_gpio_detach(device_t dev)
439 {
440
441         return (EBUSY);
442 }
443
444 static phandle_t
445 a10_gpio_get_node(device_t dev, device_t bus)
446 {
447
448         /* We only have one child, the GPIO bus, which needs our own node. */
449         return (ofw_bus_get_node(dev));
450 }
451
452 static int
453 a10_gpio_map_gpios(device_t bus, phandle_t dev, phandle_t gparent, int gcells,
454     pcell_t *gpios, uint32_t *pin, uint32_t *flags)
455 {
456
457         /* The GPIO pins are mapped as: <gpio-phandle bank pin flags>. */
458         *pin = gpios[0] * 32 + gpios[1];
459         *flags = gpios[gcells - 1];
460
461         return (0);
462 }
463
464 static device_method_t a10_gpio_methods[] = {
465         /* Device interface */
466         DEVMETHOD(device_probe,         a10_gpio_probe),
467         DEVMETHOD(device_attach,        a10_gpio_attach),
468         DEVMETHOD(device_detach,        a10_gpio_detach),
469
470         /* GPIO protocol */
471         DEVMETHOD(gpio_get_bus,         a10_gpio_get_bus),
472         DEVMETHOD(gpio_pin_max,         a10_gpio_pin_max),
473         DEVMETHOD(gpio_pin_getname,     a10_gpio_pin_getname),
474         DEVMETHOD(gpio_pin_getflags,    a10_gpio_pin_getflags),
475         DEVMETHOD(gpio_pin_getcaps,     a10_gpio_pin_getcaps),
476         DEVMETHOD(gpio_pin_setflags,    a10_gpio_pin_setflags),
477         DEVMETHOD(gpio_pin_get,         a10_gpio_pin_get),
478         DEVMETHOD(gpio_pin_set,         a10_gpio_pin_set),
479         DEVMETHOD(gpio_pin_toggle,      a10_gpio_pin_toggle),
480         DEVMETHOD(gpio_map_gpios,       a10_gpio_map_gpios),
481
482         /* ofw_bus interface */
483         DEVMETHOD(ofw_bus_get_node,     a10_gpio_get_node),
484
485         DEVMETHOD_END
486 };
487
488 static devclass_t a10_gpio_devclass;
489
490 static driver_t a10_gpio_driver = {
491         "gpio",
492         a10_gpio_methods,
493         sizeof(struct a10_gpio_softc),
494 };
495
496 DRIVER_MODULE(a10_gpio, simplebus, a10_gpio_driver, a10_gpio_devclass, 0, 0);
497
498 int
499 a10_gpio_ethernet_activate(uint32_t func)
500 {
501         int i;
502         struct a10_gpio_softc *sc = a10_gpio_sc;
503
504         if (sc == NULL)
505                 return (ENXIO);
506
507         /* Configure pin mux settings for MII. */
508         A10_GPIO_LOCK(sc);
509         for (i = 0; i <= 17; i++)
510                 a10_gpio_set_function(sc, i, func);
511         A10_GPIO_UNLOCK(sc);
512
513         return (0);
514 }