ar71xx_gpio.c revision 213286
1178828Sdfr/*- 2178828Sdfr * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3178828Sdfr * Copyright (c) 2009, Luiz Otavio O Souza. 4178828Sdfr * All rights reserved. 5178828Sdfr * 6178828Sdfr * Redistribution and use in source and binary forms, with or without 7178828Sdfr * modification, are permitted provided that the following conditions 8178828Sdfr * are met: 9178828Sdfr * 1. Redistributions of source code must retain the above copyright 10178828Sdfr * notice unmodified, this list of conditions, and the following 11178828Sdfr * disclaimer. 12178828Sdfr * 2. Redistributions in binary form must reproduce the above copyright 13178828Sdfr * notice, this list of conditions and the following disclaimer in the 14178828Sdfr * documentation and/or other materials provided with the distribution. 15178828Sdfr * 16178828Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17178828Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18178828Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19178828Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20178828Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21178828Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22178828Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23178828Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24178828Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25178828Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26178828Sdfr * SUCH DAMAGE. 27178828Sdfr */ 28178828Sdfr 29178828Sdfr/* 30178828Sdfr * GPIO driver for AR71xx 31178828Sdfr */ 32178828Sdfr 33178828Sdfr#include <sys/cdefs.h> 34178828Sdfr__FBSDID("$FreeBSD: head/sys/mips/atheros/ar71xx_gpio.c 213286 2010-09-29 23:06:41Z gonzo $"); 35178828Sdfr 36178828Sdfr#include <sys/param.h> 37178828Sdfr#include <sys/systm.h> 38178828Sdfr#include <sys/bus.h> 39178828Sdfr 40178828Sdfr#include <sys/kernel.h> 41178828Sdfr#include <sys/module.h> 42178828Sdfr#include <sys/rman.h> 43178828Sdfr#include <sys/lock.h> 44178828Sdfr#include <sys/mutex.h> 45178828Sdfr#include <sys/gpio.h> 46178828Sdfr 47178828Sdfr#include <machine/bus.h> 48178828Sdfr#include <machine/resource.h> 49178828Sdfr#include <mips/atheros/ar71xxreg.h> 50178828Sdfr#include <mips/atheros/ar71xx_gpiovar.h> 51178828Sdfr 52178828Sdfr#include "gpio_if.h" 53178828Sdfr 54178828Sdfr#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT) 55178828Sdfr 56178828Sdfrstruct ar71xx_gpio_pin { 57178828Sdfr const char *name; 58178828Sdfr int pin; 59178828Sdfr int flags; 60178828Sdfr}; 61178828Sdfr 62178828Sdfrstatic struct ar71xx_gpio_pin ar71xx_gpio_pins[] = { 63178828Sdfr { "RFled", 2, GPIO_PIN_OUTPUT}, 64178828Sdfr { "SW4", 8, GPIO_PIN_INPUT}, 65178828Sdfr { NULL, 0, 0}, 66178828Sdfr}; 67178828Sdfr 68178828Sdfr/* 69178828Sdfr * Helpers 70178828Sdfr */ 71178828Sdfrstatic void ar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, 72178828Sdfr uint32_t mask); 73178828Sdfrstatic void ar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, 74178828Sdfr uint32_t mask); 75178828Sdfrstatic void ar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, 76178828Sdfr struct gpio_pin *pin, uint32_t flags); 77178828Sdfr 78178828Sdfr/* 79178828Sdfr * Driver stuff 80178828Sdfr */ 81178828Sdfrstatic int ar71xx_gpio_probe(device_t dev); 82178828Sdfrstatic int ar71xx_gpio_attach(device_t dev); 83178828Sdfrstatic int ar71xx_gpio_detach(device_t dev); 84178828Sdfrstatic int ar71xx_gpio_filter(void *arg); 85178828Sdfrstatic void ar71xx_gpio_intr(void *arg); 86178828Sdfr 87178828Sdfr/* 88178828Sdfr * GPIO interface 89178828Sdfr */ 90178828Sdfrstatic int ar71xx_gpio_pin_max(device_t dev, int *maxpin); 91178828Sdfrstatic int ar71xx_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 92178828Sdfrstatic int ar71xx_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 93178828Sdfr *flags); 94178828Sdfrstatic int ar71xx_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 95178828Sdfrstatic int ar71xx_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 96178828Sdfrstatic int ar71xx_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 97178828Sdfrstatic int ar71xx_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 98178828Sdfrstatic int ar71xx_gpio_pin_toggle(device_t dev, uint32_t pin); 99178828Sdfr 100178828Sdfrstatic void 101178828Sdfrar71xx_gpio_function_enable(struct ar71xx_gpio_softc *sc, uint32_t mask) 102178828Sdfr{ 103178828Sdfr GPIO_LOCK(sc); 104178828Sdfr GPIO_SET_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 105178828Sdfr GPIO_UNLOCK(sc); 106178828Sdfr} 107178828Sdfr 108178828Sdfrstatic void 109178828Sdfrar71xx_gpio_function_disable(struct ar71xx_gpio_softc *sc, uint32_t mask) 110178828Sdfr{ 111178828Sdfr GPIO_LOCK(sc); 112178828Sdfr GPIO_CLEAR_BITS(sc, AR71XX_GPIO_FUNCTION, mask); 113178828Sdfr GPIO_UNLOCK(sc); 114178828Sdfr} 115178828Sdfr 116178828Sdfrstatic void 117178828Sdfrar71xx_gpio_pin_configure(struct ar71xx_gpio_softc *sc, struct gpio_pin *pin, 118178828Sdfr unsigned int flags) 119178828Sdfr{ 120178828Sdfr uint32_t mask; 121178828Sdfr 122178828Sdfr mask = 1 << pin->gp_pin; 123178828Sdfr GPIO_LOCK(sc); 124178828Sdfr 125178828Sdfr /* 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