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