2 * Copyright (c) 2011 Jakub Wojciech Klama <jceel@FreeBSD.org>
3 * Copyright (c) 2015 Hiroki Mori
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * GPIO on RT1310A consist of 2 ports:
31 * - PortA with 8 input/output pins
32 * - PortB with 4 input/output pins
34 * Pins are mapped to logical pin number as follows:
35 * [0..7] -> GPI_00..GPI_07 (port A)
36 * [8..11] -> GPI_08..GPI_11 (port B)
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
44 #include <sys/param.h>
45 #include <sys/systm.h>
49 #include <sys/endian.h>
50 #include <sys/kernel.h>
51 #include <sys/kthread.h>
53 #include <sys/malloc.h>
54 #include <sys/module.h>
55 #include <sys/mutex.h>
56 #include <sys/queue.h>
57 #include <sys/resource.h>
60 #include <sys/timetc.h>
61 #include <sys/watchdog.h>
64 #include <machine/bus.h>
65 #include <machine/cpu.h>
66 #include <machine/cpufunc.h>
67 #include <machine/resource.h>
68 #include <machine/intr.h>
69 #include <machine/fdt.h>
71 #include <dev/gpio/gpiobusvar.h>
72 #include <dev/ofw/ofw_bus.h>
73 #include <dev/ofw/ofw_bus_subr.h>
75 #include <arm/ralink/rt1310reg.h>
76 #include <arm/ralink/rt1310var.h>
80 struct rt1310_gpio_softc
84 struct resource * lg_res;
85 bus_space_tag_t lg_bst;
86 bus_space_handle_t lg_bsh;
89 struct rt1310_gpio_pinmap
98 static const struct rt1310_gpio_pinmap rt1310_gpio_pins[] = {
99 { 0, 8, RT_GPIO_PORTA, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
100 { 8, 4, RT_GPIO_PORTB, 0, GPIO_PIN_INPUT | GPIO_PIN_OUTPUT },
101 { -1, -1, -1, -1, -1 },
104 #define RT_GPIO_NPINS 12
106 #define RT_GPIO_PIN_IDX(_map, _idx) \
107 (_idx - _map->lp_start_idx)
109 #define RT_GPIO_PIN_BIT(_map, _idx) \
110 (_map->lp_start_bit + RT_GPIO_PIN_IDX(_map, _idx))
112 static int rt1310_gpio_probe(device_t);
113 static int rt1310_gpio_attach(device_t);
114 static int rt1310_gpio_detach(device_t);
116 static device_t rt1310_gpio_get_bus(device_t);
117 static int rt1310_gpio_pin_max(device_t, int *);
118 static int rt1310_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
119 static int rt1310_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
120 static int rt1310_gpio_pin_setflags(device_t, uint32_t, uint32_t);
121 static int rt1310_gpio_pin_getname(device_t, uint32_t, char *);
122 static int rt1310_gpio_pin_get(device_t, uint32_t, uint32_t *);
123 static int rt1310_gpio_pin_set(device_t, uint32_t, uint32_t);
124 static int rt1310_gpio_pin_toggle(device_t, uint32_t);
126 static const struct rt1310_gpio_pinmap *rt1310_gpio_get_pinmap(int);
128 static struct rt1310_gpio_softc *rt1310_gpio_sc = NULL;
130 #define rt1310_gpio_read_4(_sc, _reg) \
131 bus_space_read_4(_sc->lg_bst, _sc->lg_bsh, _reg)
132 #define rt1310_gpio_write_4(_sc, _reg, _val) \
133 bus_space_write_4(_sc->lg_bst, _sc->lg_bsh, _reg, _val)
136 rt1310_gpio_probe(device_t dev)
140 if (!ofw_bus_status_okay(dev))
143 if (!ofw_bus_is_compatible(dev, "ralink,rt1310-gpio"))
146 node = ofw_bus_get_node(dev);
147 if (!OF_hasprop(node, "gpio-controller"))
150 device_set_desc(dev, "RT1310 GPIO");
151 return (BUS_PROBE_DEFAULT);
155 rt1310_gpio_attach(device_t dev)
157 struct rt1310_gpio_softc *sc = device_get_softc(dev);
163 sc->lg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
166 device_printf(dev, "cannot allocate memory window\n");
170 sc->lg_bst = rman_get_bustag(sc->lg_res);
171 sc->lg_bsh = rman_get_bushandle(sc->lg_res);
175 sc->lg_busdev = gpiobus_attach_bus(dev);
176 if (sc->lg_busdev == NULL) {
177 bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->lg_res);
185 rt1310_gpio_detach(device_t dev)
191 rt1310_gpio_get_bus(device_t dev)
193 struct rt1310_gpio_softc *sc;
195 sc = device_get_softc(dev);
197 return (sc->lg_busdev);
201 rt1310_gpio_pin_max(device_t dev, int *npins)
203 *npins = RT_GPIO_NPINS - 1;
208 rt1310_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
210 const struct rt1310_gpio_pinmap *map;
212 if (pin > RT_GPIO_NPINS)
215 map = rt1310_gpio_get_pinmap(pin);
217 *caps = map->lp_flags;
222 rt1310_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
224 struct rt1310_gpio_softc *sc = device_get_softc(dev);
225 const struct rt1310_gpio_pinmap *map;
229 if (pin > RT_GPIO_NPINS)
232 map = rt1310_gpio_get_pinmap(pin);
234 /* Check whether it's bidirectional pin */
235 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
236 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) {
237 *flags = map->lp_flags;
241 switch (map->lp_port) {
243 state = rt1310_gpio_read_4(sc, RT_GPIO_OFF_PADIR);
244 dir = (state & (1 << RT_GPIO_PIN_BIT(map, pin)));
247 state = rt1310_gpio_read_4(sc, RT_GPIO_OFF_PBDIR);
248 dir = (state & (1 << RT_GPIO_PIN_BIT(map, pin)));
251 panic("unknown GPIO port");
254 *flags = dir ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
260 rt1310_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
262 struct rt1310_gpio_softc *sc = device_get_softc(dev);
263 const struct rt1310_gpio_pinmap *map;
267 if (pin > RT_GPIO_NPINS)
270 map = rt1310_gpio_get_pinmap(pin);
272 /* Check whether it's bidirectional pin */
273 if ((map->lp_flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)) !=
274 (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT))
277 if (flags & GPIO_PIN_INPUT)
280 if (flags & GPIO_PIN_OUTPUT)
283 switch (map->lp_port) {
285 port = RT_GPIO_OFF_PADIR;
288 port = RT_GPIO_OFF_PBDIR;
292 state = rt1310_gpio_read_4(sc, port);
293 if (flags & GPIO_PIN_INPUT) {
294 state &= ~(1 << RT_GPIO_PIN_IDX(map, pin));
296 state |= (1 << RT_GPIO_PIN_IDX(map, pin));
298 rt1310_gpio_write_4(sc, port, state);
304 rt1310_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
306 snprintf(name, GPIOMAXNAME - 1, "GPIO_%02d", pin);
312 rt1310_gpio_pin_get(device_t dev, uint32_t pin, uint32_t *value)
314 struct rt1310_gpio_softc *sc = device_get_softc(dev);
315 const struct rt1310_gpio_pinmap *map;
316 uint32_t state, flags;
319 map = rt1310_gpio_get_pinmap(pin);
321 if (rt1310_gpio_pin_getflags(dev, pin, &flags))
324 if (flags & GPIO_PIN_OUTPUT)
327 if (flags & GPIO_PIN_INPUT)
330 switch (map->lp_port) {
332 state = rt1310_gpio_read_4(sc, RT_GPIO_OFF_PADR);
333 *value = !!(state & (1 << RT_GPIO_PIN_BIT(map, pin)));
336 state = rt1310_gpio_read_4(sc, RT_GPIO_OFF_PBDR);
337 *value = !!(state & (1 << RT_GPIO_PIN_BIT(map, pin)));
345 rt1310_gpio_pin_set(device_t dev, uint32_t pin, uint32_t value)
347 struct rt1310_gpio_softc *sc = device_get_softc(dev);
348 const struct rt1310_gpio_pinmap *map;
349 uint32_t state, flags;
352 map = rt1310_gpio_get_pinmap(pin);
354 if (rt1310_gpio_pin_getflags(dev, pin, &flags))
357 if ((flags & GPIO_PIN_OUTPUT) == 0)
360 switch (map->lp_port) {
362 port = RT_GPIO_OFF_PADR;
365 port = RT_GPIO_OFF_PBDR;
369 state = rt1310_gpio_read_4(sc, port);
371 state |= (1 << RT_GPIO_PIN_BIT(map, pin));
373 state &= ~(1 << RT_GPIO_PIN_BIT(map, pin));
375 rt1310_gpio_write_4(sc, port, state);
381 rt1310_gpio_pin_toggle(device_t dev, uint32_t pin)
383 const struct rt1310_gpio_pinmap *map;
386 map = rt1310_gpio_get_pinmap(pin);
388 if (rt1310_gpio_pin_getflags(dev, pin, &flags))
391 if ((flags & GPIO_PIN_OUTPUT) == 0)
394 panic("not implemented yet");
400 static const struct rt1310_gpio_pinmap *
401 rt1310_gpio_get_pinmap(int pin)
403 const struct rt1310_gpio_pinmap *map;
405 for (map = &rt1310_gpio_pins[0]; map->lp_start_idx != -1; map++) {
406 if (pin >= map->lp_start_idx &&
407 pin < map->lp_start_idx + map->lp_pin_count)
411 panic("pin number %d out of range", pin);
415 rt1310_gpio_set_flags(device_t dev, int pin, int flags)
417 if (rt1310_gpio_sc == NULL)
420 return rt1310_gpio_pin_setflags(rt1310_gpio_sc->lg_dev, pin, flags);
424 rt1310_gpio_set_state(device_t dev, int pin, int state)
426 if (rt1310_gpio_sc == NULL)
429 return rt1310_gpio_pin_set(rt1310_gpio_sc->lg_dev, pin, state);
433 rt1310_gpio_get_state(device_t dev, int pin, int *state)
435 if (rt1310_gpio_sc == NULL)
438 return rt1310_gpio_pin_get(rt1310_gpio_sc->lg_dev, pin, state);
442 rt1310_gpio_get_node(device_t bus, device_t dev)
444 /* We only have one child, the GPIO bus, which needs our own node. */
445 return (ofw_bus_get_node(bus));
448 static device_method_t rt1310_gpio_methods[] = {
449 /* Device interface */
450 DEVMETHOD(device_probe, rt1310_gpio_probe),
451 DEVMETHOD(device_attach, rt1310_gpio_attach),
452 DEVMETHOD(device_detach, rt1310_gpio_detach),
455 DEVMETHOD(gpio_get_bus, rt1310_gpio_get_bus),
456 DEVMETHOD(gpio_pin_max, rt1310_gpio_pin_max),
457 DEVMETHOD(gpio_pin_getcaps, rt1310_gpio_pin_getcaps),
458 DEVMETHOD(gpio_pin_getflags, rt1310_gpio_pin_getflags),
459 DEVMETHOD(gpio_pin_setflags, rt1310_gpio_pin_setflags),
460 DEVMETHOD(gpio_pin_getname, rt1310_gpio_pin_getname),
461 DEVMETHOD(gpio_pin_set, rt1310_gpio_pin_set),
462 DEVMETHOD(gpio_pin_get, rt1310_gpio_pin_get),
463 DEVMETHOD(gpio_pin_toggle, rt1310_gpio_pin_toggle),
465 /* ofw_bus interface */
466 DEVMETHOD(ofw_bus_get_node, rt1310_gpio_get_node),
471 static devclass_t rt1310_gpio_devclass;
473 static driver_t rt1310_gpio_driver = {
476 sizeof(struct rt1310_gpio_softc),
479 DRIVER_MODULE(rt1310gpio, simplebus, rt1310_gpio_driver, rt1310_gpio_devclass, 0, 0);
480 MODULE_VERSION(rt1310gpio, 1);