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