ar71xx_gpio.c revision 213286
1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3 * Copyright (c) 2009, 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 unmodified, this list of conditions, and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* 30 * GPIO driver for AR71xx 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_gpio.c 213286 2010-09-29 23:06:41Z gonzo $"); 35 36#include <sys/param.h> 37#include <sys/systm.h> 38#include <sys/bus.h> 39 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/rman.h> 43#include <sys/lock.h> 44#include <sys/mutex.h> 45#include <sys/gpio.h> 46 47#include <machine/bus.h> 48#include <machine/resource.h> 49#include <mips/atheros/ar71xxreg.h> 50#include <mips/atheros/ar71xx_gpiovar.h> 51 52#include "gpio_if.h" 53 54#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) 55 56struct ar71xx_gpio_pin { 57 const char *name; 58 int pin; 59 int flags; 60}; 61 62static struct ar71xx_gpio_pin ar71xx_gpio_pins[] = { 63 { "RFled", 2, GPIO_PIN_OUTPUT}, 64 { "SW4", 8, GPIO_PIN_INPUT}, 65 { NULL, 0, 0}, 66}; 67 68/* 69 * Helpers 70 */ 71static void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 72 uint32_t mask); 73static void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 74 uint32_t mask); 75static void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 76 struct gpio_pin *pin, uint32_t flags); 77 78/* 79 * Driver stuff 80 */ 81static int ar71xx_gpio_probe(device_t dev); 82static int ar71xx_gpio_attach(device_t dev); 83static int ar71xx_gpio_detach(device_t dev); 84static int ar71xx_gpio_filter(void *arg); 85static void ar71xx_gpio_intr(void *arg); 86 87/* 88 * GPIO interface 89 */ 90static int ar71xx_gpio_pin_max(device_t dev, int *maxpin); 91static int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 92static int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 93 *flags); 94static int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 95static int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 96static int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 97static int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 98static int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin); 99 100static void 101ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask) 102{ 103 GPIO_LOCK(sc); 104 GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 105 GPIO_UNLOCK(sc); 106} 107 108static void 109ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask) 110{ 111 GPIO_LOCK(sc); 112 GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 113 GPIO_UNLOCK(sc); 114} 115 116static void 117ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, 118 unsigned int flags) 119{ 120 uint32_t mask; 121 122 mask = 1 << pin->gp_pin; 123 GPIO_LOCK(sc); 124 125 /* 126 * Manage input/output 127 */ 128 if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 129 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 130 if (flags & GPIO_PIN_OUTPUT) { 131 pin->gp_flags |= GPIO_PIN_OUTPUT; 132 GPIO_SET_BITS(sc, AR71XX_GPIO_OE, mask); 133 } 134 else { 135 pin->gp_flags |= GPIO_PIN_INPUT; 136 GPIO_CLEAR_BITS(sc, AR71XX_GPIO_OE, mask); 137 } 138 } 139 140 GPIO_UNLOCK(sc); 141} 142 143static int 144ar71xx_gpio_pin_max(device_t dev, int *maxpin) 145{ 146 147 *maxpin = AR71XX_GPIO_PINS - 1; 148 return (0); 149} 150 151static int 152ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 153{ 154 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 155 int i; 156 157 for (i = 0; i < sc->gpio_npins; i++) { 158 if (sc->gpio_pins[i].gp_pin == pin) 159 break; 160 } 161 162 if (i >= sc->gpio_npins) 163 return (EINVAL); 164 165 GPIO_LOCK(sc); 166 *caps = sc->gpio_pins[i].gp_caps; 167 GPIO_UNLOCK(sc); 168 169 return (0); 170} 171 172static int 173ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 174{ 175 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 176 int i; 177 178 for (i = 0; i < sc->gpio_npins; i++) { 179 if (sc->gpio_pins[i].gp_pin == pin) 180 break; 181 } 182 183 if (i >= sc->gpio_npins) 184 return (EINVAL); 185 186 GPIO_LOCK(sc); 187 *flags = sc->gpio_pins[i].gp_flags; 188 GPIO_UNLOCK(sc); 189 190 return (0); 191} 192 193static int 194ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 195{ 196 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 197 int i; 198 199 for (i = 0; i < sc->gpio_npins; i++) { 200 if (sc->gpio_pins[i].gp_pin == pin) 201 break; 202 } 203 204 if (i >= sc->gpio_npins) 205 return (EINVAL); 206 207 GPIO_LOCK(sc); 208 memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 209 GPIO_UNLOCK(sc); 210 211 return (0); 212} 213 214static int 215ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 216{ 217 int i; 218 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 219 220 for (i = 0; i < sc->gpio_npins; i++) { 221 if (sc->gpio_pins[i].gp_pin == pin) 222 break; 223 } 224 225 if (i >= sc->gpio_npins) 226 return (EINVAL); 227 228 /* Filter out unwanted flags */ 229 if ((flags &= sc->gpio_pins[i].gp_caps) != flags) 230 return (EINVAL); 231 232 /* Can't mix input/output together */ 233 if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 234 (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 235 return (EINVAL); 236 237 ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 238 return (0); 239} 240 241static int 242ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 243{ 244 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 245 int i; 246 247 for (i = 0; i < sc->gpio_npins; i++) { 248 if (sc->gpio_pins[i].gp_pin == pin) 249 break; 250 } 251 252 if (i >= sc->gpio_npins) 253 return (EINVAL); 254 255 GPIO_LOCK(sc); 256 if (value) 257 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 258 else 259 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 260 GPIO_UNLOCK(sc); 261 262 return (0); 263} 264 265static int 266ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 267{ 268 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 269 int i; 270 271 for (i = 0; i < sc->gpio_npins; i++) { 272 if (sc->gpio_pins[i].gp_pin == pin) 273 break; 274 } 275 276 if (i >= sc->gpio_npins) 277 return (EINVAL); 278 279 GPIO_LOCK(sc); 280 *val = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 281 GPIO_UNLOCK(sc); 282 283 return (0); 284} 285 286static int 287ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin) 288{ 289 int res, i; 290 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 291 292 for (i = 0; i < sc->gpio_npins; i++) { 293 if (sc->gpio_pins[i].gp_pin == pin) 294 break; 295 } 296 297 if (i >= sc->gpio_npins) 298 return (EINVAL); 299 300 GPIO_LOCK(sc); 301 res = (GPIO_READ(sc, AR71XX_GPIO_IN) & (1 << pin)) ? 1 : 0; 302 if (res) 303 GPIO_WRITE(sc, AR71XX_GPIO_CLEAR, (1 << pin)); 304 else 305 GPIO_WRITE(sc, AR71XX_GPIO_SET, (1 << pin)); 306 GPIO_UNLOCK(sc); 307 308 return (0); 309} 310 311static int 312ar71xx_gpio_filter(void *arg) 313{ 314 315 /* TODO: something useful */ 316 return (FILTER_STRAY); 317} 318 319 320 321static void 322ar71xx_gpio_intr(void *arg) 323{ 324 struct ar71xx_gpio_softc *sc = arg; 325 GPIO_LOCK(sc); 326 /* TODO: something useful */ 327 GPIO_UNLOCK(sc); 328} 329 330static int 331ar71xx_gpio_probe(device_t dev) 332{ 333 334 device_set_desc(dev, "Atheros AR71XX GPIO driver"); 335 return (0); 336} 337 338static int 339ar71xx_gpio_attach(device_t dev) 340{ 341 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 342 int error = 0; 343 struct ar71xx_gpio_pin *pinp; 344 int i; 345 346 KASSERT((device_get_unit(dev) == 0), 347 ("ar71xx_gpio: Only one gpio module supported")); 348 349 mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 350 MTX_DEF); 351 352 /* Map control/status registers. */ 353 sc->gpio_mem_rid = 0; 354 sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 355 &sc->gpio_mem_rid, RF_ACTIVE); 356 357 if (sc->gpio_mem_res == NULL) { 358 device_printf(dev, "couldn't map memory\n"); 359 error = ENXIO; 360 ar71xx_gpio_detach(dev); 361 return(error); 362 } 363 364 if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 365 &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 366 device_printf(dev, "unable to allocate IRQ resource\n"); 367 return (ENXIO); 368 } 369 370 if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 371 ar71xx_gpio_filter, ar71xx_gpio_intr, sc, &sc->gpio_ih))) { 372 device_printf(dev, 373 "WARNING: unable to register interrupt handler\n"); 374 return (ENXIO); 375 } 376 377 sc->dev = dev; 378 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS1_EN); 379 ar71xx_gpio_function_enable(sc, GPIO_FUNC_SPI_CS2_EN); 380 /* Configure all pins as input */ 381 /* disable interrupts for all pins */ 382 GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0); 383 pinp = ar71xx_gpio_pins; 384 i = 0; 385 while (pinp->name) { 386 strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME); 387 sc->gpio_pins[i].gp_pin = pinp->pin; 388 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 389 sc->gpio_pins[i].gp_flags = 0; 390 ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags); 391 pinp++; 392 i++; 393 } 394 395 sc->gpio_npins = i; 396 397 device_add_child(dev, "gpioc", device_get_unit(dev)); 398 device_add_child(dev, "gpiobus", device_get_unit(dev)); 399 return (bus_generic_attach(dev)); 400} 401 402static int 403ar71xx_gpio_detach(device_t dev) 404{ 405 struct ar71xx_gpio_softc *sc = device_get_softc(dev); 406 407 KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 408 409 ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS1_EN); 410 ar71xx_gpio_function_disable(sc, GPIO_FUNC_SPI_CS2_EN); 411 bus_generic_detach(dev); 412 413 if (sc->gpio_mem_res) 414 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 415 sc->gpio_mem_res); 416 417 mtx_destroy(&sc->gpio_mtx); 418 419 return(0); 420} 421 422static device_method_t ar71xx_gpio_methods[] = { 423 DEVMETHOD(device_probe, ar71xx_gpio_probe), 424 DEVMETHOD(device_attach, ar71xx_gpio_attach), 425 DEVMETHOD(device_detach, ar71xx_gpio_detach), 426 427 /* GPIO protocol */ 428 DEVMETHOD(gpio_pin_max, ar71xx_gpio_pin_max), 429 DEVMETHOD(gpio_pin_getname, ar71xx_gpio_pin_getname), 430 DEVMETHOD(gpio_pin_getflags, ar71xx_gpio_pin_getflags), 431 DEVMETHOD(gpio_pin_getcaps, ar71xx_gpio_pin_getcaps), 432 DEVMETHOD(gpio_pin_setflags, ar71xx_gpio_pin_setflags), 433 DEVMETHOD(gpio_pin_get, ar71xx_gpio_pin_get), 434 DEVMETHOD(gpio_pin_set, ar71xx_gpio_pin_set), 435 DEVMETHOD(gpio_pin_toggle, ar71xx_gpio_pin_toggle), 436 {0, 0}, 437}; 438 439static driver_t ar71xx_gpio_driver = { 440 "gpio", 441 ar71xx_gpio_methods, 442 sizeof(struct ar71xx_gpio_softc), 443}; 444static devclass_t ar71xx_gpio_devclass; 445 446DRIVER_MODULE(ar71xx_gpio, apb, ar71xx_gpio_driver, ar71xx_gpio_devclass, 0, 0); 447