]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/mv/gpio.c
MFV ntp 4.2.8p1 (r258945, r275970, r276091, r276092, r276093, r278284)
[FreeBSD/FreeBSD.git] / sys / arm / mv / gpio.c
1 /*-
2  * Copyright (c) 2006 Benno Rice.
3  * Copyright (C) 2008 MARVELL INTERNATIONAL LTD.
4  * All rights reserved.
5  *
6  * Adapted and extended for Marvell SoCs by Semihalf.
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 ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_gpio.c, rev 1
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/kernel.h>
38 #include <sys/lock.h>
39 #include <sys/interrupt.h>
40 #include <sys/module.h>
41 #include <sys/malloc.h>
42 #include <sys/mutex.h>
43 #include <sys/rman.h>
44 #include <sys/queue.h>
45 #include <sys/timetc.h>
46 #include <machine/bus.h>
47 #include <machine/fdt.h>
48 #include <machine/intr.h>
49
50 #include <dev/fdt/fdt_common.h>
51 #include <dev/ofw/ofw_bus.h>
52 #include <dev/ofw/ofw_bus_subr.h>
53
54 #include <arm/mv/mvvar.h>
55 #include <arm/mv/mvreg.h>
56
57 #define GPIO_MAX_INTR_COUNT     8
58 #define GPIO_PINS_PER_REG       32
59
60 struct mv_gpio_softc {
61         struct resource *       res[GPIO_MAX_INTR_COUNT + 1];
62         void                    *ih_cookie[GPIO_MAX_INTR_COUNT];
63         bus_space_tag_t         bst;
64         bus_space_handle_t      bsh;
65         uint8_t                 pin_num;        /* number of GPIO pins */
66         uint8_t                 irq_num;        /* number of real IRQs occupied by GPIO controller */
67 };
68
69 extern struct resource_spec mv_gpio_res[];
70
71 static struct mv_gpio_softc *mv_gpio_softc = NULL;
72 static uint32_t gpio_setup[MV_GPIO_MAX_NPINS];
73
74 static int      mv_gpio_probe(device_t);
75 static int      mv_gpio_attach(device_t);
76 static int      mv_gpio_intr(void *);
77 static int      mv_gpio_init(void);
78
79 static void     mv_gpio_intr_handler(int pin);
80 static uint32_t mv_gpio_reg_read(uint32_t reg);
81 static void     mv_gpio_reg_write(uint32_t reg, uint32_t val);
82 static void     mv_gpio_reg_set(uint32_t reg, uint32_t val);
83 static void     mv_gpio_reg_clear(uint32_t reg, uint32_t val);
84
85 static void     mv_gpio_blink(uint32_t pin, uint8_t enable);
86 static void     mv_gpio_polarity(uint32_t pin, uint8_t enable);
87 static void     mv_gpio_level(uint32_t pin, uint8_t enable);
88 static void     mv_gpio_edge(uint32_t pin, uint8_t enable);
89 static void     mv_gpio_out_en(uint32_t pin, uint8_t enable);
90 static void     mv_gpio_int_ack(uint32_t pin);
91 static void     mv_gpio_value_set(uint32_t pin, uint8_t val);
92 static uint32_t mv_gpio_value_get(uint32_t pin);
93
94 static device_method_t mv_gpio_methods[] = {
95         DEVMETHOD(device_probe,         mv_gpio_probe),
96         DEVMETHOD(device_attach,        mv_gpio_attach),
97         { 0, 0 }
98 };
99
100 static driver_t mv_gpio_driver = {
101         "gpio",
102         mv_gpio_methods,
103         sizeof(struct mv_gpio_softc),
104 };
105
106 static devclass_t mv_gpio_devclass;
107
108 DRIVER_MODULE(gpio, simplebus, mv_gpio_driver, mv_gpio_devclass, 0, 0);
109
110 typedef int (*gpios_phandler_t)(phandle_t, pcell_t *, int);
111
112 struct gpio_ctrl_entry {
113         const char              *compat;
114         gpios_phandler_t        handler;
115 };
116
117 int mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len);
118 int gpio_get_config_from_dt(void);
119
120 struct gpio_ctrl_entry gpio_controllers[] = {
121         { "mrvl,gpio", &mv_handle_gpios_prop },
122         { NULL, NULL }
123 };
124
125 static int
126 mv_gpio_probe(device_t dev)
127 {
128
129         if (!ofw_bus_status_okay(dev))
130                 return (ENXIO);
131
132         if (!ofw_bus_is_compatible(dev, "mrvl,gpio"))
133                 return (ENXIO);
134
135         device_set_desc(dev, "Marvell Integrated GPIO Controller");
136         return (0);
137 }
138
139 static int
140 mv_gpio_attach(device_t dev)
141 {
142         int error, i;
143         struct mv_gpio_softc *sc;
144         uint32_t dev_id, rev_id;
145
146         sc = (struct mv_gpio_softc *)device_get_softc(dev);
147         if (sc == NULL)
148                 return (ENXIO);
149
150         mv_gpio_softc = sc;
151
152         /* Get chip id and revision */
153         soc_id(&dev_id, &rev_id);
154
155         if (dev_id == MV_DEV_88F5182 ||
156             dev_id == MV_DEV_88F5281 ||
157             dev_id == MV_DEV_MV78100 ||
158             dev_id == MV_DEV_MV78100_Z0 ) {
159                 sc->pin_num = 32;
160                 sc->irq_num = 4;
161
162         } else if (dev_id == MV_DEV_88F6281 ||
163             dev_id == MV_DEV_88F6282) {
164                 sc->pin_num = 50;
165                 sc->irq_num = 7;
166
167         } else {
168                 device_printf(dev, "unknown chip id=0x%x\n", dev_id);
169                 return (ENXIO);
170         }
171
172         error = bus_alloc_resources(dev, mv_gpio_res, sc->res);
173         if (error) {
174                 device_printf(dev, "could not allocate resources\n");
175                 return (ENXIO);
176         }
177
178         sc->bst = rman_get_bustag(sc->res[0]);
179         sc->bsh = rman_get_bushandle(sc->res[0]);
180
181         /* Disable and clear all interrupts */
182         bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_EDGE_MASK, 0);
183         bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_LEV_MASK, 0);
184         bus_space_write_4(sc->bst, sc->bsh, GPIO_INT_CAUSE, 0);
185
186         if (sc->pin_num > GPIO_PINS_PER_REG) {
187                 bus_space_write_4(sc->bst, sc->bsh,
188                     GPIO_HI_INT_EDGE_MASK, 0);
189                 bus_space_write_4(sc->bst, sc->bsh,
190                     GPIO_HI_INT_LEV_MASK, 0);
191                 bus_space_write_4(sc->bst, sc->bsh,
192                     GPIO_HI_INT_CAUSE, 0);
193         }
194
195         for (i = 0; i < sc->irq_num; i++) {
196                 if (bus_setup_intr(dev, sc->res[1 + i],
197                     INTR_TYPE_MISC, mv_gpio_intr, NULL,
198                     sc, &sc->ih_cookie[i]) != 0) {
199                         bus_release_resources(dev, mv_gpio_res, sc->res);
200                         device_printf(dev, "could not set up intr %d\n", i);
201                         return (ENXIO);
202                 }
203         }
204
205         return (mv_gpio_init());
206 }
207
208 static int
209 mv_gpio_intr(void *arg)
210 {
211         uint32_t int_cause, gpio_val;
212         uint32_t int_cause_hi, gpio_val_hi = 0;
213         int i;
214
215         int_cause = mv_gpio_reg_read(GPIO_INT_CAUSE);
216         gpio_val = mv_gpio_reg_read(GPIO_DATA_IN);
217         gpio_val &= int_cause;
218         if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) {
219                 int_cause_hi = mv_gpio_reg_read(GPIO_HI_INT_CAUSE);
220                 gpio_val_hi = mv_gpio_reg_read(GPIO_HI_DATA_IN);
221                 gpio_val_hi &= int_cause_hi;
222         }
223
224         i = 0;
225         while (gpio_val != 0) {
226                 if (gpio_val & 1)
227                         mv_gpio_intr_handler(i);
228                 gpio_val >>= 1;
229                 i++;
230         }
231
232         if (mv_gpio_softc->pin_num > GPIO_PINS_PER_REG) {
233                 i = 0;
234                 while (gpio_val_hi != 0) {
235                         if (gpio_val_hi & 1)
236                                 mv_gpio_intr_handler(i + GPIO_PINS_PER_REG);
237                         gpio_val_hi >>= 1;
238                         i++;
239                 }
240         }
241
242         return (FILTER_HANDLED);
243 }
244
245 /*
246  * GPIO interrupt handling
247  */
248
249 static struct intr_event *gpio_events[MV_GPIO_MAX_NPINS];
250
251 int
252 mv_gpio_setup_intrhandler(const char *name, driver_filter_t *filt,
253     void (*hand)(void *), void *arg, int pin, int flags, void **cookiep)
254 {
255         struct  intr_event *event;
256         int     error;
257
258         if (pin < 0 || pin >= mv_gpio_softc->pin_num)
259                 return (ENXIO);
260         event = gpio_events[pin];
261         if (event == NULL) {
262                 error = intr_event_create(&event, (void *)pin, 0, pin,
263                     (void (*)(void *))mv_gpio_intr_mask,
264                     (void (*)(void *))mv_gpio_intr_unmask,
265                     (void (*)(void *))mv_gpio_int_ack,
266                     NULL,
267                     "gpio%d:", pin);
268                 if (error != 0)
269                         return (error);
270                 gpio_events[pin] = event;
271         }
272
273         intr_event_add_handler(event, name, filt, hand, arg,
274             intr_priority(flags), flags, cookiep);
275         return (0);
276 }
277
278 void
279 mv_gpio_intr_mask(int pin)
280 {
281
282         if (pin >= mv_gpio_softc->pin_num)
283                 return;
284
285         if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE)
286                 mv_gpio_edge(pin, 0);
287         else
288                 mv_gpio_level(pin, 0);
289 }
290
291 void
292 mv_gpio_intr_unmask(int pin)
293 {
294
295         if (pin >= mv_gpio_softc->pin_num)
296                 return;
297
298         if (gpio_setup[pin] & MV_GPIO_IN_IRQ_EDGE)
299                 mv_gpio_edge(pin, 1);
300         else
301                 mv_gpio_level(pin, 1);
302 }
303
304 static void
305 mv_gpio_intr_handler(int pin)
306 {
307         struct intr_event *event;
308
309         event = gpio_events[pin];
310         if (event == NULL || TAILQ_EMPTY(&event->ie_handlers))
311                 return;
312
313         intr_event_handle(event, NULL);
314 }
315
316 static int
317 mv_gpio_configure(uint32_t pin, uint32_t flags)
318 {
319
320         if (pin >= mv_gpio_softc->pin_num)
321                 return (EINVAL);
322
323         if (flags & MV_GPIO_OUT_BLINK)
324                 mv_gpio_blink(pin, 1);
325         if (flags & MV_GPIO_IN_POL_LOW)
326                 mv_gpio_polarity(pin, 1);
327         if (flags & MV_GPIO_IN_IRQ_EDGE)
328                 mv_gpio_edge(pin, 1);
329         if (flags & MV_GPIO_IN_IRQ_LEVEL)
330                 mv_gpio_level(pin, 1);
331
332         gpio_setup[pin] = flags;
333
334         return (0);
335 }
336
337 void
338 mv_gpio_out(uint32_t pin, uint8_t val, uint8_t enable)
339 {
340
341         mv_gpio_value_set(pin, val);
342         mv_gpio_out_en(pin, enable);
343 }
344
345 uint8_t
346 mv_gpio_in(uint32_t pin)
347 {
348
349         return (mv_gpio_value_get(pin) ? 1 : 0);
350 }
351
352 static uint32_t
353 mv_gpio_reg_read(uint32_t reg)
354 {
355
356         return (bus_space_read_4(mv_gpio_softc->bst,
357             mv_gpio_softc->bsh, reg));
358 }
359
360 static void
361 mv_gpio_reg_write(uint32_t reg, uint32_t val)
362 {
363
364         bus_space_write_4(mv_gpio_softc->bst,
365             mv_gpio_softc->bsh, reg, val);
366 }
367
368 static void
369 mv_gpio_reg_set(uint32_t reg, uint32_t pin)
370 {
371         uint32_t reg_val;
372
373         reg_val = mv_gpio_reg_read(reg);
374         reg_val |= GPIO(pin);
375         mv_gpio_reg_write(reg, reg_val);
376 }
377
378 static void
379 mv_gpio_reg_clear(uint32_t reg, uint32_t pin)
380 {
381         uint32_t reg_val;
382
383         reg_val = mv_gpio_reg_read(reg);
384         reg_val &= ~(GPIO(pin));
385         mv_gpio_reg_write(reg, reg_val);
386 }
387
388 static void
389 mv_gpio_out_en(uint32_t pin, uint8_t enable)
390 {
391         uint32_t reg;
392
393         if (pin >= mv_gpio_softc->pin_num)
394                 return;
395
396         if (pin >= GPIO_PINS_PER_REG) {
397                 reg = GPIO_HI_DATA_OUT_EN_CTRL;
398                 pin -= GPIO_PINS_PER_REG;
399         } else
400                 reg = GPIO_DATA_OUT_EN_CTRL;
401
402         if (enable)
403                 mv_gpio_reg_clear(reg, pin);
404         else
405                 mv_gpio_reg_set(reg, pin);
406 }
407
408 static void
409 mv_gpio_blink(uint32_t pin, uint8_t enable)
410 {
411         uint32_t reg;
412
413         if (pin >= mv_gpio_softc->pin_num)
414                 return;
415
416         if (pin >= GPIO_PINS_PER_REG) {
417                 reg = GPIO_HI_BLINK_EN;
418                 pin -= GPIO_PINS_PER_REG;
419         } else
420                 reg = GPIO_BLINK_EN;
421
422         if (enable)
423                 mv_gpio_reg_set(reg, pin);
424         else
425                 mv_gpio_reg_clear(reg, pin);
426 }
427
428 static void
429 mv_gpio_polarity(uint32_t pin, uint8_t enable)
430 {
431         uint32_t reg;
432
433         if (pin >= mv_gpio_softc->pin_num)
434                 return;
435
436         if (pin >= GPIO_PINS_PER_REG) {
437                 reg = GPIO_HI_DATA_IN_POLAR;
438                 pin -= GPIO_PINS_PER_REG;
439         } else
440                 reg = GPIO_DATA_IN_POLAR;
441
442         if (enable)
443                 mv_gpio_reg_set(reg, pin);
444         else
445                 mv_gpio_reg_clear(reg, pin);
446 }
447
448 static void
449 mv_gpio_level(uint32_t pin, uint8_t enable)
450 {
451         uint32_t reg;
452
453         if (pin >= mv_gpio_softc->pin_num)
454                 return;
455
456         if (pin >= GPIO_PINS_PER_REG) {
457                 reg = GPIO_HI_INT_LEV_MASK;
458                 pin -= GPIO_PINS_PER_REG;
459         } else
460                 reg = GPIO_INT_LEV_MASK;
461
462         if (enable)
463                 mv_gpio_reg_set(reg, pin);
464         else
465                 mv_gpio_reg_clear(reg, pin);
466 }
467
468 static void
469 mv_gpio_edge(uint32_t pin, uint8_t enable)
470 {
471         uint32_t reg;
472
473         if (pin >= mv_gpio_softc->pin_num)
474                 return;
475
476         if (pin >= GPIO_PINS_PER_REG) {
477                 reg = GPIO_HI_INT_EDGE_MASK;
478                 pin -= GPIO_PINS_PER_REG;
479         } else
480                 reg = GPIO_INT_EDGE_MASK;
481
482         if (enable)
483                 mv_gpio_reg_set(reg, pin);
484         else
485                 mv_gpio_reg_clear(reg, pin);
486 }
487
488 static void
489 mv_gpio_int_ack(uint32_t pin)
490 {
491         uint32_t reg;
492
493         if (pin >= mv_gpio_softc->pin_num)
494                 return;
495
496         if (pin >= GPIO_PINS_PER_REG) {
497                 reg = GPIO_HI_INT_CAUSE;
498                 pin -= GPIO_PINS_PER_REG;
499         } else
500                 reg = GPIO_INT_CAUSE;
501
502         mv_gpio_reg_clear(reg, pin);
503 }
504
505 static uint32_t
506 mv_gpio_value_get(uint32_t pin)
507 {
508         uint32_t reg, reg_val;
509
510         if (pin >= mv_gpio_softc->pin_num)
511                 return (0);
512
513         if (pin >= GPIO_PINS_PER_REG) {
514                 reg = GPIO_HI_DATA_IN;
515                 pin -= GPIO_PINS_PER_REG;
516         } else
517                 reg = GPIO_DATA_IN;
518
519         reg_val = mv_gpio_reg_read(reg);
520
521         return (reg_val & GPIO(pin));
522 }
523
524 static void
525 mv_gpio_value_set(uint32_t pin, uint8_t val)
526 {
527         uint32_t reg;
528
529         if (pin >= mv_gpio_softc->pin_num)
530                 return;
531
532         if (pin >= GPIO_PINS_PER_REG) {
533                 reg = GPIO_HI_DATA_OUT;
534                 pin -= GPIO_PINS_PER_REG;
535         } else
536                 reg = GPIO_DATA_OUT;
537
538         if (val)
539                 mv_gpio_reg_set(reg, pin);
540         else
541                 mv_gpio_reg_clear(reg, pin);
542 }
543
544 int
545 mv_handle_gpios_prop(phandle_t ctrl, pcell_t *gpios, int len)
546 {
547         pcell_t gpio_cells, pincnt;
548         int inc, t, tuples, tuple_size;
549         int dir, flags, pin;
550         u_long gpio_ctrl, size;
551         struct mv_gpio_softc sc;
552
553         pincnt = 0;
554         if (!OF_hasprop(ctrl, "gpio-controller"))
555                 /* Node is not a GPIO controller. */
556                 return (ENXIO);
557
558         if (OF_getprop(ctrl, "#gpio-cells", &gpio_cells, sizeof(pcell_t)) < 0)
559                 return (ENXIO);
560
561         gpio_cells = fdt32_to_cpu(gpio_cells);
562         if (gpio_cells != 3)
563                 return (ENXIO);
564
565         tuple_size = gpio_cells * sizeof(pcell_t) + sizeof(phandle_t);
566         tuples = len / tuple_size;
567
568         if (fdt_regsize(ctrl, &gpio_ctrl, &size))
569                 return (ENXIO);
570
571         if (OF_getprop(ctrl, "pin-count", &pincnt, sizeof(pcell_t)) < 0)
572                 return (ENXIO);
573         sc.pin_num = fdt32_to_cpu(pincnt);
574
575         /*
576          * Skip controller reference, since controller's phandle is given
577          * explicitly (in a function argument).
578          */
579         inc = sizeof(ihandle_t) / sizeof(pcell_t);
580         gpios += inc;
581
582         for (t = 0; t < tuples; t++) {
583                 pin = fdt32_to_cpu(gpios[0]);
584                 dir = fdt32_to_cpu(gpios[1]);
585                 flags = fdt32_to_cpu(gpios[2]);
586
587                 mv_gpio_configure(pin, flags);
588
589                 if (dir == 1)
590                         /* Input. */
591                         mv_gpio_out_en(pin, 0);
592                 else {
593                         /* Output. */
594                         if (flags & MV_GPIO_OUT_OPEN_DRAIN)
595                                 mv_gpio_out(pin, 0, 1);
596
597                         if (flags & MV_GPIO_OUT_OPEN_SRC)
598                                 mv_gpio_out(pin, 1, 1);
599                 }
600                 gpios += gpio_cells + inc;
601         }
602
603         return (0);
604 }
605
606 #define MAX_PINS_PER_NODE       5
607 #define GPIOS_PROP_CELLS        4
608 static int
609 mv_gpio_init(void)
610 {
611         phandle_t child, parent, root, ctrl;
612         pcell_t gpios[MAX_PINS_PER_NODE * GPIOS_PROP_CELLS];
613         struct gpio_ctrl_entry *e;
614         int len, rv;
615
616         root = OF_finddevice("/");
617         len = 0;
618         parent = root;
619
620         /* Traverse through entire tree to find nodes with 'gpios' prop */
621         for (child = OF_child(parent); child != 0; child = OF_peer(child)) {
622
623                 /* Find a 'leaf'. Start the search from this node. */
624                 while (OF_child(child)) {
625                         parent = child;
626                         child = OF_child(child);
627                 }
628                 if ((len = OF_getproplen(child, "gpios")) > 0) {
629
630                         if (len > sizeof(gpios))
631                                 return (ENXIO);
632
633                         /* Get 'gpios' property. */
634                         OF_getprop(child, "gpios", &gpios, len);
635
636                         e = (struct gpio_ctrl_entry *)&gpio_controllers;
637
638                         /* Find and call a handler. */
639                         for (; e->compat; e++) {
640                                 /*
641                                  * First cell of 'gpios' property should
642                                  * contain a ref. to a node defining GPIO
643                                  * controller.
644                                  */
645                                 ctrl = OF_node_from_xref(fdt32_to_cpu(gpios[0]));
646
647                                 if (fdt_is_compatible(ctrl, e->compat))
648                                         /* Call a handler. */
649                                         if ((rv = e->handler(ctrl,
650                                             (pcell_t *)&gpios, len)))
651                                                 return (rv);
652                         }
653                 }
654
655                 if (OF_peer(child) == 0) {
656                         /* No more siblings. */
657                         child = parent;
658                         parent = OF_parent(child);
659                 }
660         }
661         return (0);
662 }