1/*- 2 * Copyright (c) 2010-2011, Aleksandr Rybalko <ray@ddteam.net> 3 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 4 * Copyright (c) 2009, Luiz Otavio O Souza. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30/* 31 * GPIO driver for RT305X SoC. 32 */ 33 34#include <sys/cdefs.h>
|
36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/bus.h> 40 41#include <sys/kernel.h> 42#include <sys/module.h> 43#include <sys/rman.h> 44#include <sys/lock.h> 45#include <sys/mutex.h> 46#include <sys/gpio.h> 47 48#include <machine/bus.h> 49#include <machine/resource.h> 50#include <mips/rt305x/rt305xreg.h> 51#include <mips/rt305x/rt305x_gpio.h> 52#include <mips/rt305x/rt305x_gpiovar.h> 53#include <mips/rt305x/rt305x_sysctlvar.h> 54 55#include "gpio_if.h" 56 57#ifdef notyet 58#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 59 GPIO_PIN_INVOUT | GPIO_PIN_REPORT ) 60#else 61#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_INVIN | \ 62 GPIO_PIN_INVOUT ) 63#endif 64 65/* 66 * Helpers 67 */ 68static void rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, 69 struct gpio_pin *pin, uint32_t flags); 70 71/* 72 * Driver stuff 73 */ 74static int rt305x_gpio_probe(device_t dev); 75static int rt305x_gpio_attach(device_t dev); 76static int rt305x_gpio_detach(device_t dev); 77static int rt305x_gpio_intr(void *arg); 78 79int rt305x_get_int_mask (device_t); 80void rt305x_set_int_mask (device_t, uint32_t); 81int rt305x_get_int_status(device_t); 82void rt305x_set_int_status(device_t, uint32_t); 83 84/* 85 * GPIO interface 86 */ 87static int rt305x_gpio_pin_max(device_t dev, int *maxpin); 88static int rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps); 89static int rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t 90 *flags); 91static int rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name); 92static int rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags); 93static int rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value); 94static int rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val); 95static int rt305x_gpio_pin_toggle(device_t dev, uint32_t pin); 96 97static void 98rt305x_gpio_pin_configure(struct rt305x_gpio_softc *sc, struct gpio_pin *pin, 99 unsigned int flags) 100{ 101 GPIO_LOCK(sc); 102 103 /* 104 * Manage input/output 105 */ 106 if (flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) { 107 pin->gp_flags &= ~(GPIO_PIN_INPUT|GPIO_PIN_OUTPUT); 108 if (flags & GPIO_PIN_OUTPUT) { 109 pin->gp_flags |= GPIO_PIN_OUTPUT; 110 GPIO_BIT_SET(sc, pin->gp_pin, DIR); 111 } 112 else { 113 pin->gp_flags |= GPIO_PIN_INPUT; 114 GPIO_BIT_CLR(sc, pin->gp_pin, DIR); 115 } 116 } 117 118 if (flags & GPIO_PIN_INVOUT) { 119 pin->gp_flags |= GPIO_PIN_INVOUT; 120 GPIO_BIT_SET(sc, pin->gp_pin, POL); 121 } 122 else { 123 pin->gp_flags &= ~GPIO_PIN_INVOUT; 124 GPIO_BIT_CLR(sc, pin->gp_pin, POL); 125 } 126 127 if (flags & GPIO_PIN_INVIN) { 128 pin->gp_flags |= GPIO_PIN_INVIN; 129 GPIO_BIT_SET(sc, pin->gp_pin, POL); 130 } 131 else { 132 pin->gp_flags &= ~GPIO_PIN_INVIN; 133 GPIO_BIT_CLR(sc, pin->gp_pin, POL); 134 } 135 136#ifdef notyet 137 /* Enable interrupt bits for rising/falling transitions */ 138 if (flags & GPIO_PIN_REPORT) { 139 pin->gp_flags |= GPIO_PIN_REPORT; 140 GPIO_BIT_SET(sc, pin->gp_pin, RENA); 141 GPIO_BIT_SET(sc, pin->gp_pin, FENA); 142 device_printf(sc->dev, "Will report interrupt on pin %d\n", 143 pin->gp_pin); 144 145 } 146 else { 147 pin->gp_flags &= ~GPIO_PIN_REPORT; 148 GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 149 GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 150 } 151#else 152 /* Disable generating interrupts for now */ 153 GPIO_BIT_CLR(sc, pin->gp_pin, RENA); 154 GPIO_BIT_CLR(sc, pin->gp_pin, FENA); 155#endif 156 157 GPIO_UNLOCK(sc); 158} 159 160static int 161rt305x_gpio_pin_max(device_t dev, int *maxpin) 162{ 163 164 *maxpin = NGPIO - 1; 165 return (0); 166} 167 168static int 169rt305x_gpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps) 170{ 171 struct rt305x_gpio_softc *sc = device_get_softc(dev); 172 int i; 173 174 for (i = 0; i < sc->gpio_npins; i++) { 175 if (sc->gpio_pins[i].gp_pin == pin) 176 break; 177 } 178 179 if (i >= sc->gpio_npins) 180 return (EINVAL); 181 182 GPIO_LOCK(sc); 183 *caps = sc->gpio_pins[i].gp_caps; 184 GPIO_UNLOCK(sc); 185 186 return (0); 187} 188 189static int 190rt305x_gpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) 191{ 192 struct rt305x_gpio_softc *sc = device_get_softc(dev); 193 int i; 194 195 for (i = 0; i < sc->gpio_npins; i++) { 196 if (sc->gpio_pins[i].gp_pin == pin) 197 break; 198 } 199 200 if (i >= sc->gpio_npins) 201 return (EINVAL); 202 203 GPIO_LOCK(sc); 204 *flags = sc->gpio_pins[i].gp_flags; 205 GPIO_UNLOCK(sc); 206 207 return (0); 208} 209 210static int 211rt305x_gpio_pin_getname(device_t dev, uint32_t pin, char *name) 212{ 213 struct rt305x_gpio_softc *sc = device_get_softc(dev); 214 int i; 215 216 for (i = 0; i < sc->gpio_npins; i++) { 217 if (sc->gpio_pins[i].gp_pin == pin) 218 break; 219 } 220 221 if (i >= sc->gpio_npins) 222 return (EINVAL); 223 224 GPIO_LOCK(sc); 225 memcpy(name, sc->gpio_pins[i].gp_name, GPIOMAXNAME); 226 GPIO_UNLOCK(sc); 227 228 return (0); 229} 230 231static int 232rt305x_gpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) 233{ 234 int i; 235 struct rt305x_gpio_softc *sc = device_get_softc(dev); 236 237 for (i = 0; i < sc->gpio_npins; i++) { 238 if (sc->gpio_pins[i].gp_pin == pin) 239 break; 240 } 241 242 if (i >= sc->gpio_npins) 243 return (EINVAL); 244 245 /* Check for unwanted flags. */ 246 if ((flags & sc->gpio_pins[i].gp_caps) != flags) 247 return (EINVAL); 248 249 /* Can't mix input/output together */ 250 if ((flags & (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) == 251 (GPIO_PIN_INPUT|GPIO_PIN_OUTPUT)) 252 return (EINVAL); 253 254 rt305x_gpio_pin_configure(sc, &sc->gpio_pins[i], flags); 255 256 257 return (0); 258} 259 260static int 261rt305x_gpio_pin_set(device_t dev, uint32_t pin, unsigned int value) 262{ 263 struct rt305x_gpio_softc *sc = device_get_softc(dev); 264 int i; 265 266 for (i = 0; i < sc->gpio_npins; i++) { 267 if (sc->gpio_pins[i].gp_pin == pin) 268 break; 269 } 270 271 if (i >= sc->gpio_npins) 272 return (EINVAL); 273 274 275 GPIO_LOCK(sc); 276 if (value) GPIO_BIT_SET(sc, i, DATA); 277 else GPIO_BIT_CLR(sc, i, DATA); 278 GPIO_UNLOCK(sc); 279 280 return (0); 281} 282 283static int 284rt305x_gpio_pin_get(device_t dev, uint32_t pin, unsigned int *val) 285{ 286 struct rt305x_gpio_softc *sc = device_get_softc(dev); 287 int i; 288 289 for (i = 0; i < sc->gpio_npins; i++) { 290 if (sc->gpio_pins[i].gp_pin == pin) 291 break; 292 } 293 294 if (i >= sc->gpio_npins) 295 return (EINVAL); 296 297 GPIO_LOCK(sc); 298 *val = GPIO_BIT_GET(sc, i, DATA); 299 GPIO_UNLOCK(sc); 300 301 return (0); 302} 303 304static int 305rt305x_gpio_pin_toggle(device_t dev, uint32_t pin) 306{ 307 int i; 308 struct rt305x_gpio_softc *sc = device_get_softc(dev); 309 310 for (i = 0; i < sc->gpio_npins; i++) { 311 if (sc->gpio_pins[i].gp_pin == pin) 312 break; 313 } 314 315 if (i >= sc->gpio_npins) 316 return (EINVAL); 317 318 GPIO_LOCK(sc); 319 GPIO_BIT_SET(sc, i, TOG); 320 GPIO_UNLOCK(sc); 321 322 return (0); 323} 324 325static int 326rt305x_gpio_intr(void *arg) 327{ 328 struct rt305x_gpio_softc *sc = arg; 329#ifdef notyet 330 uint32_t i; 331#endif 332 uint64_t input, value; 333#ifdef notyet 334 uint64_t reset_pin; 335 char notify[16]; 336 char pinname[6]; 337#endif 338 339 /* Read all reported pins */ 340 input = GPIO_READ_ALL(sc, INT); 341 /* Clear int status */ 342 GPIO_WRITE_ALL(sc, INT, input); 343 /* Clear report for OUTs */ 344 input &= ~GPIO_READ_ALL(sc, DIR); 345 value = input & GPIO_READ_ALL(sc, DATA); 346 347 if (!input) goto intr_done; 348 349#ifdef notyet 350 /* if reset_gpio and this pin is input */ 351 if (sc->reset_gpio >= 0 && (input & (1 << sc->reset_gpio))) { 352 /* get reset_gpio pin value */ 353 reset_pin = (value & (1 << sc->reset_gpio))?1:0; 354 if ( sc->reset_gpio_last != reset_pin ) { 355 /* 356 * if now reset is high, check how long 357 * and do reset if less than 2 seconds 358 */ 359 if ( reset_pin && 360 (time_uptime - sc->reset_gpio_ontime) < 2 ) 361 shutdown_nice(0); 362 363 sc->reset_gpio_last = reset_pin; 364 sc->reset_gpio_ontime = time_uptime; 365 } 366 } 367 368 for ( i = 0; i < NGPIO; i ++ ) 369 { 370 /* Next if output pin */ 371 if ( !(( input >> i) & 1) ) continue; 372 373 if ( (((value & input) >> i) & 1) != sc->gpio_pins[i].gp_last ) 374 { 375 /* !system=GPIO subsystem=pin7 type=PIN_HIGH period=3 */ 376 snprintf(notify , sizeof(notify ), "period=%d", 377 (uint32_t)time_uptime - sc->gpio_pins[i].gp_time); 378 snprintf(pinname, sizeof(pinname), "pin%02d", i); 379 devctl_notify("GPIO", pinname, 380 (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 381 notify); 382 printf("GPIO[%s] %s %s\n", pinname, 383 (((value & input) >> i) & 1)?"PIN_HIGH":"PIN_LOW", 384 notify); 385 sc->gpio_pins[i].gp_last = ((value & input) >> i) & 1; 386 sc->gpio_pins[i].gp_time = time_uptime; 387 } 388 389 } 390#endif 391 392intr_done: 393 return (FILTER_HANDLED); 394} 395 396static int 397rt305x_gpio_probe(device_t dev) 398{ 399 device_set_desc(dev, "RT305X GPIO driver"); 400 return (0); 401} 402 403static uint64_t 404rt305x_gpio_init(device_t dev) 405{ 406 uint64_t avl = ~0ULL; 407 uint32_t gmode = rt305x_sysctl_get(SYSCTL_GPIOMODE); 408 if (!(gmode & SYSCTL_GPIOMODE_RGMII_GPIO_MODE)) 409 avl &= ~RGMII_GPIO_MODE_MASK; 410 if (!(gmode & SYSCTL_GPIOMODE_SDRAM_GPIO_MODE)) 411 avl &= ~SDRAM_GPIO_MODE_MASK; 412 if (!(gmode & SYSCTL_GPIOMODE_MDIO_GPIO_MODE)) 413 avl &= ~MDIO_GPIO_MODE_MASK; 414 if (!(gmode & SYSCTL_GPIOMODE_JTAG_GPIO_MODE)) 415 avl &= ~JTAG_GPIO_MODE_MASK; 416 if (!(gmode & SYSCTL_GPIOMODE_UARTL_GPIO_MODE)) 417 avl &= ~UARTL_GPIO_MODE_MASK; 418 if (!(gmode & SYSCTL_GPIOMODE_SPI_GPIO_MODE)) 419 avl &= ~SPI_GPIO_MODE_MASK; 420 if (!(gmode & SYSCTL_GPIOMODE_I2C_GPIO_MODE)) 421 avl &= ~I2C_GPIO_MODE_MASK; 422 if ((gmode & SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) != 423 SYSCTL_GPIOMODE_UARTF_SHARE_MODE_GPIO) 424 avl &= ~I2C_GPIO_MODE_MASK; 425/* D-Link DAP-1350 Board have 426 * MDIO_GPIO_MODE 427 * UARTF_GPIO_MODE 428 * SPI_GPIO_MODE 429 * I2C_GPIO_MODE 430 * So we have 431 * 00000001 10000000 01111111 11111110 432*/ 433 return (avl); 434 435} 436 437#define DAP1350_RESET_GPIO 10 438 439static int 440rt305x_gpio_attach(device_t dev) 441{ 442 struct rt305x_gpio_softc *sc = device_get_softc(dev); 443 int error = 0, i; 444 uint64_t avlpins = 0; 445 sc->reset_gpio = DAP1350_RESET_GPIO; 446 447 KASSERT((device_get_unit(dev) == 0), 448 ("rt305x_gpio_gpio: Only one gpio module supported")); 449 450 mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 451 452 /* Map control/status registers. */ 453 sc->gpio_mem_rid = 0; 454 sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 455 &sc->gpio_mem_rid, RF_ACTIVE); 456 457 if (sc->gpio_mem_res == NULL) { 458 device_printf(dev, "couldn't map memory\n"); 459 error = ENXIO; 460 rt305x_gpio_detach(dev); 461 return(error); 462 } 463 464 if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 465 &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { 466 device_printf(dev, "unable to allocate IRQ resource\n"); 467 return (ENXIO); 468 } 469 470 if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, 471 /* rt305x_gpio_filter, */ 472 rt305x_gpio_intr, NULL, sc, &sc->gpio_ih))) { 473 device_printf(dev, 474 "WARNING: unable to register interrupt handler\n"); 475 return (ENXIO); 476 } 477 478 sc->dev = dev; 479 avlpins = rt305x_gpio_init(dev); 480 481 /* Configure all pins as input */ 482 /* disable interrupts for all pins */ 483 /* TODO */ 484 485 sc->gpio_npins = NGPIO; 486 resource_int_value(device_get_name(dev), device_get_unit(dev), 487 "pins", &sc->gpio_npins); 488 489 for (i = 0; i < sc->gpio_npins; i++) { 490 sc->gpio_pins[i].gp_pin = i; 491 sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; 492 sc->gpio_pins[i].gp_flags = 0; 493 } 494 495 /* Setup reset pin interrupt */ 496 if (TUNABLE_INT_FETCH("reset_gpio", &sc->reset_gpio)) { 497 device_printf(dev, "\tHinted reset_gpio %d\n", sc->reset_gpio); 498 } 499#ifdef notyet 500 if (sc->reset_gpio != -1) { 501 rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 502 GPIO_PIN_INPUT|GPIO_PIN_INVOUT| 503 GPIO_PIN_INVOUT|GPIO_PIN_REPORT); 504 device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 505 } 506#else 507 if (sc->reset_gpio != -1) { 508 rt305x_gpio_pin_setflags(dev, sc->reset_gpio, 509 GPIO_PIN_INPUT|GPIO_PIN_INVOUT); 510 device_printf(dev, "\tUse reset_gpio %d\n", sc->reset_gpio); 511 } 512#endif 513
|
517 return (bus_generic_attach(dev)); 518} 519 520static int 521rt305x_gpio_detach(device_t dev) 522{ 523 struct rt305x_gpio_softc *sc = device_get_softc(dev); 524 525 KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); 526 527 bus_generic_detach(dev); 528 529 if (sc->gpio_mem_res) 530 bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, 531 sc->gpio_mem_res); 532 533 mtx_destroy(&sc->gpio_mtx); 534 535 return(0); 536} 537 538#ifdef notyet 539static struct resource * 540rt305x_gpio_alloc_resource(device_t bus, device_t child, int type, int *rid, 541 u_long start, u_long end, u_long count, u_int flags) 542{ 543 struct obio_softc *sc = device_get_softc(bus); 544 struct resource *rv; 545 struct rman *rm; 546 547 switch (type) { 548 case SYS_RES_GPIO: 549 rm = &sc->gpio_rman; 550 break; 551 default: 552 printf("%s: unknown resource type %d\n", __func__, type); 553 return (0); 554 } 555 556 rv = rman_reserve_resource(rm, start, end, count, flags, child); 557 if (rv == 0) { 558 printf("%s: could not reserve resource\n", __func__); 559 return (0); 560 } 561 562 rman_set_rid(rv, *rid); 563 564 return (rv); 565} 566 567static int 568rt305x_gpio_activate_resource(device_t bus, device_t child, int type, int rid, 569 struct resource *r) 570{ 571 572 return (rman_activate_resource(r)); 573} 574 575static int 576rt305x_gpio_deactivate_resource(device_t bus, device_t child, int type, int rid, 577 struct resource *r) 578{ 579 580 return (rman_deactivate_resource(r)); 581} 582 583static int 584rt305x_gpio_release_resource(device_t dev, device_t child, int type, 585 int rid, struct resource *r) 586{ 587 rman_release_resource(r); 588 return (0); 589} 590#endif 591 592static device_method_t rt305x_gpio_methods[] = { 593 DEVMETHOD(device_probe, rt305x_gpio_probe), 594 DEVMETHOD(device_attach, rt305x_gpio_attach), 595 DEVMETHOD(device_detach, rt305x_gpio_detach), 596 597 /* GPIO protocol */ 598 DEVMETHOD(gpio_pin_max, rt305x_gpio_pin_max), 599 DEVMETHOD(gpio_pin_getname, rt305x_gpio_pin_getname), 600 DEVMETHOD(gpio_pin_getflags, rt305x_gpio_pin_getflags), 601 DEVMETHOD(gpio_pin_getcaps, rt305x_gpio_pin_getcaps), 602 DEVMETHOD(gpio_pin_setflags, rt305x_gpio_pin_setflags), 603 DEVMETHOD(gpio_pin_get, rt305x_gpio_pin_get), 604 DEVMETHOD(gpio_pin_set, rt305x_gpio_pin_set), 605 DEVMETHOD(gpio_pin_toggle, rt305x_gpio_pin_toggle), 606 {0, 0}, 607}; 608 609static driver_t rt305x_gpio_driver = { 610 "gpio", 611 rt305x_gpio_methods, 612 sizeof(struct rt305x_gpio_softc), 613}; 614static devclass_t rt305x_gpio_devclass; 615 616DRIVER_MODULE(rt305x_gpio, obio, rt305x_gpio_driver, 617 rt305x_gpio_devclass, 0, 0);
|