1122531Sume/*-
2122531Sume * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
3122531Sume * Copyright (c) 2012 Luiz Otavio O Souza.
4122531Sume * All rights reserved.
5122531Sume *
6122531Sume * Redistribution and use in source and binary forms, with or without
7122531Sume * modification, are permitted provided that the following conditions
8122531Sume * are met:
9122531Sume * 1. Redistributions of source code must retain the above copyright
10122531Sume *    notice, this list of conditions and the following disclaimer.
11122531Sume * 2. Redistributions in binary form must reproduce the above copyright
12122531Sume *    notice, this list of conditions and the following disclaimer in the
13122531Sume *    documentation and/or other materials provided with the distribution.
14122531Sume *
15122531Sume * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16122531Sume * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17122531Sume * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18122531Sume * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19122531Sume * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20122531Sume * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21122531Sume * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22122531Sume * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23122531Sume * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24122531Sume * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25122531Sume * SUCH DAMAGE.
26122531Sume *
27122531Sume */
28122531Sume#include <sys/cdefs.h>
29122531Sume__FBSDID("$FreeBSD: stable/10/sys/arm/broadcom/bcm2835/bcm2835_gpio.c 322724 2017-08-20 16:52:27Z marius $");
30122531Sume
31122531Sume#include <sys/param.h>
32122531Sume#include <sys/systm.h>
33175360Ssobomax#include <sys/bus.h>
34122531Sume
35175360Ssobomax#include <sys/kernel.h>
36122531Sume#include <sys/module.h>
37122531Sume#include <sys/rman.h>
38122531Sume#include <sys/lock.h>
39122531Sume#include <sys/mutex.h>
40122531Sume#include <sys/gpio.h>
41122531Sume#include <sys/sysctl.h>
42122531Sume
43122531Sume#include <machine/bus.h>
44122531Sume#include <machine/cpu.h>
45122531Sume#include <machine/cpufunc.h>
46122531Sume#include <machine/resource.h>
47122531Sume#include <machine/fdt.h>
48122531Sume#include <machine/intr.h>
49122531Sume
50122531Sume#include <dev/fdt/fdt_common.h>
51122531Sume#include <dev/ofw/ofw_bus.h>
52122531Sume#include <dev/ofw/ofw_bus_subr.h>
53122531Sume
54122531Sume#include <arm/broadcom/bcm2835/bcm2835_gpio.h>
55122531Sume
56122531Sume#include "gpio_if.h"
57122531Sume
58122531Sume#ifdef DEBUG
59122531Sume#define dprintf(fmt, args...) do { printf("%s(): ", __func__);   \
60    printf(fmt,##args); } while (0)
61#else
62#define dprintf(fmt, args...)
63#endif
64
65#define	BCM_GPIO_PINS		54
66#define	BCM_GPIO_DEFAULT_CAPS	(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT |	\
67    GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)
68
69struct bcm_gpio_sysctl {
70	struct bcm_gpio_softc	*sc;
71	uint32_t		pin;
72};
73
74struct bcm_gpio_softc {
75	device_t		sc_dev;
76	struct mtx		sc_mtx;
77	struct resource *	sc_mem_res;
78	struct resource *	sc_irq_res;
79	bus_space_tag_t		sc_bst;
80	bus_space_handle_t	sc_bsh;
81	void *			sc_intrhand;
82	int			sc_gpio_npins;
83	int			sc_ro_npins;
84	int			sc_ro_pins[BCM_GPIO_PINS];
85	struct gpio_pin		sc_gpio_pins[BCM_GPIO_PINS];
86	struct bcm_gpio_sysctl	sc_sysctl[BCM_GPIO_PINS];
87};
88
89enum bcm_gpio_pud {
90	BCM_GPIO_NONE,
91	BCM_GPIO_PULLDOWN,
92	BCM_GPIO_PULLUP,
93};
94
95#define	BCM_GPIO_LOCK(_sc)	mtx_lock(&_sc->sc_mtx)
96#define	BCM_GPIO_UNLOCK(_sc)	mtx_unlock(&_sc->sc_mtx)
97#define	BCM_GPIO_LOCK_ASSERT(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED)
98
99#define	BCM_GPIO_GPFSEL(_bank)	0x00 + _bank * 4
100#define	BCM_GPIO_GPSET(_bank)	0x1c + _bank * 4
101#define	BCM_GPIO_GPCLR(_bank)	0x28 + _bank * 4
102#define	BCM_GPIO_GPLEV(_bank)	0x34 + _bank * 4
103#define	BCM_GPIO_GPPUD(_bank)	0x94
104#define	BCM_GPIO_GPPUDCLK(_bank)	0x98 + _bank * 4
105
106#define	BCM_GPIO_WRITE(_sc, _off, _val)		\
107    bus_space_write_4(_sc->sc_bst, _sc->sc_bsh, _off, _val)
108#define	BCM_GPIO_READ(_sc, _off)		\
109    bus_space_read_4(_sc->sc_bst, _sc->sc_bsh, _off)
110
111static struct ofw_compat_data compat_data[] = {
112	{"broadcom,bcm2835-gpio",	1},
113	{"brcm,bcm2835-gpio",		1},
114	{NULL,				0}
115};
116
117static int
118bcm_gpio_pin_is_ro(struct bcm_gpio_softc *sc, int pin)
119{
120	int i;
121
122	for (i = 0; i < sc->sc_ro_npins; i++)
123		if (pin == sc->sc_ro_pins[i])
124			return (1);
125	return (0);
126}
127
128static uint32_t
129bcm_gpio_get_function(struct bcm_gpio_softc *sc, uint32_t pin)
130{
131	uint32_t bank, func, offset;
132
133	/* Five banks, 10 pins per bank, 3 bits per pin. */
134	bank = pin / 10;
135	offset = (pin - bank * 10) * 3;
136
137	BCM_GPIO_LOCK(sc);
138	func = (BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank)) >> offset) & 7;
139	BCM_GPIO_UNLOCK(sc);
140
141	return (func);
142}
143
144static void
145bcm_gpio_func_str(uint32_t nfunc, char *buf, int bufsize)
146{
147
148	switch (nfunc) {
149	case BCM_GPIO_INPUT:
150		strncpy(buf, "input", bufsize);
151		break;
152	case BCM_GPIO_OUTPUT:
153		strncpy(buf, "output", bufsize);
154		break;
155	case BCM_GPIO_ALT0:
156		strncpy(buf, "alt0", bufsize);
157		break;
158	case BCM_GPIO_ALT1:
159		strncpy(buf, "alt1", bufsize);
160		break;
161	case BCM_GPIO_ALT2:
162		strncpy(buf, "alt2", bufsize);
163		break;
164	case BCM_GPIO_ALT3:
165		strncpy(buf, "alt3", bufsize);
166		break;
167	case BCM_GPIO_ALT4:
168		strncpy(buf, "alt4", bufsize);
169		break;
170	case BCM_GPIO_ALT5:
171		strncpy(buf, "alt5", bufsize);
172		break;
173	default:
174		strncpy(buf, "invalid", bufsize);
175	}
176}
177
178static int
179bcm_gpio_str_func(char *func, uint32_t *nfunc)
180{
181
182	if (strcasecmp(func, "input") == 0)
183		*nfunc = BCM_GPIO_INPUT;
184	else if (strcasecmp(func, "output") == 0)
185		*nfunc = BCM_GPIO_OUTPUT;
186	else if (strcasecmp(func, "alt0") == 0)
187		*nfunc = BCM_GPIO_ALT0;
188	else if (strcasecmp(func, "alt1") == 0)
189		*nfunc = BCM_GPIO_ALT1;
190	else if (strcasecmp(func, "alt2") == 0)
191		*nfunc = BCM_GPIO_ALT2;
192	else if (strcasecmp(func, "alt3") == 0)
193		*nfunc = BCM_GPIO_ALT3;
194	else if (strcasecmp(func, "alt4") == 0)
195		*nfunc = BCM_GPIO_ALT4;
196	else if (strcasecmp(func, "alt5") == 0)
197		*nfunc = BCM_GPIO_ALT5;
198	else
199		return (-1);
200
201	return (0);
202}
203
204static uint32_t
205bcm_gpio_func_flag(uint32_t nfunc)
206{
207
208	switch (nfunc) {
209	case BCM_GPIO_INPUT:
210		return (GPIO_PIN_INPUT);
211	case BCM_GPIO_OUTPUT:
212		return (GPIO_PIN_OUTPUT);
213	}
214	return (0);
215}
216
217static void
218bcm_gpio_set_function(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t f)
219{
220	uint32_t bank, data, offset;
221
222	/* Must be called with lock held. */
223	BCM_GPIO_LOCK_ASSERT(sc);
224
225	/* Five banks, 10 pins per bank, 3 bits per pin. */
226	bank = pin / 10;
227	offset = (pin - bank * 10) * 3;
228
229	data = BCM_GPIO_READ(sc, BCM_GPIO_GPFSEL(bank));
230	data &= ~(7 << offset);
231	data |= (f << offset);
232	BCM_GPIO_WRITE(sc, BCM_GPIO_GPFSEL(bank), data);
233}
234
235static void
236bcm_gpio_set_pud(struct bcm_gpio_softc *sc, uint32_t pin, uint32_t state)
237{
238	uint32_t bank, offset;
239
240	/* Must be called with lock held. */
241	BCM_GPIO_LOCK_ASSERT(sc);
242
243	bank = pin / 32;
244	offset = pin - 32 * bank;
245
246	BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), state);
247	DELAY(10);
248	BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), (1 << offset));
249	DELAY(10);
250	BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), 0);
251	BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), 0);
252}
253
254void
255bcm_gpio_set_alternate(device_t dev, uint32_t pin, uint32_t nfunc)
256{
257	struct bcm_gpio_softc *sc;
258	int i;
259
260	sc = device_get_softc(dev);
261	BCM_GPIO_LOCK(sc);
262
263	/* Disable pull-up or pull-down on pin. */
264	bcm_gpio_set_pud(sc, pin, BCM_GPIO_NONE);
265
266	/* And now set the pin function. */
267	bcm_gpio_set_function(sc, pin, nfunc);
268
269	/* Update the pin flags. */
270	for (i = 0; i < sc->sc_gpio_npins; i++) {
271		if (sc->sc_gpio_pins[i].gp_pin == pin)
272			break;
273	}
274	if (i < sc->sc_gpio_npins)
275		sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(nfunc);
276
277        BCM_GPIO_UNLOCK(sc);
278}
279
280static void
281bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin,
282    unsigned int flags)
283{
284
285	BCM_GPIO_LOCK(sc);
286
287	/*
288	 * Manage input/output.
289	 */
290	if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
291		pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
292		if (flags & GPIO_PIN_OUTPUT) {
293			pin->gp_flags |= GPIO_PIN_OUTPUT;
294			bcm_gpio_set_function(sc, pin->gp_pin,
295			    BCM_GPIO_OUTPUT);
296		} else {
297			pin->gp_flags |= GPIO_PIN_INPUT;
298			bcm_gpio_set_function(sc, pin->gp_pin,
299			    BCM_GPIO_INPUT);
300		}
301	}
302
303	/* Manage Pull-up/pull-down. */
304	pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
305	if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
306		if (flags & GPIO_PIN_PULLUP) {
307			pin->gp_flags |= GPIO_PIN_PULLUP;
308			bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLUP);
309		} else {
310			pin->gp_flags |= GPIO_PIN_PULLDOWN;
311			bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLDOWN);
312		}
313	} else
314		bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_NONE);
315
316	BCM_GPIO_UNLOCK(sc);
317}
318
319static int
320bcm_gpio_pin_max(device_t dev, int *maxpin)
321{
322
323	*maxpin = BCM_GPIO_PINS - 1;
324	return (0);
325}
326
327static int
328bcm_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
329{
330	struct bcm_gpio_softc *sc = device_get_softc(dev);
331	int i;
332
333	for (i = 0; i < sc->sc_gpio_npins; i++) {
334		if (sc->sc_gpio_pins[i].gp_pin == pin)
335			break;
336	}
337
338	if (i >= sc->sc_gpio_npins)
339		return (EINVAL);
340
341	BCM_GPIO_LOCK(sc);
342	*caps = sc->sc_gpio_pins[i].gp_caps;
343	BCM_GPIO_UNLOCK(sc);
344
345	return (0);
346}
347
348static int
349bcm_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
350{
351	struct bcm_gpio_softc *sc = device_get_softc(dev);
352	int i;
353
354	for (i = 0; i < sc->sc_gpio_npins; i++) {
355		if (sc->sc_gpio_pins[i].gp_pin == pin)
356			break;
357	}
358
359	if (i >= sc->sc_gpio_npins)
360		return (EINVAL);
361
362	BCM_GPIO_LOCK(sc);
363	*flags = sc->sc_gpio_pins[i].gp_flags;
364	BCM_GPIO_UNLOCK(sc);
365
366	return (0);
367}
368
369static int
370bcm_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
371{
372	struct bcm_gpio_softc *sc = device_get_softc(dev);
373	int i;
374
375	for (i = 0; i < sc->sc_gpio_npins; i++) {
376		if (sc->sc_gpio_pins[i].gp_pin == pin)
377			break;
378	}
379
380	if (i >= sc->sc_gpio_npins)
381		return (EINVAL);
382
383	BCM_GPIO_LOCK(sc);
384	memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
385	BCM_GPIO_UNLOCK(sc);
386
387	return (0);
388}
389
390static int
391bcm_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
392{
393	struct bcm_gpio_softc *sc = device_get_softc(dev);
394	int i;
395
396	for (i = 0; i < sc->sc_gpio_npins; i++) {
397		if (sc->sc_gpio_pins[i].gp_pin == pin)
398			break;
399	}
400
401	if (i >= sc->sc_gpio_npins)
402		return (EINVAL);
403
404	/* We never touch on read-only/reserved pins. */
405	if (bcm_gpio_pin_is_ro(sc, pin))
406		return (EINVAL);
407
408	bcm_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
409
410	return (0);
411}
412
413static int
414bcm_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
415{
416	struct bcm_gpio_softc *sc = device_get_softc(dev);
417	uint32_t bank, offset;
418	int i;
419
420	for (i = 0; i < sc->sc_gpio_npins; i++) {
421		if (sc->sc_gpio_pins[i].gp_pin == pin)
422			break;
423	}
424
425	if (i >= sc->sc_gpio_npins)
426		return (EINVAL);
427
428	/* We never write to read-only/reserved pins. */
429	if (bcm_gpio_pin_is_ro(sc, pin))
430		return (EINVAL);
431
432	bank = pin / 32;
433	offset = pin - 32 * bank;
434
435	BCM_GPIO_LOCK(sc);
436	if (value)
437		BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
438	else
439		BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
440	BCM_GPIO_UNLOCK(sc);
441
442	return (0);
443}
444
445static int
446bcm_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
447{
448	struct bcm_gpio_softc *sc = device_get_softc(dev);
449	uint32_t bank, offset, reg_data;
450	int i;
451
452	for (i = 0; i < sc->sc_gpio_npins; i++) {
453		if (sc->sc_gpio_pins[i].gp_pin == pin)
454			break;
455	}
456
457	if (i >= sc->sc_gpio_npins)
458		return (EINVAL);
459
460	bank = pin / 32;
461	offset = pin - 32 * bank;
462
463	BCM_GPIO_LOCK(sc);
464	reg_data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
465	BCM_GPIO_UNLOCK(sc);
466	*val = (reg_data & (1 << offset)) ? 1 : 0;
467
468	return (0);
469}
470
471static int
472bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
473{
474	struct bcm_gpio_softc *sc = device_get_softc(dev);
475	uint32_t bank, data, offset;
476	int i;
477
478	for (i = 0; i < sc->sc_gpio_npins; i++) {
479		if (sc->sc_gpio_pins[i].gp_pin == pin)
480			break;
481	}
482
483	if (i >= sc->sc_gpio_npins)
484		return (EINVAL);
485
486	/* We never write to read-only/reserved pins. */
487	if (bcm_gpio_pin_is_ro(sc, pin))
488		return (EINVAL);
489
490	bank = pin / 32;
491	offset = pin - 32 * bank;
492
493	BCM_GPIO_LOCK(sc);
494	data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
495	if (data & (1 << offset))
496		BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
497	else
498		BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
499	BCM_GPIO_UNLOCK(sc);
500
501	return (0);
502}
503
504static int
505bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
506{
507	char buf[16];
508	struct bcm_gpio_softc *sc;
509	struct bcm_gpio_sysctl *sc_sysctl;
510	uint32_t nfunc;
511	int error;
512
513	sc_sysctl = arg1;
514	sc = sc_sysctl->sc;
515
516	/* Get the current pin function. */
517	nfunc = bcm_gpio_get_function(sc, sc_sysctl->pin);
518	bcm_gpio_func_str(nfunc, buf, sizeof(buf));
519
520	error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
521	if (error != 0 || req->newptr == NULL)
522		return (error);
523	/* Ignore changes on read-only pins. */
524	if (bcm_gpio_pin_is_ro(sc, sc_sysctl->pin))
525		return (0);
526	/* Parse the user supplied string and check for a valid pin function. */
527	if (bcm_gpio_str_func(buf, &nfunc) != 0)
528		return (EINVAL);
529
530	/* Update the pin alternate function. */
531	bcm_gpio_set_alternate(sc->sc_dev, sc_sysctl->pin, nfunc);
532
533	return (0);
534}
535
536static void
537bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
538{
539	char pinbuf[3];
540	struct bcm_gpio_sysctl *sc_sysctl;
541	struct sysctl_ctx_list *ctx;
542	struct sysctl_oid *tree_node, *pin_node, *pinN_node;
543	struct sysctl_oid_list *tree, *pin_tree, *pinN_tree;
544	int i;
545
546	/*
547	 * Add per-pin sysctl tree/handlers.
548	 */
549	ctx = device_get_sysctl_ctx(sc->sc_dev);
550 	tree_node = device_get_sysctl_tree(sc->sc_dev);
551 	tree = SYSCTL_CHILDREN(tree_node);
552	pin_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "pin",
553	    CTLFLAG_RD, NULL, "GPIO Pins");
554	pin_tree = SYSCTL_CHILDREN(pin_node);
555
556	for (i = 0; i < sc->sc_gpio_npins; i++) {
557
558		snprintf(pinbuf, sizeof(pinbuf), "%d", i);
559		pinN_node = SYSCTL_ADD_NODE(ctx, pin_tree, OID_AUTO, pinbuf,
560		    CTLFLAG_RD, NULL, "GPIO Pin");
561		pinN_tree = SYSCTL_CHILDREN(pinN_node);
562
563		sc->sc_sysctl[i].sc = sc;
564		sc_sysctl = &sc->sc_sysctl[i];
565		sc_sysctl->sc = sc;
566		sc_sysctl->pin = sc->sc_gpio_pins[i].gp_pin;
567		SYSCTL_ADD_PROC(ctx, pinN_tree, OID_AUTO, "function",
568		    CTLFLAG_RW | CTLTYPE_STRING, sc_sysctl,
569		    sizeof(struct bcm_gpio_sysctl), bcm_gpio_func_proc,
570		    "A", "Pin Function");
571	}
572}
573
574static int
575bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc, phandle_t node,
576	const char *propname, const char *label)
577{
578	int i, need_comma, npins, range_start, range_stop;
579	pcell_t *pins;
580
581	/* Get the property data. */
582	npins = OF_getencprop_alloc(node, propname, sizeof(*pins),
583	    (void **)&pins);
584	if (npins < 0)
585		return (-1);
586	if (npins == 0) {
587		free(pins, M_OFWPROP);
588		return (0);
589	}
590	for (i = 0; i < npins; i++)
591		sc->sc_ro_pins[i + sc->sc_ro_npins] = pins[i];
592	sc->sc_ro_npins += npins;
593	need_comma = 0;
594	device_printf(sc->sc_dev, "%s pins: ", label);
595	range_start = range_stop = pins[0];
596	for (i = 1; i < npins; i++) {
597		if (pins[i] != range_stop + 1) {
598			if (need_comma)
599				printf(",");
600			if (range_start != range_stop)
601				printf("%d-%d", range_start, range_stop);
602			else
603				printf("%d", range_start);
604			range_start = range_stop = pins[i];
605			need_comma = 1;
606		} else
607			range_stop++;
608	}
609	if (need_comma)
610		printf(",");
611	if (range_start != range_stop)
612		printf("%d-%d.\n", range_start, range_stop);
613	else
614		printf("%d.\n", range_start);
615	free(pins, M_OFWPROP);
616
617	return (0);
618}
619
620static int
621bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
622{
623	char *name;
624	phandle_t gpio, node, reserved;
625	ssize_t len;
626
627	/* Get read-only pins if they're provided */
628	gpio = ofw_bus_get_node(sc->sc_dev);
629	if (bcm_gpio_get_ro_pins(sc, gpio, "broadcom,read-only",
630	    "read-only") != 0)
631		return (0);
632	/* Traverse the GPIO subnodes to find the reserved pins node. */
633	reserved = 0;
634	node = OF_child(gpio);
635	while ((node != 0) && (reserved == 0)) {
636		len = OF_getprop_alloc(node, "name", 1, (void **)&name);
637		if (len == -1)
638			return (-1);
639		if (strcmp(name, "reserved") == 0)
640			reserved = node;
641		free(name, M_OFWPROP);
642		node = OF_peer(node);
643	}
644	if (reserved == 0)
645		return (-1);
646	/* Get the reserved pins. */
647	if (bcm_gpio_get_ro_pins(sc, reserved, "broadcom,pins",
648	    "reserved") != 0)
649		return (-1);
650
651	return (0);
652}
653
654static int
655bcm_gpio_probe(device_t dev)
656{
657
658	if (!ofw_bus_status_okay(dev))
659		return (ENXIO);
660
661	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
662		return (ENXIO);
663
664	device_set_desc(dev, "BCM2708/2835 GPIO controller");
665	return (BUS_PROBE_DEFAULT);
666}
667
668static int
669bcm_gpio_attach(device_t dev)
670{
671	struct bcm_gpio_softc *sc = device_get_softc(dev);
672	uint32_t func;
673	int i, j, rid;
674	phandle_t gpio;
675
676	sc->sc_dev = dev;
677
678	mtx_init(&sc->sc_mtx, "bcm gpio", "gpio", MTX_DEF);
679
680	rid = 0;
681	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
682	    RF_ACTIVE);
683	if (!sc->sc_mem_res) {
684		device_printf(dev, "cannot allocate memory window\n");
685		return (ENXIO);
686	}
687
688	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
689	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
690
691	rid = 0;
692	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
693	    RF_ACTIVE);
694	if (!sc->sc_irq_res) {
695		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
696		device_printf(dev, "cannot allocate interrupt\n");
697		return (ENXIO);
698	}
699
700	/* Find our node. */
701	gpio = ofw_bus_get_node(sc->sc_dev);
702
703	if (!OF_hasprop(gpio, "gpio-controller"))
704		/* Node is not a GPIO controller. */
705		goto fail;
706
707	/*
708	 * Find the read-only pins.  These are pins we never touch or bad
709	 * things could happen.
710	 */
711	if (bcm_gpio_get_reserved_pins(sc) == -1)
712		goto fail;
713
714	/* Initialize the software controlled pins. */
715	for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
716		snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
717		    "pin %d", j);
718		func = bcm_gpio_get_function(sc, j);
719		sc->sc_gpio_pins[i].gp_pin = j;
720		sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
721		sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
722		i++;
723	}
724	sc->sc_gpio_npins = i;
725
726	bcm_gpio_sysctl_init(sc);
727
728	device_add_child(dev, "gpioc", -1);
729	device_add_child(dev, "gpiobus", -1);
730
731	return (bus_generic_attach(dev));
732
733fail:
734	if (sc->sc_irq_res)
735		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
736	if (sc->sc_mem_res)
737		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
738	return (ENXIO);
739}
740
741static int
742bcm_gpio_detach(device_t dev)
743{
744
745	return (EBUSY);
746}
747
748static phandle_t
749bcm_gpio_get_node(device_t bus, device_t dev)
750{
751
752	/* We only have one child, the GPIO bus, which needs our own node. */
753	return (ofw_bus_get_node(bus));
754}
755
756static device_method_t bcm_gpio_methods[] = {
757	/* Device interface */
758	DEVMETHOD(device_probe,		bcm_gpio_probe),
759	DEVMETHOD(device_attach,	bcm_gpio_attach),
760	DEVMETHOD(device_detach,	bcm_gpio_detach),
761
762	/* GPIO protocol */
763	DEVMETHOD(gpio_pin_max,		bcm_gpio_pin_max),
764	DEVMETHOD(gpio_pin_getname,	bcm_gpio_pin_getname),
765	DEVMETHOD(gpio_pin_getflags,	bcm_gpio_pin_getflags),
766	DEVMETHOD(gpio_pin_getcaps,	bcm_gpio_pin_getcaps),
767	DEVMETHOD(gpio_pin_setflags,	bcm_gpio_pin_setflags),
768	DEVMETHOD(gpio_pin_get,		bcm_gpio_pin_get),
769	DEVMETHOD(gpio_pin_set,		bcm_gpio_pin_set),
770	DEVMETHOD(gpio_pin_toggle,	bcm_gpio_pin_toggle),
771
772	/* ofw_bus interface */
773	DEVMETHOD(ofw_bus_get_node,	bcm_gpio_get_node),
774
775	DEVMETHOD_END
776};
777
778static devclass_t bcm_gpio_devclass;
779
780static driver_t bcm_gpio_driver = {
781	"gpio",
782	bcm_gpio_methods,
783	sizeof(struct bcm_gpio_softc),
784};
785
786DRIVER_MODULE(bcm_gpio, simplebus, bcm_gpio_driver, bcm_gpio_devclass, 0, 0);
787