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