]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/arm/freescale/imx/imx_gpio.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / arm / freescale / imx / imx_gpio.c
1 /*-
2  * Copyright (c) 2012, 2013 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Oleksandr Rybalko under sponsorship
6  * from the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1.   Redistributions of source code must retain the above copyright
12  *      notice, this list of conditions and the following disclaimer.
13  * 2.   Redistributions in binary form must reproduce the above copyright
14  *      notice, this list of conditions and the following disclaimer in the
15  *      documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 /*
31  * Freescale i.MX515 GPIO driver.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/bus.h>
40
41 #include <sys/kernel.h>
42 #include <sys/module.h>
43 #include <sys/rman.h>
44 #include <sys/lock.h>
45 #include <sys/mutex.h>
46 #include <sys/gpio.h>
47
48 #include <machine/bus.h>
49 #include <machine/resource.h>
50
51 #include <dev/fdt/fdt_common.h>
52 #include <dev/ofw/openfirm.h>
53 #include <dev/ofw/ofw_bus.h>
54 #include <dev/ofw/ofw_bus_subr.h>
55
56 #include "gpio_if.h"
57
58 #define GPIO_LOCK(_sc)          mtx_lock(&(_sc)->sc_mtx)
59 #define GPIO_UNLOCK(_sc)        mtx_unlock(&(_sc)->sc_mtx)
60 #define GPIO_LOCK_INIT(_sc)     mtx_init(&_sc->sc_mtx,                  \
61             device_get_nameunit(_sc->sc_dev), "imx_gpio", MTX_DEF)
62 #define GPIO_LOCK_DESTROY(_sc)  mtx_destroy(&_sc->sc_mtx);
63 #define GPIO_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
64 #define GPIO_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
65
66 #define WRITE4(_sc, _r, _v)                                             \
67             bus_space_write_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r), (_v))
68 #define READ4(_sc, _r)                                                  \
69             bus_space_read_4((_sc)->sc_iot, (_sc)->sc_ioh, (_r))
70 #define SET4(_sc, _r, _m)                                               \
71             WRITE4((_sc), (_r), READ4((_sc), (_r)) | (_m))
72 #define CLEAR4(_sc, _r, _m)                                             \
73             WRITE4((_sc), (_r), READ4((_sc), (_r)) & ~(_m))
74
75 /* Registers definition for Freescale i.MX515 GPIO controller */
76
77 #define IMX_GPIO_DR_REG         0x000 /* Pin Data */
78 #define IMX_GPIO_OE_REG         0x004 /* Set Pin Output */
79 #define IMX_GPIO_PSR_REG        0x008 /* Pad Status */
80 #define IMX_GPIO_ICR1_REG       0x00C /* Interrupt Configuration */
81 #define IMX_GPIO_ICR2_REG       0x010 /* Interrupt Configuration */
82 #define         GPIO_ICR_COND_LOW       0
83 #define         GPIO_ICR_COND_HIGH      1
84 #define         GPIO_ICR_COND_RISE      2
85 #define         GPIO_ICR_COND_FALL      3
86 #define IMX_GPIO_IMR_REG        0x014 /* Interrupt Mask Register */
87 #define IMX_GPIO_ISR_REG        0x018 /* Interrupt Status Register */
88 #define IMX_GPIO_EDGE_REG       0x01C /* Edge Detect Register */
89
90 #define DEFAULT_CAPS    (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
91 #define NGPIO           32
92
93 struct imx51_gpio_softc {
94         device_t                dev;
95         struct mtx              sc_mtx;
96         struct resource         *sc_res[11]; /* 1 x mem, 2 x IRQ, 8 x IRQ */
97         void                    *gpio_ih[11]; /* 1 ptr is not a big waste */
98         int                     sc_l_irq; /* Last irq resource */
99         bus_space_tag_t         sc_iot;
100         bus_space_handle_t      sc_ioh;
101         int                     gpio_npins;
102         struct gpio_pin         gpio_pins[NGPIO];
103 };
104
105 static struct ofw_compat_data compat_data[] = {
106         {"fsl,imx6q-gpio",  1},
107         {"fsl,imx53-gpio",  1},
108         {"fsl,imx51-gpio",  1},
109         {NULL,              0}
110 };
111
112 static struct resource_spec imx_gpio_spec[] = {
113         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
114         { SYS_RES_IRQ,          0,      RF_ACTIVE },
115         { SYS_RES_IRQ,          1,      RF_ACTIVE },
116         { -1, 0 }
117 };
118
119 static struct resource_spec imx_gpio0irq_spec[] = {
120         { SYS_RES_IRQ,          2,      RF_ACTIVE },
121         { SYS_RES_IRQ,          3,      RF_ACTIVE },
122         { SYS_RES_IRQ,          4,      RF_ACTIVE },
123         { SYS_RES_IRQ,          5,      RF_ACTIVE },
124         { SYS_RES_IRQ,          6,      RF_ACTIVE },
125         { SYS_RES_IRQ,          7,      RF_ACTIVE },
126         { SYS_RES_IRQ,          8,      RF_ACTIVE },
127         { SYS_RES_IRQ,          9,      RF_ACTIVE },
128         { -1, 0 }
129 };
130
131 /*
132  * Helpers
133  */
134 static void imx51_gpio_pin_configure(struct imx51_gpio_softc *,
135     struct gpio_pin *, uint32_t);
136
137 /*
138  * Driver stuff
139  */
140 static int imx51_gpio_probe(device_t);
141 static int imx51_gpio_attach(device_t);
142 static int imx51_gpio_detach(device_t);
143 static int imx51_gpio_intr(void *);
144
145 /*
146  * GPIO interface
147  */
148 static int imx51_gpio_pin_max(device_t, int *);
149 static int imx51_gpio_pin_getcaps(device_t, uint32_t, uint32_t *);
150 static int imx51_gpio_pin_getflags(device_t, uint32_t, uint32_t *);
151 static int imx51_gpio_pin_getname(device_t, uint32_t, char *);
152 static int imx51_gpio_pin_setflags(device_t, uint32_t, uint32_t);
153 static int imx51_gpio_pin_set(device_t, uint32_t, unsigned int);
154 static int imx51_gpio_pin_get(device_t, uint32_t, unsigned int *);
155 static int imx51_gpio_pin_toggle(device_t, uint32_t pin);
156
157 static void
158 imx51_gpio_pin_configure(struct imx51_gpio_softc *sc, struct gpio_pin *pin,
159     unsigned int flags)
160 {
161
162         GPIO_LOCK(sc);
163
164         /*
165          * Manage input/output
166          */
167         if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
168                 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
169                 if (flags & GPIO_PIN_OUTPUT) {
170                         pin->gp_flags |= GPIO_PIN_OUTPUT;
171                         SET4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin));
172                 }
173                 else {
174                         pin->gp_flags |= GPIO_PIN_INPUT;
175                         CLEAR4(sc, IMX_GPIO_OE_REG, (1 << pin->gp_pin));
176                 }
177         }
178
179         GPIO_UNLOCK(sc);
180 }
181
182 static int
183 imx51_gpio_pin_max(device_t dev, int *maxpin)
184 {
185
186         *maxpin = NGPIO - 1;
187         return (0);
188 }
189
190 static int
191 imx51_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
192 {
193         struct imx51_gpio_softc *sc;
194         int i;
195
196         sc = device_get_softc(dev);
197         for (i = 0; i < sc->gpio_npins; i++) {
198                 if (sc->gpio_pins[i].gp_pin == pin)
199                         break;
200         }
201
202         if (i >= sc->gpio_npins)
203                 return (EINVAL);
204
205         GPIO_LOCK(sc);
206         *caps = sc->gpio_pins[i].gp_caps;
207         GPIO_UNLOCK(sc);
208
209         return (0);
210 }
211
212 static int
213 imx51_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
214 {
215         struct imx51_gpio_softc *sc;
216         int i;
217
218         sc = device_get_softc(dev);
219         for (i = 0; i < sc->gpio_npins; i++) {
220                 if (sc->gpio_pins[i].gp_pin == pin)
221                         break;
222         }
223
224         if (i >= sc->gpio_npins)
225                 return (EINVAL);
226
227         GPIO_LOCK(sc);
228         *flags = sc->gpio_pins[i].gp_flags;
229         GPIO_UNLOCK(sc);
230
231         return (0);
232 }
233
234 static int
235 imx51_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
236 {
237         struct imx51_gpio_softc *sc;
238         int i;
239
240         sc = device_get_softc(dev);
241         for (i = 0; i < sc->gpio_npins; i++) {
242                 if (sc->gpio_pins[i].gp_pin == pin)
243                         break;
244         }
245
246         if (i >= sc->gpio_npins)
247                 return (EINVAL);
248
249         GPIO_LOCK(sc);
250         memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME);
251         GPIO_UNLOCK(sc);
252
253         return (0);
254 }
255
256 static int
257 imx51_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
258 {
259         struct imx51_gpio_softc *sc;
260         int i;
261
262         sc = device_get_softc(dev);
263         for (i = 0; i < sc->gpio_npins; i++) {
264                 if (sc->gpio_pins[i].gp_pin == pin)
265                         break;
266         }
267
268         if (i >= sc->gpio_npins)
269                 return (EINVAL);
270
271         imx51_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
272
273         return (0);
274 }
275
276 static int
277 imx51_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
278 {
279         struct imx51_gpio_softc *sc;
280         int i;
281
282         sc = device_get_softc(dev);
283         for (i = 0; i < sc->gpio_npins; i++) {
284                 if (sc->gpio_pins[i].gp_pin == pin)
285                         break;
286         }
287
288         if (i >= sc->gpio_npins)
289                 return (EINVAL);
290
291         GPIO_LOCK(sc);
292         if (value)
293                 SET4(sc, IMX_GPIO_DR_REG, (1 << i));
294         else
295                 CLEAR4(sc, IMX_GPIO_DR_REG, (1 << i));
296         GPIO_UNLOCK(sc);
297
298         return (0);
299 }
300
301 static int
302 imx51_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
303 {
304         struct imx51_gpio_softc *sc;
305         int i;
306
307         sc = device_get_softc(dev);
308         for (i = 0; i < sc->gpio_npins; i++) {
309                 if (sc->gpio_pins[i].gp_pin == pin)
310                         break;
311         }
312
313         if (i >= sc->gpio_npins)
314                 return (EINVAL);
315
316         GPIO_LOCK(sc);
317         *val = (READ4(sc, IMX_GPIO_DR_REG) >> i) & 1;
318         GPIO_UNLOCK(sc);
319
320         return (0);
321 }
322
323 static int
324 imx51_gpio_pin_toggle(device_t dev, uint32_t pin)
325 {
326         struct imx51_gpio_softc *sc;
327         int i;
328
329         sc = device_get_softc(dev);
330         for (i = 0; i < sc->gpio_npins; i++) {
331                 if (sc->gpio_pins[i].gp_pin == pin)
332                         break;
333         }
334
335         if (i >= sc->gpio_npins)
336                 return (EINVAL);
337
338         GPIO_LOCK(sc);
339         WRITE4(sc, IMX_GPIO_DR_REG,
340             (READ4(sc, IMX_GPIO_DR_REG) ^ (1 << i)));
341         GPIO_UNLOCK(sc);
342
343         return (0);
344 }
345
346 static int
347 imx51_gpio_intr(void *arg)
348 {
349         struct imx51_gpio_softc *sc;
350         uint32_t input, value;
351
352         sc = arg;
353         input = READ4(sc, IMX_GPIO_ISR_REG);
354         value = input & READ4(sc, IMX_GPIO_IMR_REG);
355         WRITE4(sc, IMX_GPIO_ISR_REG, input);
356
357         if (!value)
358                 goto intr_done;
359
360         /* TODO: interrupt handling */
361
362 intr_done:
363         return (FILTER_HANDLED);
364 }
365
366 static int
367 imx51_gpio_probe(device_t dev)
368 {
369
370         if (!ofw_bus_status_okay(dev))
371                 return (ENXIO);
372
373         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
374                 device_set_desc(dev, "Freescale i.MX GPIO Controller");
375                 return (BUS_PROBE_DEFAULT);
376         }
377
378         return (ENXIO);
379 }
380
381 static int
382 imx51_gpio_attach(device_t dev)
383 {
384         struct imx51_gpio_softc *sc;
385         int i, irq;
386
387         sc = device_get_softc(dev);
388         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
389
390         if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) {
391                 device_printf(dev, "could not allocate resources\n");
392                 return (ENXIO);
393         }
394
395         sc->dev = dev;
396         sc->gpio_npins = NGPIO;
397         sc->sc_l_irq = 2;
398         sc->sc_iot = rman_get_bustag(sc->sc_res[0]);
399         sc->sc_ioh = rman_get_bushandle(sc->sc_res[0]);
400
401         if (bus_alloc_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]) == 0) {
402                 /*
403                  * First GPIO unit able to serve +8 interrupts for 8 first
404                  * pins.
405                  */
406                 sc->sc_l_irq = 10;
407         }
408
409         for (irq = 1; irq <= sc->sc_l_irq; irq ++) {
410                 if ((bus_setup_intr(dev, sc->sc_res[irq], INTR_TYPE_MISC,
411                     imx51_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) {
412                         device_printf(dev,
413                             "WARNING: unable to register interrupt handler\n");
414                         return (ENXIO);
415                 }
416         }
417
418         for (i = 0; i < sc->gpio_npins; i++) {
419                 sc->gpio_pins[i].gp_pin = i;
420                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
421                 sc->gpio_pins[i].gp_flags =
422                     (READ4(sc, IMX_GPIO_OE_REG) & (1 << i)) ? GPIO_PIN_OUTPUT:
423                     GPIO_PIN_INPUT;
424                 snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
425                     "imx_gpio%d.%d", device_get_unit(dev), i);
426         }
427
428         device_add_child(dev, "gpioc", -1);
429         device_add_child(dev, "gpiobus", -1);
430
431         return (bus_generic_attach(dev));
432 }
433
434 static int
435 imx51_gpio_detach(device_t dev)
436 {
437         struct imx51_gpio_softc *sc;
438
439         sc = device_get_softc(dev);
440
441         KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
442
443         bus_generic_detach(dev);
444
445         if (sc->sc_res[3])
446                 bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]);
447
448         if (sc->sc_res[0])
449                 bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
450
451         mtx_destroy(&sc->sc_mtx);
452
453         return(0);
454 }
455
456 static device_method_t imx51_gpio_methods[] = {
457         DEVMETHOD(device_probe,         imx51_gpio_probe),
458         DEVMETHOD(device_attach,        imx51_gpio_attach),
459         DEVMETHOD(device_detach,        imx51_gpio_detach),
460
461         /* GPIO protocol */
462         DEVMETHOD(gpio_pin_max,         imx51_gpio_pin_max),
463         DEVMETHOD(gpio_pin_getname,     imx51_gpio_pin_getname),
464         DEVMETHOD(gpio_pin_getflags,    imx51_gpio_pin_getflags),
465         DEVMETHOD(gpio_pin_getcaps,     imx51_gpio_pin_getcaps),
466         DEVMETHOD(gpio_pin_setflags,    imx51_gpio_pin_setflags),
467         DEVMETHOD(gpio_pin_get,         imx51_gpio_pin_get),
468         DEVMETHOD(gpio_pin_set,         imx51_gpio_pin_set),
469         DEVMETHOD(gpio_pin_toggle,      imx51_gpio_pin_toggle),
470         {0, 0},
471 };
472
473 static driver_t imx51_gpio_driver = {
474         "gpio",
475         imx51_gpio_methods,
476         sizeof(struct imx51_gpio_softc),
477 };
478 static devclass_t imx51_gpio_devclass;
479
480 DRIVER_MODULE(imx51_gpio, simplebus, imx51_gpio_driver, imx51_gpio_devclass,
481     0, 0);