]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/freescale/imx/imx_gpio.c
Rename gpio driver file.
[FreeBSD/FreeBSD.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         /* Check for unwanted flags. */
272         if ((flags & sc->gpio_pins[i].gp_caps) != flags)
273                 return (EINVAL);
274
275         /* Can't mix input/output together */
276         if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
277             (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
278                 return (EINVAL);
279
280         imx51_gpio_pin_configure(sc, &sc->gpio_pins[i], flags);
281
282
283         return (0);
284 }
285
286 static int
287 imx51_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
288 {
289         struct imx51_gpio_softc *sc;
290         int i;
291
292         sc = device_get_softc(dev);
293         for (i = 0; i < sc->gpio_npins; i++) {
294                 if (sc->gpio_pins[i].gp_pin == pin)
295                         break;
296         }
297
298         if (i >= sc->gpio_npins)
299                 return (EINVAL);
300
301         GPIO_LOCK(sc);
302         if (value)
303                 SET4(sc, IMX_GPIO_DR_REG, (1 << i));
304         else
305                 CLEAR4(sc, IMX_GPIO_DR_REG, (1 << i));
306         GPIO_UNLOCK(sc);
307
308         return (0);
309 }
310
311 static int
312 imx51_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
313 {
314         struct imx51_gpio_softc *sc;
315         int i;
316
317         sc = device_get_softc(dev);
318         for (i = 0; i < sc->gpio_npins; i++) {
319                 if (sc->gpio_pins[i].gp_pin == pin)
320                         break;
321         }
322
323         if (i >= sc->gpio_npins)
324                 return (EINVAL);
325
326         GPIO_LOCK(sc);
327         *val = (READ4(sc, IMX_GPIO_DR_REG) >> i) & 1;
328         GPIO_UNLOCK(sc);
329
330         return (0);
331 }
332
333 static int
334 imx51_gpio_pin_toggle(device_t dev, uint32_t pin)
335 {
336         struct imx51_gpio_softc *sc;
337         int i;
338
339         sc = device_get_softc(dev);
340         for (i = 0; i < sc->gpio_npins; i++) {
341                 if (sc->gpio_pins[i].gp_pin == pin)
342                         break;
343         }
344
345         if (i >= sc->gpio_npins)
346                 return (EINVAL);
347
348         GPIO_LOCK(sc);
349         WRITE4(sc, IMX_GPIO_DR_REG,
350             (READ4(sc, IMX_GPIO_DR_REG) ^ (1 << i)));
351         GPIO_UNLOCK(sc);
352
353         return (0);
354 }
355
356 static int
357 imx51_gpio_intr(void *arg)
358 {
359         struct imx51_gpio_softc *sc;
360         uint32_t input, value;
361
362         sc = arg;
363         input = READ4(sc, IMX_GPIO_ISR_REG);
364         value = input & READ4(sc, IMX_GPIO_IMR_REG);
365         WRITE4(sc, IMX_GPIO_ISR_REG, input);
366
367         if (!value)
368                 goto intr_done;
369
370         /* TODO: interrupt handling */
371
372 intr_done:
373         return (FILTER_HANDLED);
374 }
375
376 static int
377 imx51_gpio_probe(device_t dev)
378 {
379
380         if (!ofw_bus_status_okay(dev))
381                 return (ENXIO);
382
383         if (ofw_bus_search_compatible(dev, compat_data)->ocd_data != 0) {
384                 device_set_desc(dev, "Freescale i.MX GPIO Controller");
385                 return (BUS_PROBE_DEFAULT);
386         }
387
388         return (ENXIO);
389 }
390
391 static int
392 imx51_gpio_attach(device_t dev)
393 {
394         struct imx51_gpio_softc *sc;
395         int i, irq;
396
397         sc = device_get_softc(dev);
398         mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);
399
400         if (bus_alloc_resources(dev, imx_gpio_spec, sc->sc_res)) {
401                 device_printf(dev, "could not allocate resources\n");
402                 return (ENXIO);
403         }
404
405         sc->dev = dev;
406         sc->gpio_npins = NGPIO;
407         sc->sc_l_irq = 2;
408         sc->sc_iot = rman_get_bustag(sc->sc_res[0]);
409         sc->sc_ioh = rman_get_bushandle(sc->sc_res[0]);
410
411         if (bus_alloc_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]) == 0) {
412                 /*
413                  * First GPIO unit able to serve +8 interrupts for 8 first
414                  * pins.
415                  */
416                 sc->sc_l_irq = 10;
417         }
418
419         for (irq = 1; irq <= sc->sc_l_irq; irq ++) {
420                 if ((bus_setup_intr(dev, sc->sc_res[irq], INTR_TYPE_MISC,
421                     imx51_gpio_intr, NULL, sc, &sc->gpio_ih[irq]))) {
422                         device_printf(dev,
423                             "WARNING: unable to register interrupt handler\n");
424                         return (ENXIO);
425                 }
426         }
427
428         for (i = 0; i < sc->gpio_npins; i++) {
429                 sc->gpio_pins[i].gp_pin = i;
430                 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
431                 sc->gpio_pins[i].gp_flags =
432                     (READ4(sc, IMX_GPIO_OE_REG) & (1 << i)) ? GPIO_PIN_OUTPUT:
433                     GPIO_PIN_INPUT;
434                 snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
435                     "imx_gpio%d.%d", device_get_unit(dev), i);
436         }
437
438         device_add_child(dev, "gpioc", device_get_unit(dev));
439         device_add_child(dev, "gpiobus", device_get_unit(dev));
440
441         return (bus_generic_attach(dev));
442 }
443
444 static int
445 imx51_gpio_detach(device_t dev)
446 {
447         struct imx51_gpio_softc *sc;
448
449         sc = device_get_softc(dev);
450
451         KASSERT(mtx_initialized(&sc->sc_mtx), ("gpio mutex not initialized"));
452
453         bus_generic_detach(dev);
454
455         if (sc->sc_res[3])
456                 bus_release_resources(dev, imx_gpio0irq_spec, &sc->sc_res[3]);
457
458         if (sc->sc_res[0])
459                 bus_release_resources(dev, imx_gpio_spec, sc->sc_res);
460
461         mtx_destroy(&sc->sc_mtx);
462
463         return(0);
464 }
465
466 static device_method_t imx51_gpio_methods[] = {
467         DEVMETHOD(device_probe,         imx51_gpio_probe),
468         DEVMETHOD(device_attach,        imx51_gpio_attach),
469         DEVMETHOD(device_detach,        imx51_gpio_detach),
470
471         /* GPIO protocol */
472         DEVMETHOD(gpio_pin_max,         imx51_gpio_pin_max),
473         DEVMETHOD(gpio_pin_getname,     imx51_gpio_pin_getname),
474         DEVMETHOD(gpio_pin_getflags,    imx51_gpio_pin_getflags),
475         DEVMETHOD(gpio_pin_getcaps,     imx51_gpio_pin_getcaps),
476         DEVMETHOD(gpio_pin_setflags,    imx51_gpio_pin_setflags),
477         DEVMETHOD(gpio_pin_get,         imx51_gpio_pin_get),
478         DEVMETHOD(gpio_pin_set,         imx51_gpio_pin_set),
479         DEVMETHOD(gpio_pin_toggle,      imx51_gpio_pin_toggle),
480         {0, 0},
481 };
482
483 static driver_t imx51_gpio_driver = {
484         "gpio",
485         imx51_gpio_methods,
486         sizeof(struct imx51_gpio_softc),
487 };
488 static devclass_t imx51_gpio_devclass;
489
490 DRIVER_MODULE(imx51_gpio, simplebus, imx51_gpio_driver, imx51_gpio_devclass,
491     0, 0);