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