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