Deleted Added
full compact
bcm2835_gpio.c (274669) bcm2835_gpio.c (274670)
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>
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: head/sys/arm/broadcom/bcm2835/bcm2835_gpio.c 274669 2014-11-18 17:07:02Z imp $");
29__FBSDID("$FreeBSD: head/sys/arm/broadcom/bcm2835/bcm2835_gpio.c 274670 2014-11-18 17:22:08Z loos $");
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
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 int
112bcm_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
122static uint32_t
123bcm_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
138static void
139bcm_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
172static int
173bcm_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
198static uint32_t
199bcm_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
211static void
212bcm_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
229static void
230bcm_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 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), (1 << offset));
242 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), 0);
243 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), 0);
244}
245
246void
247bcm_gpio_set_alternate(device_t dev, uint32_t pin, uint32_t nfunc)
248{
249 struct bcm_gpio_softc *sc;
250 int i;
251
252 sc = device_get_softc(dev);
253 BCM_GPIO_LOCK(sc);
254
255 /* Disable pull-up or pull-down on pin. */
256 bcm_gpio_set_pud(sc, pin, BCM_GPIO_NONE);
257
258 /* And now set the pin function. */
259 bcm_gpio_set_function(sc, pin, nfunc);
260
261 /* Update the pin flags. */
262 for (i = 0; i < sc->sc_gpio_npins; i++) {
263 if (sc->sc_gpio_pins[i].gp_pin == pin)
264 break;
265 }
266 if (i < sc->sc_gpio_npins)
267 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(nfunc);
268
269 BCM_GPIO_UNLOCK(sc);
270}
271
272static void
273bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin,
274 unsigned int flags)
275{
276
277 BCM_GPIO_LOCK(sc);
278
279 /*
280 * Manage input/output.
281 */
282 if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
283 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
284 if (flags & GPIO_PIN_OUTPUT) {
285 pin->gp_flags |= GPIO_PIN_OUTPUT;
286 bcm_gpio_set_function(sc, pin->gp_pin,
287 BCM_GPIO_OUTPUT);
288 } else {
289 pin->gp_flags |= GPIO_PIN_INPUT;
290 bcm_gpio_set_function(sc, pin->gp_pin,
291 BCM_GPIO_INPUT);
292 }
293 }
294
295 /* Manage Pull-up/pull-down. */
296 pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
297 if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
298 if (flags & GPIO_PIN_PULLUP) {
299 pin->gp_flags |= GPIO_PIN_PULLUP;
300 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLUP);
301 } else {
302 pin->gp_flags |= GPIO_PIN_PULLDOWN;
303 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLDOWN);
304 }
305 } else
306 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_NONE);
307
308 BCM_GPIO_UNLOCK(sc);
309}
310
311static int
312bcm_gpio_pin_max(device_t dev, int *maxpin)
313{
314
315 *maxpin = BCM_GPIO_PINS - 1;
316 return (0);
317}
318
319static int
320bcm_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
321{
322 struct bcm_gpio_softc *sc = device_get_softc(dev);
323 int i;
324
325 for (i = 0; i < sc->sc_gpio_npins; i++) {
326 if (sc->sc_gpio_pins[i].gp_pin == pin)
327 break;
328 }
329
330 if (i >= sc->sc_gpio_npins)
331 return (EINVAL);
332
333 BCM_GPIO_LOCK(sc);
334 *caps = sc->sc_gpio_pins[i].gp_caps;
335 BCM_GPIO_UNLOCK(sc);
336
337 return (0);
338}
339
340static int
341bcm_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
342{
343 struct bcm_gpio_softc *sc = device_get_softc(dev);
344 int i;
345
346 for (i = 0; i < sc->sc_gpio_npins; i++) {
347 if (sc->sc_gpio_pins[i].gp_pin == pin)
348 break;
349 }
350
351 if (i >= sc->sc_gpio_npins)
352 return (EINVAL);
353
354 BCM_GPIO_LOCK(sc);
355 *flags = sc->sc_gpio_pins[i].gp_flags;
356 BCM_GPIO_UNLOCK(sc);
357
358 return (0);
359}
360
361static int
362bcm_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
363{
364 struct bcm_gpio_softc *sc = device_get_softc(dev);
365 int i;
366
367 for (i = 0; i < sc->sc_gpio_npins; i++) {
368 if (sc->sc_gpio_pins[i].gp_pin == pin)
369 break;
370 }
371
372 if (i >= sc->sc_gpio_npins)
373 return (EINVAL);
374
375 BCM_GPIO_LOCK(sc);
376 memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
377 BCM_GPIO_UNLOCK(sc);
378
379 return (0);
380}
381
382static int
383bcm_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
384{
385 struct bcm_gpio_softc *sc = device_get_softc(dev);
386 int i;
387
388 for (i = 0; i < sc->sc_gpio_npins; i++) {
389 if (sc->sc_gpio_pins[i].gp_pin == pin)
390 break;
391 }
392
393 if (i >= sc->sc_gpio_npins)
394 return (EINVAL);
395
396 /* We never touch on read-only/reserved pins. */
397 if (bcm_gpio_pin_is_ro(sc, pin))
398 return (EINVAL);
399
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
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 int
112bcm_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
122static uint32_t
123bcm_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
138static void
139bcm_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
172static int
173bcm_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
198static uint32_t
199bcm_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
211static void
212bcm_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
229static void
230bcm_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 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), (1 << offset));
242 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUD(0), 0);
243 BCM_GPIO_WRITE(sc, BCM_GPIO_GPPUDCLK(bank), 0);
244}
245
246void
247bcm_gpio_set_alternate(device_t dev, uint32_t pin, uint32_t nfunc)
248{
249 struct bcm_gpio_softc *sc;
250 int i;
251
252 sc = device_get_softc(dev);
253 BCM_GPIO_LOCK(sc);
254
255 /* Disable pull-up or pull-down on pin. */
256 bcm_gpio_set_pud(sc, pin, BCM_GPIO_NONE);
257
258 /* And now set the pin function. */
259 bcm_gpio_set_function(sc, pin, nfunc);
260
261 /* Update the pin flags. */
262 for (i = 0; i < sc->sc_gpio_npins; i++) {
263 if (sc->sc_gpio_pins[i].gp_pin == pin)
264 break;
265 }
266 if (i < sc->sc_gpio_npins)
267 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(nfunc);
268
269 BCM_GPIO_UNLOCK(sc);
270}
271
272static void
273bcm_gpio_pin_configure(struct bcm_gpio_softc *sc, struct gpio_pin *pin,
274 unsigned int flags)
275{
276
277 BCM_GPIO_LOCK(sc);
278
279 /*
280 * Manage input/output.
281 */
282 if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) {
283 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT);
284 if (flags & GPIO_PIN_OUTPUT) {
285 pin->gp_flags |= GPIO_PIN_OUTPUT;
286 bcm_gpio_set_function(sc, pin->gp_pin,
287 BCM_GPIO_OUTPUT);
288 } else {
289 pin->gp_flags |= GPIO_PIN_INPUT;
290 bcm_gpio_set_function(sc, pin->gp_pin,
291 BCM_GPIO_INPUT);
292 }
293 }
294
295 /* Manage Pull-up/pull-down. */
296 pin->gp_flags &= ~(GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN);
297 if (flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) {
298 if (flags & GPIO_PIN_PULLUP) {
299 pin->gp_flags |= GPIO_PIN_PULLUP;
300 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLUP);
301 } else {
302 pin->gp_flags |= GPIO_PIN_PULLDOWN;
303 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_PULLDOWN);
304 }
305 } else
306 bcm_gpio_set_pud(sc, pin->gp_pin, BCM_GPIO_NONE);
307
308 BCM_GPIO_UNLOCK(sc);
309}
310
311static int
312bcm_gpio_pin_max(device_t dev, int *maxpin)
313{
314
315 *maxpin = BCM_GPIO_PINS - 1;
316 return (0);
317}
318
319static int
320bcm_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
321{
322 struct bcm_gpio_softc *sc = device_get_softc(dev);
323 int i;
324
325 for (i = 0; i < sc->sc_gpio_npins; i++) {
326 if (sc->sc_gpio_pins[i].gp_pin == pin)
327 break;
328 }
329
330 if (i >= sc->sc_gpio_npins)
331 return (EINVAL);
332
333 BCM_GPIO_LOCK(sc);
334 *caps = sc->sc_gpio_pins[i].gp_caps;
335 BCM_GPIO_UNLOCK(sc);
336
337 return (0);
338}
339
340static int
341bcm_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
342{
343 struct bcm_gpio_softc *sc = device_get_softc(dev);
344 int i;
345
346 for (i = 0; i < sc->sc_gpio_npins; i++) {
347 if (sc->sc_gpio_pins[i].gp_pin == pin)
348 break;
349 }
350
351 if (i >= sc->sc_gpio_npins)
352 return (EINVAL);
353
354 BCM_GPIO_LOCK(sc);
355 *flags = sc->sc_gpio_pins[i].gp_flags;
356 BCM_GPIO_UNLOCK(sc);
357
358 return (0);
359}
360
361static int
362bcm_gpio_pin_getname(device_t dev, uint32_t pin, char *name)
363{
364 struct bcm_gpio_softc *sc = device_get_softc(dev);
365 int i;
366
367 for (i = 0; i < sc->sc_gpio_npins; i++) {
368 if (sc->sc_gpio_pins[i].gp_pin == pin)
369 break;
370 }
371
372 if (i >= sc->sc_gpio_npins)
373 return (EINVAL);
374
375 BCM_GPIO_LOCK(sc);
376 memcpy(name, sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME);
377 BCM_GPIO_UNLOCK(sc);
378
379 return (0);
380}
381
382static int
383bcm_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
384{
385 struct bcm_gpio_softc *sc = device_get_softc(dev);
386 int i;
387
388 for (i = 0; i < sc->sc_gpio_npins; i++) {
389 if (sc->sc_gpio_pins[i].gp_pin == pin)
390 break;
391 }
392
393 if (i >= sc->sc_gpio_npins)
394 return (EINVAL);
395
396 /* We never touch on read-only/reserved pins. */
397 if (bcm_gpio_pin_is_ro(sc, pin))
398 return (EINVAL);
399
400 /* Check for unwanted flags. */
401 if ((flags & sc->sc_gpio_pins[i].gp_caps) != flags)
402 return (EINVAL);
403
404 /* Can't mix input/output together. */
405 if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) ==
406 (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT))
407 return (EINVAL);
408
409 /* Can't mix pull-up/pull-down together. */
410 if ((flags & (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN)) ==
411 (GPIO_PIN_PULLUP|GPIO_PIN_PULLDOWN))
412 return (EINVAL);
413
414 bcm_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
415
416 return (0);
417}
418
419static int
420bcm_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
421{
422 struct bcm_gpio_softc *sc = device_get_softc(dev);
423 uint32_t bank, offset;
424 int i;
425
426 for (i = 0; i < sc->sc_gpio_npins; i++) {
427 if (sc->sc_gpio_pins[i].gp_pin == pin)
428 break;
429 }
430
431 if (i >= sc->sc_gpio_npins)
432 return (EINVAL);
433
434 /* We never write to read-only/reserved pins. */
435 if (bcm_gpio_pin_is_ro(sc, pin))
436 return (EINVAL);
437
438 bank = pin / 32;
439 offset = pin - 32 * bank;
440
441 BCM_GPIO_LOCK(sc);
442 if (value)
443 BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
444 else
445 BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
446 BCM_GPIO_UNLOCK(sc);
447
448 return (0);
449}
450
451static int
452bcm_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
453{
454 struct bcm_gpio_softc *sc = device_get_softc(dev);
455 uint32_t bank, offset, reg_data;
456 int i;
457
458 for (i = 0; i < sc->sc_gpio_npins; i++) {
459 if (sc->sc_gpio_pins[i].gp_pin == pin)
460 break;
461 }
462
463 if (i >= sc->sc_gpio_npins)
464 return (EINVAL);
465
466 bank = pin / 32;
467 offset = pin - 32 * bank;
468
469 BCM_GPIO_LOCK(sc);
470 reg_data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
471 BCM_GPIO_UNLOCK(sc);
472 *val = (reg_data & (1 << offset)) ? 1 : 0;
473
474 return (0);
475}
476
477static int
478bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
479{
480 struct bcm_gpio_softc *sc = device_get_softc(dev);
481 uint32_t bank, data, offset;
482 int i;
483
484 for (i = 0; i < sc->sc_gpio_npins; i++) {
485 if (sc->sc_gpio_pins[i].gp_pin == pin)
486 break;
487 }
488
489 if (i >= sc->sc_gpio_npins)
490 return (EINVAL);
491
492 /* We never write to read-only/reserved pins. */
493 if (bcm_gpio_pin_is_ro(sc, pin))
494 return (EINVAL);
495
496 bank = pin / 32;
497 offset = pin - 32 * bank;
498
499 BCM_GPIO_LOCK(sc);
500 data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
501 if (data & (1 << offset))
502 BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
503 else
504 BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
505 BCM_GPIO_UNLOCK(sc);
506
507 return (0);
508}
509
510static int
511bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc)
512{
513 int i, len;
514 pcell_t pins[BCM_GPIO_PINS];
515 phandle_t gpio;
516
517 /* Find the gpio node to start. */
518 gpio = ofw_bus_get_node(sc->sc_dev);
519
520 len = OF_getproplen(gpio, "broadcom,read-only");
521 if (len < 0 || len > sizeof(pins))
522 return (-1);
523
524 if (OF_getprop(gpio, "broadcom,read-only", &pins, len) < 0)
525 return (-1);
526
527 sc->sc_ro_npins = len / sizeof(pcell_t);
528
529 device_printf(sc->sc_dev, "read-only pins: ");
530 for (i = 0; i < sc->sc_ro_npins; i++) {
531 sc->sc_ro_pins[i] = fdt32_to_cpu(pins[i]);
532 if (i > 0)
533 printf(",");
534 printf("%d", sc->sc_ro_pins[i]);
535 }
536 if (i > 0)
537 printf(".");
538 printf("\n");
539
540 return (0);
541}
542
543static int
544bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
545{
546 char buf[16];
547 struct bcm_gpio_softc *sc;
548 struct bcm_gpio_sysctl *sc_sysctl;
549 uint32_t nfunc;
550 int error;
551
552 sc_sysctl = arg1;
553 sc = sc_sysctl->sc;
554
555 /* Get the current pin function. */
556 nfunc = bcm_gpio_get_function(sc, sc_sysctl->pin);
557 bcm_gpio_func_str(nfunc, buf, sizeof(buf));
558
559 error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
560 if (error != 0 || req->newptr == NULL)
561 return (error);
562
563 /* Parse the user supplied string and check for a valid pin function. */
564 if (bcm_gpio_str_func(buf, &nfunc) != 0)
565 return (EINVAL);
566
567 /* Update the pin alternate function. */
568 bcm_gpio_set_alternate(sc->sc_dev, sc_sysctl->pin, nfunc);
569
570 return (0);
571}
572
573static void
574bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
575{
576 char pinbuf[3];
577 struct bcm_gpio_sysctl *sc_sysctl;
578 struct sysctl_ctx_list *ctx;
579 struct sysctl_oid *tree_node, *pin_node, *pinN_node;
580 struct sysctl_oid_list *tree, *pin_tree, *pinN_tree;
581 int i;
582
583 /*
584 * Add per-pin sysctl tree/handlers.
585 */
586 ctx = device_get_sysctl_ctx(sc->sc_dev);
587 tree_node = device_get_sysctl_tree(sc->sc_dev);
588 tree = SYSCTL_CHILDREN(tree_node);
589 pin_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "pin",
590 CTLFLAG_RD, NULL, "GPIO Pins");
591 pin_tree = SYSCTL_CHILDREN(pin_node);
592
593 for (i = 0; i < sc->sc_gpio_npins; i++) {
594
595 snprintf(pinbuf, sizeof(pinbuf), "%d", i);
596 pinN_node = SYSCTL_ADD_NODE(ctx, pin_tree, OID_AUTO, pinbuf,
597 CTLFLAG_RD, NULL, "GPIO Pin");
598 pinN_tree = SYSCTL_CHILDREN(pinN_node);
599
600 sc->sc_sysctl[i].sc = sc;
601 sc_sysctl = &sc->sc_sysctl[i];
602 sc_sysctl->sc = sc;
603 sc_sysctl->pin = sc->sc_gpio_pins[i].gp_pin;
604 SYSCTL_ADD_PROC(ctx, pinN_tree, OID_AUTO, "function",
605 CTLFLAG_RW | CTLTYPE_STRING, sc_sysctl,
606 sizeof(struct bcm_gpio_sysctl), bcm_gpio_func_proc,
607 "A", "Pin Function");
608 }
609}
610
611static int
612bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
613{
614 int i, j, len, npins;
615 pcell_t pins[BCM_GPIO_PINS];
616 phandle_t gpio, node, reserved;
617 char name[32];
618
619 /* Get read-only pins. */
620 if (bcm_gpio_get_ro_pins(sc) != 0)
621 return (-1);
622
623 /* Find the gpio/reserved pins node to start. */
624 gpio = ofw_bus_get_node(sc->sc_dev);
625 node = OF_child(gpio);
626
627 /*
628 * Find reserved node
629 */
630 reserved = 0;
631 while ((node != 0) && (reserved == 0)) {
632 len = OF_getprop(node, "name", name,
633 sizeof(name) - 1);
634 name[len] = 0;
635 if (strcmp(name, "reserved") == 0)
636 reserved = node;
637 node = OF_peer(node);
638 }
639
640 if (reserved == 0)
641 return (-1);
642
643 /* Get the reserved pins. */
644 len = OF_getproplen(reserved, "broadcom,pins");
645 if (len < 0 || len > sizeof(pins))
646 return (-1);
647
648 if (OF_getprop(reserved, "broadcom,pins", &pins, len) < 0)
649 return (-1);
650
651 npins = len / sizeof(pcell_t);
652
653 j = 0;
654 device_printf(sc->sc_dev, "reserved pins: ");
655 for (i = 0; i < npins; i++) {
656 if (i > 0)
657 printf(",");
658 printf("%d", fdt32_to_cpu(pins[i]));
659 /* Some pins maybe already on the list of read-only pins. */
660 if (bcm_gpio_pin_is_ro(sc, fdt32_to_cpu(pins[i])))
661 continue;
662 sc->sc_ro_pins[j++ + sc->sc_ro_npins] = fdt32_to_cpu(pins[i]);
663 }
664 sc->sc_ro_npins += j;
665 if (i > 0)
666 printf(".");
667 printf("\n");
668
669 return (0);
670}
671
672static int
673bcm_gpio_probe(device_t dev)
674{
675
676 if (!ofw_bus_status_okay(dev))
677 return (ENXIO);
678
679 if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-gpio"))
680 return (ENXIO);
681
682 device_set_desc(dev, "BCM2708/2835 GPIO controller");
683 return (BUS_PROBE_DEFAULT);
684}
685
686static int
687bcm_gpio_attach(device_t dev)
688{
689 struct bcm_gpio_softc *sc = device_get_softc(dev);
690 uint32_t func;
691 int i, j, rid;
692 phandle_t gpio;
693
694 sc->sc_dev = dev;
695
696 mtx_init(&sc->sc_mtx, "bcm gpio", "gpio", MTX_DEF);
697
698 rid = 0;
699 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
700 RF_ACTIVE);
701 if (!sc->sc_mem_res) {
702 device_printf(dev, "cannot allocate memory window\n");
703 return (ENXIO);
704 }
705
706 sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
707 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
708
709 rid = 0;
710 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
711 RF_ACTIVE);
712 if (!sc->sc_irq_res) {
713 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
714 device_printf(dev, "cannot allocate interrupt\n");
715 return (ENXIO);
716 }
717
718 /* Find our node. */
719 gpio = ofw_bus_get_node(sc->sc_dev);
720
721 if (!OF_hasprop(gpio, "gpio-controller"))
722 /* Node is not a GPIO controller. */
723 goto fail;
724
725 /*
726 * Find the read-only pins. These are pins we never touch or bad
727 * things could happen.
728 */
729 if (bcm_gpio_get_reserved_pins(sc) == -1)
730 goto fail;
731
732 /* Initialize the software controlled pins. */
733 for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
734 if (bcm_gpio_pin_is_ro(sc, j))
735 continue;
736 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
737 "pin %d", j);
738 func = bcm_gpio_get_function(sc, j);
739 sc->sc_gpio_pins[i].gp_pin = j;
740 sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
741 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
742 i++;
743 }
744 sc->sc_gpio_npins = i;
745
746 bcm_gpio_sysctl_init(sc);
747
748 device_add_child(dev, "gpioc", -1);
749 device_add_child(dev, "gpiobus", -1);
750
751 return (bus_generic_attach(dev));
752
753fail:
754 if (sc->sc_irq_res)
755 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
756 if (sc->sc_mem_res)
757 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
758 return (ENXIO);
759}
760
761static int
762bcm_gpio_detach(device_t dev)
763{
764
765 return (EBUSY);
766}
767
768static phandle_t
769bcm_gpio_get_node(device_t bus, device_t dev)
770{
771
772 /* We only have one child, the GPIO bus, which needs our own node. */
773 return (ofw_bus_get_node(bus));
774}
775
776static device_method_t bcm_gpio_methods[] = {
777 /* Device interface */
778 DEVMETHOD(device_probe, bcm_gpio_probe),
779 DEVMETHOD(device_attach, bcm_gpio_attach),
780 DEVMETHOD(device_detach, bcm_gpio_detach),
781
782 /* GPIO protocol */
783 DEVMETHOD(gpio_pin_max, bcm_gpio_pin_max),
784 DEVMETHOD(gpio_pin_getname, bcm_gpio_pin_getname),
785 DEVMETHOD(gpio_pin_getflags, bcm_gpio_pin_getflags),
786 DEVMETHOD(gpio_pin_getcaps, bcm_gpio_pin_getcaps),
787 DEVMETHOD(gpio_pin_setflags, bcm_gpio_pin_setflags),
788 DEVMETHOD(gpio_pin_get, bcm_gpio_pin_get),
789 DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set),
790 DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle),
791
792 /* ofw_bus interface */
793 DEVMETHOD(ofw_bus_get_node, bcm_gpio_get_node),
794
795 DEVMETHOD_END
796};
797
798static devclass_t bcm_gpio_devclass;
799
800static driver_t bcm_gpio_driver = {
801 "gpio",
802 bcm_gpio_methods,
803 sizeof(struct bcm_gpio_softc),
804};
805
806DRIVER_MODULE(bcm_gpio, simplebus, bcm_gpio_driver, bcm_gpio_devclass, 0, 0);
400 bcm_gpio_pin_configure(sc, &sc->sc_gpio_pins[i], flags);
401
402 return (0);
403}
404
405static int
406bcm_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
407{
408 struct bcm_gpio_softc *sc = device_get_softc(dev);
409 uint32_t bank, offset;
410 int i;
411
412 for (i = 0; i < sc->sc_gpio_npins; i++) {
413 if (sc->sc_gpio_pins[i].gp_pin == pin)
414 break;
415 }
416
417 if (i >= sc->sc_gpio_npins)
418 return (EINVAL);
419
420 /* We never write to read-only/reserved pins. */
421 if (bcm_gpio_pin_is_ro(sc, pin))
422 return (EINVAL);
423
424 bank = pin / 32;
425 offset = pin - 32 * bank;
426
427 BCM_GPIO_LOCK(sc);
428 if (value)
429 BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
430 else
431 BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
432 BCM_GPIO_UNLOCK(sc);
433
434 return (0);
435}
436
437static int
438bcm_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val)
439{
440 struct bcm_gpio_softc *sc = device_get_softc(dev);
441 uint32_t bank, offset, reg_data;
442 int i;
443
444 for (i = 0; i < sc->sc_gpio_npins; i++) {
445 if (sc->sc_gpio_pins[i].gp_pin == pin)
446 break;
447 }
448
449 if (i >= sc->sc_gpio_npins)
450 return (EINVAL);
451
452 bank = pin / 32;
453 offset = pin - 32 * bank;
454
455 BCM_GPIO_LOCK(sc);
456 reg_data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
457 BCM_GPIO_UNLOCK(sc);
458 *val = (reg_data & (1 << offset)) ? 1 : 0;
459
460 return (0);
461}
462
463static int
464bcm_gpio_pin_toggle(device_t dev, uint32_t pin)
465{
466 struct bcm_gpio_softc *sc = device_get_softc(dev);
467 uint32_t bank, data, offset;
468 int i;
469
470 for (i = 0; i < sc->sc_gpio_npins; i++) {
471 if (sc->sc_gpio_pins[i].gp_pin == pin)
472 break;
473 }
474
475 if (i >= sc->sc_gpio_npins)
476 return (EINVAL);
477
478 /* We never write to read-only/reserved pins. */
479 if (bcm_gpio_pin_is_ro(sc, pin))
480 return (EINVAL);
481
482 bank = pin / 32;
483 offset = pin - 32 * bank;
484
485 BCM_GPIO_LOCK(sc);
486 data = BCM_GPIO_READ(sc, BCM_GPIO_GPLEV(bank));
487 if (data & (1 << offset))
488 BCM_GPIO_WRITE(sc, BCM_GPIO_GPCLR(bank), (1 << offset));
489 else
490 BCM_GPIO_WRITE(sc, BCM_GPIO_GPSET(bank), (1 << offset));
491 BCM_GPIO_UNLOCK(sc);
492
493 return (0);
494}
495
496static int
497bcm_gpio_get_ro_pins(struct bcm_gpio_softc *sc)
498{
499 int i, len;
500 pcell_t pins[BCM_GPIO_PINS];
501 phandle_t gpio;
502
503 /* Find the gpio node to start. */
504 gpio = ofw_bus_get_node(sc->sc_dev);
505
506 len = OF_getproplen(gpio, "broadcom,read-only");
507 if (len < 0 || len > sizeof(pins))
508 return (-1);
509
510 if (OF_getprop(gpio, "broadcom,read-only", &pins, len) < 0)
511 return (-1);
512
513 sc->sc_ro_npins = len / sizeof(pcell_t);
514
515 device_printf(sc->sc_dev, "read-only pins: ");
516 for (i = 0; i < sc->sc_ro_npins; i++) {
517 sc->sc_ro_pins[i] = fdt32_to_cpu(pins[i]);
518 if (i > 0)
519 printf(",");
520 printf("%d", sc->sc_ro_pins[i]);
521 }
522 if (i > 0)
523 printf(".");
524 printf("\n");
525
526 return (0);
527}
528
529static int
530bcm_gpio_func_proc(SYSCTL_HANDLER_ARGS)
531{
532 char buf[16];
533 struct bcm_gpio_softc *sc;
534 struct bcm_gpio_sysctl *sc_sysctl;
535 uint32_t nfunc;
536 int error;
537
538 sc_sysctl = arg1;
539 sc = sc_sysctl->sc;
540
541 /* Get the current pin function. */
542 nfunc = bcm_gpio_get_function(sc, sc_sysctl->pin);
543 bcm_gpio_func_str(nfunc, buf, sizeof(buf));
544
545 error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
546 if (error != 0 || req->newptr == NULL)
547 return (error);
548
549 /* Parse the user supplied string and check for a valid pin function. */
550 if (bcm_gpio_str_func(buf, &nfunc) != 0)
551 return (EINVAL);
552
553 /* Update the pin alternate function. */
554 bcm_gpio_set_alternate(sc->sc_dev, sc_sysctl->pin, nfunc);
555
556 return (0);
557}
558
559static void
560bcm_gpio_sysctl_init(struct bcm_gpio_softc *sc)
561{
562 char pinbuf[3];
563 struct bcm_gpio_sysctl *sc_sysctl;
564 struct sysctl_ctx_list *ctx;
565 struct sysctl_oid *tree_node, *pin_node, *pinN_node;
566 struct sysctl_oid_list *tree, *pin_tree, *pinN_tree;
567 int i;
568
569 /*
570 * Add per-pin sysctl tree/handlers.
571 */
572 ctx = device_get_sysctl_ctx(sc->sc_dev);
573 tree_node = device_get_sysctl_tree(sc->sc_dev);
574 tree = SYSCTL_CHILDREN(tree_node);
575 pin_node = SYSCTL_ADD_NODE(ctx, tree, OID_AUTO, "pin",
576 CTLFLAG_RD, NULL, "GPIO Pins");
577 pin_tree = SYSCTL_CHILDREN(pin_node);
578
579 for (i = 0; i < sc->sc_gpio_npins; i++) {
580
581 snprintf(pinbuf, sizeof(pinbuf), "%d", i);
582 pinN_node = SYSCTL_ADD_NODE(ctx, pin_tree, OID_AUTO, pinbuf,
583 CTLFLAG_RD, NULL, "GPIO Pin");
584 pinN_tree = SYSCTL_CHILDREN(pinN_node);
585
586 sc->sc_sysctl[i].sc = sc;
587 sc_sysctl = &sc->sc_sysctl[i];
588 sc_sysctl->sc = sc;
589 sc_sysctl->pin = sc->sc_gpio_pins[i].gp_pin;
590 SYSCTL_ADD_PROC(ctx, pinN_tree, OID_AUTO, "function",
591 CTLFLAG_RW | CTLTYPE_STRING, sc_sysctl,
592 sizeof(struct bcm_gpio_sysctl), bcm_gpio_func_proc,
593 "A", "Pin Function");
594 }
595}
596
597static int
598bcm_gpio_get_reserved_pins(struct bcm_gpio_softc *sc)
599{
600 int i, j, len, npins;
601 pcell_t pins[BCM_GPIO_PINS];
602 phandle_t gpio, node, reserved;
603 char name[32];
604
605 /* Get read-only pins. */
606 if (bcm_gpio_get_ro_pins(sc) != 0)
607 return (-1);
608
609 /* Find the gpio/reserved pins node to start. */
610 gpio = ofw_bus_get_node(sc->sc_dev);
611 node = OF_child(gpio);
612
613 /*
614 * Find reserved node
615 */
616 reserved = 0;
617 while ((node != 0) && (reserved == 0)) {
618 len = OF_getprop(node, "name", name,
619 sizeof(name) - 1);
620 name[len] = 0;
621 if (strcmp(name, "reserved") == 0)
622 reserved = node;
623 node = OF_peer(node);
624 }
625
626 if (reserved == 0)
627 return (-1);
628
629 /* Get the reserved pins. */
630 len = OF_getproplen(reserved, "broadcom,pins");
631 if (len < 0 || len > sizeof(pins))
632 return (-1);
633
634 if (OF_getprop(reserved, "broadcom,pins", &pins, len) < 0)
635 return (-1);
636
637 npins = len / sizeof(pcell_t);
638
639 j = 0;
640 device_printf(sc->sc_dev, "reserved pins: ");
641 for (i = 0; i < npins; i++) {
642 if (i > 0)
643 printf(",");
644 printf("%d", fdt32_to_cpu(pins[i]));
645 /* Some pins maybe already on the list of read-only pins. */
646 if (bcm_gpio_pin_is_ro(sc, fdt32_to_cpu(pins[i])))
647 continue;
648 sc->sc_ro_pins[j++ + sc->sc_ro_npins] = fdt32_to_cpu(pins[i]);
649 }
650 sc->sc_ro_npins += j;
651 if (i > 0)
652 printf(".");
653 printf("\n");
654
655 return (0);
656}
657
658static int
659bcm_gpio_probe(device_t dev)
660{
661
662 if (!ofw_bus_status_okay(dev))
663 return (ENXIO);
664
665 if (!ofw_bus_is_compatible(dev, "broadcom,bcm2835-gpio"))
666 return (ENXIO);
667
668 device_set_desc(dev, "BCM2708/2835 GPIO controller");
669 return (BUS_PROBE_DEFAULT);
670}
671
672static int
673bcm_gpio_attach(device_t dev)
674{
675 struct bcm_gpio_softc *sc = device_get_softc(dev);
676 uint32_t func;
677 int i, j, rid;
678 phandle_t gpio;
679
680 sc->sc_dev = dev;
681
682 mtx_init(&sc->sc_mtx, "bcm gpio", "gpio", MTX_DEF);
683
684 rid = 0;
685 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
686 RF_ACTIVE);
687 if (!sc->sc_mem_res) {
688 device_printf(dev, "cannot allocate memory window\n");
689 return (ENXIO);
690 }
691
692 sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
693 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
694
695 rid = 0;
696 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
697 RF_ACTIVE);
698 if (!sc->sc_irq_res) {
699 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
700 device_printf(dev, "cannot allocate interrupt\n");
701 return (ENXIO);
702 }
703
704 /* Find our node. */
705 gpio = ofw_bus_get_node(sc->sc_dev);
706
707 if (!OF_hasprop(gpio, "gpio-controller"))
708 /* Node is not a GPIO controller. */
709 goto fail;
710
711 /*
712 * Find the read-only pins. These are pins we never touch or bad
713 * things could happen.
714 */
715 if (bcm_gpio_get_reserved_pins(sc) == -1)
716 goto fail;
717
718 /* Initialize the software controlled pins. */
719 for (i = 0, j = 0; j < BCM_GPIO_PINS; j++) {
720 if (bcm_gpio_pin_is_ro(sc, j))
721 continue;
722 snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
723 "pin %d", j);
724 func = bcm_gpio_get_function(sc, j);
725 sc->sc_gpio_pins[i].gp_pin = j;
726 sc->sc_gpio_pins[i].gp_caps = BCM_GPIO_DEFAULT_CAPS;
727 sc->sc_gpio_pins[i].gp_flags = bcm_gpio_func_flag(func);
728 i++;
729 }
730 sc->sc_gpio_npins = i;
731
732 bcm_gpio_sysctl_init(sc);
733
734 device_add_child(dev, "gpioc", -1);
735 device_add_child(dev, "gpiobus", -1);
736
737 return (bus_generic_attach(dev));
738
739fail:
740 if (sc->sc_irq_res)
741 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
742 if (sc->sc_mem_res)
743 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
744 return (ENXIO);
745}
746
747static int
748bcm_gpio_detach(device_t dev)
749{
750
751 return (EBUSY);
752}
753
754static phandle_t
755bcm_gpio_get_node(device_t bus, device_t dev)
756{
757
758 /* We only have one child, the GPIO bus, which needs our own node. */
759 return (ofw_bus_get_node(bus));
760}
761
762static device_method_t bcm_gpio_methods[] = {
763 /* Device interface */
764 DEVMETHOD(device_probe, bcm_gpio_probe),
765 DEVMETHOD(device_attach, bcm_gpio_attach),
766 DEVMETHOD(device_detach, bcm_gpio_detach),
767
768 /* GPIO protocol */
769 DEVMETHOD(gpio_pin_max, bcm_gpio_pin_max),
770 DEVMETHOD(gpio_pin_getname, bcm_gpio_pin_getname),
771 DEVMETHOD(gpio_pin_getflags, bcm_gpio_pin_getflags),
772 DEVMETHOD(gpio_pin_getcaps, bcm_gpio_pin_getcaps),
773 DEVMETHOD(gpio_pin_setflags, bcm_gpio_pin_setflags),
774 DEVMETHOD(gpio_pin_get, bcm_gpio_pin_get),
775 DEVMETHOD(gpio_pin_set, bcm_gpio_pin_set),
776 DEVMETHOD(gpio_pin_toggle, bcm_gpio_pin_toggle),
777
778 /* ofw_bus interface */
779 DEVMETHOD(ofw_bus_get_node, bcm_gpio_get_node),
780
781 DEVMETHOD_END
782};
783
784static devclass_t bcm_gpio_devclass;
785
786static driver_t bcm_gpio_driver = {
787 "gpio",
788 bcm_gpio_methods,
789 sizeof(struct bcm_gpio_softc),
790};
791
792DRIVER_MODULE(bcm_gpio, simplebus, bcm_gpio_driver, bcm_gpio_devclass, 0, 0);