]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/mips/ingenic/jz4780_gpio.c
Remove incomplete support for plain MD5 from OCF.
[FreeBSD/FreeBSD.git] / sys / mips / ingenic / jz4780_gpio.c
1 /*-
2  * Copyright 2015 Alexander Kabaev <kan@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_platform.h"
31
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/conf.h>
35 #include <sys/bus.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/proc.h>
41 #include <sys/resource.h>
42 #include <sys/gpio.h>
43
44 #include <machine/bus.h>
45 #include <machine/intr.h>
46
47 #include <dev/gpio/gpiobusvar.h>
48
49 #include <dev/fdt/fdt_common.h>
50 #include <dev/ofw/ofw_bus.h>
51 #include <dev/ofw/ofw_bus_subr.h>
52
53 #include <mips/ingenic/jz4780_regs.h>
54 #include <gnu/dts/include/dt-bindings/interrupt-controller/irq.h>
55
56 #include "jz4780_gpio_if.h"
57 #include "gpio_if.h"
58 #include "pic_if.h"
59
60 #define JZ4780_GPIO_PINS 32
61
62 enum pin_function {
63         JZ_FUNC_DEV_0,
64         JZ_FUNC_DEV_1,
65         JZ_FUNC_DEV_2,
66         JZ_FUNC_DEV_3,
67         JZ_FUNC_GPIO,
68         JZ_FUNC_INTR,
69 };
70
71 struct jz4780_gpio_pin {
72         struct intr_irqsrc pin_irqsrc;
73         enum intr_trigger intr_trigger;
74         enum intr_polarity intr_polarity;
75         enum pin_function pin_func;
76         uint32_t pin_caps;
77         uint32_t pin_flags;
78         uint32_t pin_num;
79         char pin_name[GPIOMAXNAME];
80 };
81
82 struct jz4780_gpio_softc {
83         device_t                dev;
84         device_t                busdev;
85         struct resource         *res[2];
86         struct mtx              mtx;
87         struct jz4780_gpio_pin  pins[JZ4780_GPIO_PINS];
88         void                    *intrhand;
89 };
90
91 static struct resource_spec jz4780_gpio_spec[] = {
92         { SYS_RES_MEMORY, 0, RF_ACTIVE },
93         { SYS_RES_IRQ,    0, RF_ACTIVE },
94         { -1, 0 }
95 };
96
97 static int jz4780_gpio_probe(device_t dev);
98 static int jz4780_gpio_attach(device_t dev);
99 static int jz4780_gpio_detach(device_t dev);
100 static int jz4780_gpio_intr(void *arg);
101
102 #define JZ4780_GPIO_LOCK(sc)            mtx_lock_spin(&(sc)->mtx)
103 #define JZ4780_GPIO_UNLOCK(sc)          mtx_unlock_spin(&(sc)->mtx)
104 #define JZ4780_GPIO_LOCK_INIT(sc)       \
105     mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev),        \
106     "jz4780_gpio", MTX_SPIN)
107 #define JZ4780_GPIO_LOCK_DESTROY(sc)    mtx_destroy(&(sc)->mtx);
108
109 #define CSR_WRITE_4(sc, reg, val)       bus_write_4((sc)->res[0], (reg), (val))
110 #define CSR_READ_4(sc, reg)             bus_read_4((sc)->res[0], (reg))
111
112 static int
113 jz4780_gpio_probe(device_t dev)
114 {
115         phandle_t node;
116
117         if (!ofw_bus_status_okay(dev))
118                 return (ENXIO);
119
120         /* We only like particular parent */
121         if (!ofw_bus_is_compatible(device_get_parent(dev),
122            "ingenic,jz4780-pinctrl"))
123                 return (ENXIO);
124
125         /* ... and only specific children os that parent */
126         node = ofw_bus_get_node(dev);
127         if (!OF_hasprop(node, "gpio-controller"))
128                 return (ENXIO);
129
130         device_set_desc(dev, "Ingenic JZ4780 GPIO Controller");
131
132         return (BUS_PROBE_DEFAULT);
133 }
134
135 static int
136 jz4780_gpio_pin_set_func(struct jz4780_gpio_softc *sc, uint32_t pin,
137     uint32_t func)
138 {
139         uint32_t mask = (1u << pin);
140
141         if (func > (uint32_t)JZ_FUNC_DEV_3)
142                 return (EINVAL);
143
144         CSR_WRITE_4(sc, JZ_GPIO_INTC, mask);
145         CSR_WRITE_4(sc, JZ_GPIO_MASKC, mask);
146         if (func & 2)
147                 CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
148         else
149                 CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
150         if (func & 1)
151                 CSR_WRITE_4(sc, JZ_GPIO_PAT0S, mask);
152         else
153                 CSR_WRITE_4(sc, JZ_GPIO_PAT0C, mask);
154
155         sc->pins[pin].pin_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
156         sc->pins[pin].pin_func = (enum pin_function)func;
157         return (0);
158 }
159
160 static int
161 jz4780_gpio_pin_set_direction(struct jz4780_gpio_softc *sc,
162     uint32_t pin, uint32_t dir)
163 {
164         uint32_t mask = (1u << pin);
165
166         switch (dir) {
167         case GPIO_PIN_OUTPUT:
168                 if (sc->pins[pin].pin_caps & dir)
169                         CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
170                 else
171                         return (EINVAL);
172                 break;
173         case GPIO_PIN_INPUT:
174                 if (sc->pins[pin].pin_caps & dir)
175                         CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
176                 else
177                         return (EINVAL);
178                 break;
179         }
180
181         sc->pins[pin].pin_flags &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT);
182         sc->pins[pin].pin_flags |= dir;
183         return (0);
184 }
185
186 static int
187 jz4780_gpio_pin_set_bias(struct jz4780_gpio_softc *sc,
188     uint32_t pin, uint32_t bias)
189 {
190         uint32_t mask = (1u << pin);
191
192         switch (bias) {
193         case GPIO_PIN_PULLUP:
194         case GPIO_PIN_PULLDOWN:
195                 if (sc->pins[pin].pin_caps & bias)
196                         CSR_WRITE_4(sc, JZ_GPIO_DPULLC, mask);
197                 else
198                         return (EINVAL);
199                 break;
200         case 0:
201                 CSR_WRITE_4(sc, JZ_GPIO_DPULLS, mask);
202                 break;
203         default:
204                 return (ENOTSUP);
205         }
206
207         sc->pins[pin].pin_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
208         sc->pins[pin].pin_flags |= bias;
209         return (0);
210 }
211
212 /*
213  * Decode pin configuration using this map
214  */
215 #if 0
216 INT MASK PAT1 PAT0
217 1   x    0    0 /* intr, level, low */
218 1   x    0    1 /* intr, level, high */
219 1   x    1    0 /* intr, edge, falling */
220 1   x    1    1 /* intr, edge, rising */
221 0   0    0    0 /* function, func 0 */
222 0   0    0    1 /* function, func 1 */
223 0   0    1    0 /* function, func 2 */
224 0   0    1    0 /* function, func 3 */
225 0   1    0    0 /* gpio, output 0 */
226 0   1    0    1 /* gpio, output 1 */
227 0   1    1    x /* gpio, input */
228 #endif
229
230 static void
231 jz4780_gpio_pin_probe(struct jz4780_gpio_softc *sc, uint32_t pin)
232 {
233         uint32_t mask = (1u << pin);
234         uint32_t val;
235
236         /* Clear cached gpio config */
237         sc->pins[pin].pin_flags = 0;
238
239         /* First check if pin is in interrupt mode */
240         val = CSR_READ_4(sc, JZ_GPIO_INT);
241         if (val & mask) {
242                 /* Pin is in interrupt mode, decode interrupt triggering mode */
243                 val = CSR_READ_4(sc, JZ_GPIO_PAT1);
244                 if (val & mask)
245                         sc->pins[pin].intr_trigger = INTR_TRIGGER_EDGE;
246                 else
247                         sc->pins[pin].intr_trigger = INTR_TRIGGER_LEVEL;
248                 /* Decode interrupt polarity */
249                 val = CSR_READ_4(sc, JZ_GPIO_PAT0);
250                 if (val & mask)
251                         sc->pins[pin].intr_polarity = INTR_POLARITY_HIGH;
252                 else
253                         sc->pins[pin].intr_polarity = INTR_POLARITY_LOW;
254
255                 sc->pins[pin].pin_func = JZ_FUNC_INTR;
256                 sc->pins[pin].pin_flags = 0;
257                 return;
258         }
259         /* Next check if pin is in gpio mode */
260         val = CSR_READ_4(sc, JZ_GPIO_MASK);
261         if (val & mask) {
262                 /* Pin is in gpio mode, decode direction and bias */
263                 val = CSR_READ_4(sc, JZ_GPIO_PAT1);
264                 if (val & mask)
265                         sc->pins[pin].pin_flags |= GPIO_PIN_INPUT;
266                 else
267                         sc->pins[pin].pin_flags |= GPIO_PIN_OUTPUT;
268                 /* Check for bias */
269                 val = CSR_READ_4(sc, JZ_GPIO_DPULL);
270                 if ((val & mask) == 0)
271                         sc->pins[pin].pin_flags |= sc->pins[pin].pin_caps &
272                                 (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
273                 sc->pins[pin].pin_func = JZ_FUNC_GPIO;
274                 return;
275         }
276         /* By exclusion, pin is in alternate function mode */
277         val = CSR_READ_4(sc, JZ_GPIO_DPULL);
278         if ((val & mask) == 0)
279                 sc->pins[pin].pin_flags = sc->pins[pin].pin_caps &
280                         (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN);
281         val = ((CSR_READ_4(sc, JZ_GPIO_PAT1) & mask) >> pin) << 1;
282         val = val | ((CSR_READ_4(sc, JZ_GPIO_PAT1) & mask) >> pin);
283         sc->pins[pin].pin_func = (enum pin_function)val;
284 }
285
286 static int
287 jz4780_gpio_register_isrcs(struct jz4780_gpio_softc *sc)
288 {
289         int error;
290         uint32_t irq, i;
291         struct intr_irqsrc *isrc;
292         const char *name;
293
294         name = device_get_nameunit(sc->dev);
295         for (irq = 0; irq < JZ4780_GPIO_PINS; irq++) {
296                 isrc = &sc->pins[irq].pin_irqsrc;
297                 error = intr_isrc_register(isrc, sc->dev, 0, "%s,%d",
298                     name, irq);
299                 if (error != 0) {
300                         for (i = 0; i < irq; i++)
301                                 intr_isrc_deregister(&sc->pins[i].pin_irqsrc);
302                         device_printf(sc->dev, "%s failed", __func__);
303                         return (error);
304                 }
305         }
306
307         return (0);
308 }
309
310 static int
311 jz4780_gpio_attach(device_t dev)
312 {
313         struct jz4780_gpio_softc *sc = device_get_softc(dev);
314         phandle_t node;
315         uint32_t i, pd_pins, pu_pins;
316
317         sc->dev = dev;
318
319         if (bus_alloc_resources(dev, jz4780_gpio_spec, sc->res)) {
320                 device_printf(dev, "could not allocate resources for device\n");
321                 return (ENXIO);
322         }
323
324         JZ4780_GPIO_LOCK_INIT(sc);
325
326         node = ofw_bus_get_node(dev);
327         OF_getencprop(node, "ingenic,pull-ups", &pu_pins, sizeof(pu_pins));
328         OF_getencprop(node, "ingenic,pull-downs", &pd_pins, sizeof(pd_pins));
329
330         for (i = 0; i < JZ4780_GPIO_PINS; i++) {
331                 sc->pins[i].pin_num = i;
332                 sc->pins[i].pin_caps |= GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
333                 if (pu_pins & (1 << i))
334                         sc->pins[i].pin_caps |= GPIO_PIN_PULLUP;
335                 if (pd_pins & (1 << i))
336                         sc->pins[i].pin_caps |= GPIO_PIN_PULLDOWN;
337                 sc->pins[i].intr_polarity = INTR_POLARITY_CONFORM;
338                 sc->pins[i].intr_trigger = INTR_TRIGGER_CONFORM;
339
340                 snprintf(sc->pins[i].pin_name, GPIOMAXNAME - 1, "gpio%c%d",
341                     device_get_unit(dev) + 'a', i);
342                 sc->pins[i].pin_name[GPIOMAXNAME - 1] = '\0';
343
344                 jz4780_gpio_pin_probe(sc, i);
345         }
346
347         if (jz4780_gpio_register_isrcs(sc) != 0)
348                 goto fail;
349
350         if (intr_pic_register(dev, OF_xref_from_node(node)) == NULL) {
351                 device_printf(dev, "could not register PIC\n");
352                 goto fail;
353         }
354
355         if (bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
356             jz4780_gpio_intr, NULL, sc, &sc->intrhand) != 0)
357                 goto fail_pic;
358
359         sc->busdev = gpiobus_attach_bus(dev);
360         if (sc->busdev == NULL)
361                 goto fail_pic;
362
363         return (0);
364 fail_pic:
365         intr_pic_deregister(dev, OF_xref_from_node(node));
366 fail:
367         if (sc->intrhand != NULL)
368                 bus_teardown_intr(dev, sc->res[1], sc->intrhand);
369         bus_release_resources(dev, jz4780_gpio_spec, sc->res);
370         JZ4780_GPIO_LOCK_DESTROY(sc);
371         return (ENXIO);
372 }
373
374 static int
375 jz4780_gpio_detach(device_t dev)
376 {
377         struct jz4780_gpio_softc *sc = device_get_softc(dev);
378
379         bus_release_resources(dev, jz4780_gpio_spec, sc->res);
380         JZ4780_GPIO_LOCK_DESTROY(sc);
381         return (0);
382 }
383
384 static int
385 jz4780_gpio_configure_pin(device_t dev, uint32_t pin, uint32_t func,
386     uint32_t flags)
387 {
388         struct jz4780_gpio_softc *sc;
389         int retval;
390
391         if (pin >= JZ4780_GPIO_PINS)
392                 return (EINVAL);
393
394         sc = device_get_softc(dev);
395         JZ4780_GPIO_LOCK(sc);
396         retval = jz4780_gpio_pin_set_func(sc, pin, func);
397         if (retval == 0)
398                 retval = jz4780_gpio_pin_set_bias(sc, pin, flags);
399         JZ4780_GPIO_UNLOCK(sc);
400         return (retval);
401 }
402
403 static device_t
404 jz4780_gpio_get_bus(device_t dev)
405 {
406         struct jz4780_gpio_softc *sc;
407
408         sc = device_get_softc(dev);
409
410         return (sc->busdev);
411 }
412
413 static int
414 jz4780_gpio_pin_max(device_t dev, int *maxpin)
415 {
416
417         *maxpin = JZ4780_GPIO_PINS - 1;
418         return (0);
419 }
420
421 static int
422 jz4780_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
423 {
424         struct jz4780_gpio_softc *sc;
425
426         if (pin >= JZ4780_GPIO_PINS)
427                 return (EINVAL);
428
429         sc = device_get_softc(dev);
430         JZ4780_GPIO_LOCK(sc);
431         *caps = sc->pins[pin].pin_caps;
432         JZ4780_GPIO_UNLOCK(sc);
433
434         return (0);
435 }
436
437 static int
438 jz4780_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
439 {
440         struct jz4780_gpio_softc *sc;
441
442         if (pin >= JZ4780_GPIO_PINS)
443                 return (EINVAL);
444
445         sc = device_get_softc(dev);
446         JZ4780_GPIO_LOCK(sc);
447         *flags = sc->pins[pin].pin_flags;
448         JZ4780_GPIO_UNLOCK(sc);
449
450         return (0);
451 }
452
453 static int
454 jz4780_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
455 {
456         struct jz4780_gpio_softc *sc;
457
458         if (pin >= JZ4780_GPIO_PINS)
459                 return (EINVAL);
460
461         sc = device_get_softc(dev);
462         strncpy(name, sc->pins[pin].pin_name, GPIOMAXNAME - 1);
463         name[GPIOMAXNAME - 1] = '\0';
464
465         return (0);
466 }
467
468 static int
469 jz4780_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
470 {
471         struct jz4780_gpio_softc *sc;
472         int retval;
473
474         if (pin >= JZ4780_GPIO_PINS)
475                 return (EINVAL);
476
477         sc = device_get_softc(dev);
478         JZ4780_GPIO_LOCK(sc);
479         retval = jz4780_gpio_pin_set_direction(sc, pin,
480             flags & (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT));
481         if (retval == 0)
482                 retval = jz4780_gpio_pin_set_bias(sc, pin,
483                     flags & (GPIO_PIN_PULLDOWN | GPIO_PIN_PULLUP));
484         JZ4780_GPIO_UNLOCK(sc);
485
486         return (retval);
487 }
488
489 static int
490 jz4780_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
491 {
492         struct jz4780_gpio_softc *sc;
493         uint32_t mask;
494         int retval;
495
496         if (pin >= JZ4780_GPIO_PINS)
497                 return (EINVAL);
498
499         retval = EINVAL;
500         mask = (1u << pin);
501         sc = device_get_softc(dev);
502         JZ4780_GPIO_LOCK(sc);
503         if (sc->pins[pin].pin_func == JZ_FUNC_GPIO) {
504                 CSR_WRITE_4(sc, value ? JZ_GPIO_PAT0S : JZ_GPIO_PAT0C, mask);
505                 retval = 0;
506         }
507         JZ4780_GPIO_UNLOCK(sc);
508
509         return (retval);
510 }
511
512 static int
513 jz4780_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
514 {
515         struct jz4780_gpio_softc *sc;
516         uint32_t data, mask;
517
518         if (pin >= JZ4780_GPIO_PINS)
519                 return (EINVAL);
520
521         mask = (1u << pin);
522         sc = device_get_softc(dev);
523         JZ4780_GPIO_LOCK(sc);
524         data = CSR_READ_4(sc, JZ_GPIO_PIN);
525         JZ4780_GPIO_UNLOCK(sc);
526         *val = (data & mask) ? 1 : 0;
527
528         return (0);
529 }
530
531 static int
532 jz4780_gpio_pin_toggle(device_t dev, uint32_t pin)
533 {
534         struct jz4780_gpio_softc *sc;
535         uint32_t data, mask;
536         int retval;
537
538         if (pin >= JZ4780_GPIO_PINS)
539                 return (EINVAL);
540
541         retval = EINVAL;
542         mask = (1u << pin);
543         sc = device_get_softc(dev);
544         JZ4780_GPIO_LOCK(sc);
545         if (sc->pins[pin].pin_func == JZ_FUNC_GPIO &&
546             sc->pins[pin].pin_flags & GPIO_PIN_OUTPUT) {
547                 data = CSR_READ_4(sc, JZ_GPIO_PIN);
548                 CSR_WRITE_4(sc, (data & mask) ? JZ_GPIO_PAT0C : JZ_GPIO_PAT0S,
549                     mask);
550                 retval = 0;
551         }
552         JZ4780_GPIO_UNLOCK(sc);
553
554         return (retval);
555 }
556
557 #ifdef FDT
558 static int
559 jz_gpio_map_intr_fdt(device_t dev, struct intr_map_data *data, u_int *irqp,
560         enum intr_polarity *polp, enum intr_trigger *trigp)
561 {
562         struct jz4780_gpio_softc *sc;
563         struct intr_map_data_fdt *daf;
564
565         sc = device_get_softc(dev);
566         daf = (struct intr_map_data_fdt *)data;
567
568         if (data == NULL || data->type != INTR_MAP_DATA_FDT ||
569             daf->ncells == 0 || daf->ncells > 2)
570                 return (EINVAL);
571
572         *irqp = daf->cells[0];
573         if (daf->ncells == 1) {
574                 *trigp = INTR_TRIGGER_CONFORM;
575                 *polp = INTR_POLARITY_CONFORM;
576                 return (0);
577         }
578
579         switch (daf->cells[1])
580         {
581         case IRQ_TYPE_EDGE_RISING:
582                 *trigp = INTR_TRIGGER_EDGE;
583                 *polp = INTR_POLARITY_HIGH;
584                 break;
585         case IRQ_TYPE_EDGE_FALLING:
586                 *trigp = INTR_TRIGGER_EDGE;
587                 *polp = INTR_POLARITY_LOW;
588                 break;
589         case IRQ_TYPE_LEVEL_HIGH:
590                 *trigp = INTR_TRIGGER_LEVEL;
591                 *polp = INTR_POLARITY_HIGH;
592                 break;
593         case IRQ_TYPE_LEVEL_LOW:
594                 *trigp = INTR_TRIGGER_LEVEL;
595                 *polp = INTR_POLARITY_LOW;
596                 break;
597         default:
598                 device_printf(sc->dev, "unsupported trigger/polarity 0x%2x\n",
599                     daf->cells[1]);
600                 return (ENOTSUP);
601         }
602
603         return (0);
604 }
605 #endif
606
607 static int
608 jz_gpio_map_intr(device_t dev, struct intr_map_data *data, u_int *irqp,
609         enum intr_polarity *polp, enum intr_trigger *trigp)
610 {
611         struct jz4780_gpio_softc *sc;
612         enum intr_polarity pol;
613         enum intr_trigger trig;
614         u_int irq;
615
616         sc = device_get_softc(dev);
617         switch (data->type) {
618 #ifdef FDT
619         case INTR_MAP_DATA_FDT:
620                 if (jz_gpio_map_intr_fdt(dev, data, &irq, &pol, &trig) != 0)
621                         return (EINVAL);
622                 break;
623 #endif
624         default:
625                 return (EINVAL);
626         }
627
628         if (irq >= nitems(sc->pins))
629                 return (EINVAL);
630
631         *irqp = irq;
632         if (polp != NULL)
633                 *polp = pol;
634         if (trigp != NULL)
635                 *trigp = trig;
636         return (0);
637 }
638
639 static int
640 jz4780_gpio_pic_map_intr(device_t dev, struct intr_map_data *data,
641     struct intr_irqsrc **isrcp)
642 {
643         struct jz4780_gpio_softc *sc;
644         int retval;
645         u_int irq;
646
647         retval = jz_gpio_map_intr(dev, data, &irq, NULL, NULL);
648         if (retval == 0) {
649                 sc = device_get_softc(dev);
650                 *isrcp = &sc->pins[irq].pin_irqsrc;
651         }
652         return (retval);
653 }
654
655 static int
656 jz4780_gpio_pic_setup_intr(device_t dev, struct intr_irqsrc *isrc,
657         struct resource *res, struct intr_map_data *data)
658 {
659         struct jz4780_gpio_softc *sc;
660         struct jz4780_gpio_pin *pin;
661         enum intr_polarity pol;
662         enum intr_trigger trig;
663         uint32_t mask, irq;
664
665         if (data == NULL)
666                 return (ENOTSUP);
667
668         /* Get config for resource. */
669         if (jz_gpio_map_intr(dev, data, &irq, &pol, &trig))
670                 return (EINVAL);
671
672         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
673         if (isrc != &pin->pin_irqsrc)
674                 return (EINVAL);
675
676         /* Compare config if this is not first setup. */
677         if (isrc->isrc_handlers != 0) {
678                 if ((pol != INTR_POLARITY_CONFORM && pol != pin->intr_polarity) ||
679                     (trig != INTR_TRIGGER_CONFORM && trig != pin->intr_trigger))
680                         return (EINVAL);
681                 else
682                         return (0);
683         }
684
685         if (pol == INTR_POLARITY_CONFORM)
686                 pol = INTR_POLARITY_LOW;        /* just pick some */
687         if (trig == INTR_TRIGGER_CONFORM)
688                 trig = INTR_TRIGGER_EDGE;       /* just pick some */
689
690         sc = device_get_softc(dev);
691         mask = 1u << pin->pin_num;
692
693         JZ4780_GPIO_LOCK(sc);
694         CSR_WRITE_4(sc, JZ_GPIO_MASKS, mask);
695         CSR_WRITE_4(sc, JZ_GPIO_INTS, mask);
696
697         if (trig == INTR_TRIGGER_LEVEL)
698                 CSR_WRITE_4(sc, JZ_GPIO_PAT1C, mask);
699         else
700                 CSR_WRITE_4(sc, JZ_GPIO_PAT1S, mask);
701
702         if (pol == INTR_POLARITY_LOW)
703                 CSR_WRITE_4(sc, JZ_GPIO_PAT0C, mask);
704         else
705                 CSR_WRITE_4(sc, JZ_GPIO_PAT0S, mask);
706
707         pin->pin_func = JZ_FUNC_INTR;
708         pin->intr_trigger = trig;
709         pin->intr_polarity = pol;
710
711         CSR_WRITE_4(sc, JZ_GPIO_FLAGC, mask);
712         CSR_WRITE_4(sc, JZ_GPIO_MASKC, mask);
713         JZ4780_GPIO_UNLOCK(sc);
714         return (0);
715 }
716
717 static void
718 jz4780_gpio_pic_enable_intr(device_t dev, struct intr_irqsrc *isrc)
719 {
720         struct jz4780_gpio_softc *sc;
721         struct jz4780_gpio_pin *pin;
722
723         sc = device_get_softc(dev);
724         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
725
726         CSR_WRITE_4(sc, JZ_GPIO_MASKC, 1u << pin->pin_num);
727 }
728
729 static void
730 jz4780_gpio_pic_disable_intr(device_t dev, struct intr_irqsrc *isrc)
731 {
732         struct jz4780_gpio_softc *sc;
733         struct jz4780_gpio_pin *pin;
734
735         sc = device_get_softc(dev);
736         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
737
738         CSR_WRITE_4(sc, JZ_GPIO_MASKS, 1u << pin->pin_num);
739 }
740
741 static void
742 jz4780_gpio_pic_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
743 {
744
745         jz4780_gpio_pic_disable_intr(dev, isrc);
746 }
747
748 static void
749 jz4780_gpio_pic_post_ithread(device_t dev, struct intr_irqsrc *isrc)
750 {
751
752         jz4780_gpio_pic_enable_intr(dev, isrc);
753 }
754
755 static void
756 jz4780_gpio_pic_post_filter(device_t dev, struct intr_irqsrc *isrc)
757 {
758         struct jz4780_gpio_softc *sc;
759         struct jz4780_gpio_pin *pin;
760
761         sc = device_get_softc(dev);
762         pin = __containerof(isrc, struct jz4780_gpio_pin, pin_irqsrc);
763
764         CSR_WRITE_4(sc, JZ_GPIO_FLAGC, 1u << pin->pin_num);
765 }
766
767 static int
768 jz4780_gpio_intr(void *arg)
769 {
770         struct jz4780_gpio_softc *sc;
771         uint32_t i, interrupts;
772
773         sc = arg;
774         interrupts = CSR_READ_4(sc, JZ_GPIO_FLAG);
775
776         for (i = 0; interrupts != 0; i++, interrupts >>= 1) {
777                 if ((interrupts & 0x1) == 0)
778                         continue;
779                 if (intr_isrc_dispatch(&sc->pins[i].pin_irqsrc,
780                     curthread->td_intr_frame) != 0) {
781                         device_printf(sc->dev, "spurious interrupt %d\n", i);
782                         PIC_DISABLE_INTR(sc->dev, &sc->pins[i].pin_irqsrc);
783                 }
784         }
785
786         return (FILTER_HANDLED);
787 }
788
789 static phandle_t
790 jz4780_gpio_bus_get_node(device_t bus, device_t dev)
791 {
792
793         return (ofw_bus_get_node(bus));
794 }
795
796 static device_method_t jz4780_gpio_methods[] = {
797         /* Device interface */
798         DEVMETHOD(device_probe,         jz4780_gpio_probe),
799         DEVMETHOD(device_attach,        jz4780_gpio_attach),
800         DEVMETHOD(device_detach,        jz4780_gpio_detach),
801
802         /* GPIO protocol */
803         DEVMETHOD(gpio_get_bus,         jz4780_gpio_get_bus),
804         DEVMETHOD(gpio_pin_max,         jz4780_gpio_pin_max),
805         DEVMETHOD(gpio_pin_getname,     jz4780_gpio_pin_getname),
806         DEVMETHOD(gpio_pin_getflags,    jz4780_gpio_pin_getflags),
807         DEVMETHOD(gpio_pin_getcaps,     jz4780_gpio_pin_getcaps),
808         DEVMETHOD(gpio_pin_setflags,    jz4780_gpio_pin_setflags),
809         DEVMETHOD(gpio_pin_get,         jz4780_gpio_pin_get),
810         DEVMETHOD(gpio_pin_set,         jz4780_gpio_pin_set),
811         DEVMETHOD(gpio_pin_toggle,      jz4780_gpio_pin_toggle),
812
813         /* Custom interface to set pin function */
814         DEVMETHOD(jz4780_gpio_configure_pin, jz4780_gpio_configure_pin),
815
816         /* Interrupt controller interface */
817         DEVMETHOD(pic_setup_intr,       jz4780_gpio_pic_setup_intr),
818         DEVMETHOD(pic_enable_intr,      jz4780_gpio_pic_enable_intr),
819         DEVMETHOD(pic_disable_intr,     jz4780_gpio_pic_disable_intr),
820         DEVMETHOD(pic_map_intr,         jz4780_gpio_pic_map_intr),
821         DEVMETHOD(pic_post_filter,      jz4780_gpio_pic_post_filter),
822         DEVMETHOD(pic_post_ithread,     jz4780_gpio_pic_post_ithread),
823         DEVMETHOD(pic_pre_ithread,      jz4780_gpio_pic_pre_ithread),
824
825         /* ofw_bus interface */
826         DEVMETHOD(ofw_bus_get_node,     jz4780_gpio_bus_get_node),
827
828         DEVMETHOD_END
829 };
830
831 static driver_t jz4780_gpio_driver = {
832         "gpio",
833         jz4780_gpio_methods,
834         sizeof(struct jz4780_gpio_softc),
835 };
836
837 static devclass_t jz4780_gpio_devclass;
838
839 EARLY_DRIVER_MODULE(jz4780_gpio, simplebus, jz4780_gpio_driver,
840     jz4780_gpio_devclass, 0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);