gpiobus.c revision 274638
1/*- 2 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: head/sys/dev/gpio/gpiobus.c 274638 2014-11-18 01:38:39Z loos $"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/bus.h> 33#include <sys/kernel.h> 34#include <sys/malloc.h> 35#include <sys/module.h> 36 37#include <dev/gpio/gpiobusvar.h> 38 39#include "gpiobus_if.h" 40 41#undef GPIOBUS_DEBUG 42#ifdef GPIOBUS_DEBUG 43#define dprintf printf 44#else 45#define dprintf(x, arg...) 46#endif 47 48static int gpiobus_parse_pins(struct gpiobus_softc *, device_t, int); 49static int gpiobus_probe(device_t); 50static int gpiobus_attach(device_t); 51static int gpiobus_detach(device_t); 52static int gpiobus_suspend(device_t); 53static int gpiobus_resume(device_t); 54static int gpiobus_print_child(device_t, device_t); 55static int gpiobus_child_location_str(device_t, device_t, char *, size_t); 56static int gpiobus_child_pnpinfo_str(device_t, device_t, char *, size_t); 57static device_t gpiobus_add_child(device_t, u_int, const char *, int); 58static void gpiobus_hinted_child(device_t, const char *, int); 59 60/* 61 * GPIOBUS interface 62 */ 63static int gpiobus_acquire_bus(device_t, device_t, int); 64static void gpiobus_release_bus(device_t, device_t); 65static int gpiobus_pin_setflags(device_t, device_t, uint32_t, uint32_t); 66static int gpiobus_pin_getflags(device_t, device_t, uint32_t, uint32_t*); 67static int gpiobus_pin_getcaps(device_t, device_t, uint32_t, uint32_t*); 68static int gpiobus_pin_set(device_t, device_t, uint32_t, unsigned int); 69static int gpiobus_pin_get(device_t, device_t, uint32_t, unsigned int*); 70static int gpiobus_pin_toggle(device_t, device_t, uint32_t); 71 72void 73gpiobus_print_pins(struct gpiobus_ivar *devi) 74{ 75 int range_start, range_stop, need_coma; 76 int i; 77 78 if (devi->npins == 0) 79 return; 80 81 need_coma = 0; 82 range_start = range_stop = devi->pins[0]; 83 for (i = 1; i < devi->npins; i++) { 84 if (devi->pins[i] != (range_stop + 1)) { 85 if (need_coma) 86 printf(","); 87 if (range_start != range_stop) 88 printf("%d-%d", range_start, range_stop); 89 else 90 printf("%d", range_start); 91 92 range_start = range_stop = devi->pins[i]; 93 need_coma = 1; 94 } 95 else 96 range_stop++; 97 } 98 99 if (need_coma) 100 printf(","); 101 if (range_start != range_stop) 102 printf("%d-%d", range_start, range_stop); 103 else 104 printf("%d", range_start); 105} 106 107int 108gpiobus_init_softc(device_t dev) 109{ 110 struct gpiobus_softc *sc; 111 112 sc = GPIOBUS_SOFTC(dev); 113 sc->sc_busdev = dev; 114 sc->sc_dev = device_get_parent(dev); 115 sc->sc_intr_rman.rm_type = RMAN_ARRAY; 116 sc->sc_intr_rman.rm_descr = "GPIO Interrupts"; 117 if (rman_init(&sc->sc_intr_rman) != 0 || 118 rman_manage_region(&sc->sc_intr_rman, 0, ~0) != 0) 119 panic("%s: failed to set up rman.", __func__); 120 121 if (GPIO_PIN_MAX(sc->sc_dev, &sc->sc_npins) != 0) 122 return (ENXIO); 123 124 KASSERT(sc->sc_npins != 0, ("GPIO device with no pins")); 125 126 /* Pins = GPIO_PIN_MAX() + 1 */ 127 sc->sc_npins++; 128 129 sc->sc_pins_mapped = malloc(sizeof(int) * sc->sc_npins, M_DEVBUF, 130 M_NOWAIT | M_ZERO); 131 if (sc->sc_pins_mapped == NULL) 132 return (ENOMEM); 133 134 /* Initialize the bus lock. */ 135 GPIOBUS_LOCK_INIT(sc); 136 137 return (0); 138} 139 140static int 141gpiobus_parse_pins(struct gpiobus_softc *sc, device_t child, int mask) 142{ 143 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 144 int i, npins; 145 146 npins = 0; 147 for (i = 0; i < 32; i++) { 148 if (mask & (1 << i)) 149 npins++; 150 } 151 152 if (npins == 0) { 153 device_printf(child, "empty pin mask\n"); 154 return (EINVAL); 155 } 156 157 devi->npins = npins; 158 devi->pins = malloc(sizeof(uint32_t) * devi->npins, M_DEVBUF, 159 M_NOWAIT | M_ZERO); 160 161 if (!devi->pins) 162 return (ENOMEM); 163 164 npins = 0; 165 for (i = 0; i < 32; i++) { 166 167 if ((mask & (1 << i)) == 0) 168 continue; 169 170 if (i >= sc->sc_npins) { 171 device_printf(child, 172 "invalid pin %d, max: %d\n", i, sc->sc_npins - 1); 173 free(devi->pins, M_DEVBUF); 174 return (EINVAL); 175 } 176 177 devi->pins[npins++] = i; 178 /* 179 * Mark pin as mapped and give warning if it's already mapped 180 */ 181 if (sc->sc_pins_mapped[i]) { 182 device_printf(child, 183 "warning: pin %d is already mapped\n", i); 184 free(devi->pins, M_DEVBUF); 185 return (EINVAL); 186 } 187 sc->sc_pins_mapped[i] = 1; 188 } 189 190 return (0); 191} 192 193static int 194gpiobus_probe(device_t dev) 195{ 196 device_set_desc(dev, "GPIO bus"); 197 198 return (BUS_PROBE_GENERIC); 199} 200 201static int 202gpiobus_attach(device_t dev) 203{ 204 int err; 205 206 err = gpiobus_init_softc(dev); 207 if (err != 0) 208 return (err); 209 210 /* 211 * Get parent's pins and mark them as unmapped 212 */ 213 bus_generic_probe(dev); 214 bus_enumerate_hinted_children(dev); 215 216 return (bus_generic_attach(dev)); 217} 218 219/* 220 * Since this is not a self-enumerating bus, and since we always add 221 * children in attach, we have to always delete children here. 222 */ 223static int 224gpiobus_detach(device_t dev) 225{ 226 struct gpiobus_softc *sc; 227 struct gpiobus_ivar *devi; 228 device_t *devlist; 229 int i, err, ndevs; 230 231 sc = GPIOBUS_SOFTC(dev); 232 KASSERT(mtx_initialized(&sc->sc_mtx), 233 ("gpiobus mutex not initialized")); 234 GPIOBUS_LOCK_DESTROY(sc); 235 236 if ((err = bus_generic_detach(dev)) != 0) 237 return (err); 238 239 if ((err = device_get_children(dev, &devlist, &ndevs)) != 0) 240 return (err); 241 for (i = 0; i < ndevs; i++) { 242 device_delete_child(dev, devlist[i]); 243 devi = GPIOBUS_IVAR(devlist[i]); 244 if (devi->pins) { 245 free(devi->pins, M_DEVBUF); 246 devi->pins = NULL; 247 } 248 } 249 free(devlist, M_TEMP); 250 251 if (sc->sc_pins_mapped) { 252 free(sc->sc_pins_mapped, M_DEVBUF); 253 sc->sc_pins_mapped = NULL; 254 } 255 256 return (0); 257} 258 259static int 260gpiobus_suspend(device_t dev) 261{ 262 263 return (bus_generic_suspend(dev)); 264} 265 266static int 267gpiobus_resume(device_t dev) 268{ 269 270 return (bus_generic_resume(dev)); 271} 272 273static int 274gpiobus_print_child(device_t dev, device_t child) 275{ 276 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 277 int retval = 0; 278 279 retval += bus_print_child_header(dev, child); 280 retval += printf(" at pin(s) "); 281 gpiobus_print_pins(devi); 282 resource_list_print_type(&devi->rl, "irq", SYS_RES_IRQ, "%ld"); 283 retval += bus_print_child_footer(dev, child); 284 285 return (retval); 286} 287 288static int 289gpiobus_child_location_str(device_t bus, device_t child, char *buf, 290 size_t buflen) 291{ 292 293 snprintf(buf, buflen, "pins=?"); 294 return (0); 295} 296 297static int 298gpiobus_child_pnpinfo_str(device_t bus, device_t child, char *buf, 299 size_t buflen) 300{ 301 302 *buf = '\0'; 303 return (0); 304} 305 306static device_t 307gpiobus_add_child(device_t dev, u_int order, const char *name, int unit) 308{ 309 device_t child; 310 struct gpiobus_ivar *devi; 311 312 child = device_add_child_ordered(dev, order, name, unit); 313 if (child == NULL) 314 return (child); 315 devi = malloc(sizeof(struct gpiobus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO); 316 if (devi == NULL) { 317 device_delete_child(dev, child); 318 return (0); 319 } 320 resource_list_init(&devi->rl); 321 device_set_ivars(child, devi); 322 323 return (child); 324} 325 326static void 327gpiobus_hinted_child(device_t bus, const char *dname, int dunit) 328{ 329 struct gpiobus_softc *sc = GPIOBUS_SOFTC(bus); 330 struct gpiobus_ivar *devi; 331 device_t child; 332 int irq, pins; 333 334 child = BUS_ADD_CHILD(bus, 0, dname, dunit); 335 devi = GPIOBUS_IVAR(child); 336 resource_int_value(dname, dunit, "pins", &pins); 337 if (gpiobus_parse_pins(sc, child, pins)) 338 device_delete_child(bus, child); 339 if (resource_int_value(dname, dunit, "irq", &irq) == 0) { 340 if (bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1) != 0) 341 device_printf(bus, 342 "warning: bus_set_resource() failed\n"); 343 } 344} 345 346static int 347gpiobus_set_resource(device_t dev, device_t child, int type, int rid, 348 u_long start, u_long count) 349{ 350 struct gpiobus_ivar *devi; 351 struct resource_list_entry *rle; 352 353 dprintf("%s: entry (%p, %p, %d, %d, %p, %ld)\n", 354 __func__, dev, child, type, rid, (void *)(intptr_t)start, count); 355 devi = GPIOBUS_IVAR(child); 356 rle = resource_list_add(&devi->rl, type, rid, start, 357 start + count - 1, count); 358 if (rle == NULL) 359 return (ENXIO); 360 361 return (0); 362} 363 364static struct resource * 365gpiobus_alloc_resource(device_t bus, device_t child, int type, int *rid, 366 u_long start, u_long end, u_long count, u_int flags) 367{ 368 struct gpiobus_softc *sc; 369 struct resource *rv; 370 struct resource_list *rl; 371 struct resource_list_entry *rle; 372 int isdefault; 373 374 if (type != SYS_RES_IRQ) 375 return (NULL); 376 isdefault = (start == 0UL && end == ~0UL && count == 1); 377 rle = NULL; 378 if (isdefault) { 379 rl = BUS_GET_RESOURCE_LIST(bus, child); 380 if (rl == NULL) 381 return (NULL); 382 rle = resource_list_find(rl, type, *rid); 383 if (rle == NULL) 384 return (NULL); 385 if (rle->res != NULL) 386 panic("%s: resource entry is busy", __func__); 387 start = rle->start; 388 count = rle->count; 389 end = rle->end; 390 } 391 sc = device_get_softc(bus); 392 rv = rman_reserve_resource(&sc->sc_intr_rman, start, end, count, flags, 393 child); 394 if (rv == NULL) 395 return (NULL); 396 rman_set_rid(rv, *rid); 397 if ((flags & RF_ACTIVE) != 0 && 398 bus_activate_resource(child, type, *rid, rv) != 0) { 399 rman_release_resource(rv); 400 return (NULL); 401 } 402 403 return (rv); 404} 405 406static int 407gpiobus_release_resource(device_t bus __unused, device_t child, int type, 408 int rid, struct resource *r) 409{ 410 int error; 411 412 if (rman_get_flags(r) & RF_ACTIVE) { 413 error = bus_deactivate_resource(child, type, rid, r); 414 if (error) 415 return (error); 416 } 417 418 return (rman_release_resource(r)); 419} 420 421static struct resource_list * 422gpiobus_get_resource_list(device_t bus __unused, device_t child) 423{ 424 struct gpiobus_ivar *ivar; 425 426 ivar = GPIOBUS_IVAR(child); 427 428 return (&ivar->rl); 429} 430 431static int 432gpiobus_acquire_bus(device_t busdev, device_t child, int how) 433{ 434 struct gpiobus_softc *sc; 435 436 sc = device_get_softc(busdev); 437 GPIOBUS_ASSERT_UNLOCKED(sc); 438 GPIOBUS_LOCK(sc); 439 if (sc->sc_owner != NULL) { 440 if (how == GPIOBUS_DONTWAIT) { 441 GPIOBUS_UNLOCK(sc); 442 return (EWOULDBLOCK); 443 } 444 while (sc->sc_owner != NULL) 445 mtx_sleep(sc, &sc->sc_mtx, 0, "gpiobuswait", 0); 446 } 447 sc->sc_owner = child; 448 GPIOBUS_UNLOCK(sc); 449 450 return (0); 451} 452 453static void 454gpiobus_release_bus(device_t busdev, device_t child) 455{ 456 struct gpiobus_softc *sc; 457 458 sc = device_get_softc(busdev); 459 GPIOBUS_ASSERT_UNLOCKED(sc); 460 GPIOBUS_LOCK(sc); 461 if (sc->sc_owner == NULL) 462 panic("gpiobus: releasing unowned bus."); 463 if (sc->sc_owner != child) 464 panic("gpiobus: you don't own the bus. game over."); 465 sc->sc_owner = NULL; 466 wakeup(sc); 467 GPIOBUS_UNLOCK(sc); 468} 469 470static int 471gpiobus_pin_setflags(device_t dev, device_t child, uint32_t pin, 472 uint32_t flags) 473{ 474 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 475 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 476 477 if (pin >= devi->npins) 478 return (EINVAL); 479 480 return GPIO_PIN_SETFLAGS(sc->sc_dev, devi->pins[pin], flags); 481} 482 483static int 484gpiobus_pin_getflags(device_t dev, device_t child, uint32_t pin, 485 uint32_t *flags) 486{ 487 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 488 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 489 490 if (pin >= devi->npins) 491 return (EINVAL); 492 493 return GPIO_PIN_GETFLAGS(sc->sc_dev, devi->pins[pin], flags); 494} 495 496static int 497gpiobus_pin_getcaps(device_t dev, device_t child, uint32_t pin, 498 uint32_t *caps) 499{ 500 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 501 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 502 503 if (pin >= devi->npins) 504 return (EINVAL); 505 506 return GPIO_PIN_GETCAPS(sc->sc_dev, devi->pins[pin], caps); 507} 508 509static int 510gpiobus_pin_set(device_t dev, device_t child, uint32_t pin, 511 unsigned int value) 512{ 513 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 514 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 515 516 if (pin >= devi->npins) 517 return (EINVAL); 518 519 return GPIO_PIN_SET(sc->sc_dev, devi->pins[pin], value); 520} 521 522static int 523gpiobus_pin_get(device_t dev, device_t child, uint32_t pin, 524 unsigned int *value) 525{ 526 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 527 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 528 529 if (pin >= devi->npins) 530 return (EINVAL); 531 532 return GPIO_PIN_GET(sc->sc_dev, devi->pins[pin], value); 533} 534 535static int 536gpiobus_pin_toggle(device_t dev, device_t child, uint32_t pin) 537{ 538 struct gpiobus_softc *sc = GPIOBUS_SOFTC(dev); 539 struct gpiobus_ivar *devi = GPIOBUS_IVAR(child); 540 541 if (pin >= devi->npins) 542 return (EINVAL); 543 544 return GPIO_PIN_TOGGLE(sc->sc_dev, devi->pins[pin]); 545} 546 547static device_method_t gpiobus_methods[] = { 548 /* Device interface */ 549 DEVMETHOD(device_probe, gpiobus_probe), 550 DEVMETHOD(device_attach, gpiobus_attach), 551 DEVMETHOD(device_detach, gpiobus_detach), 552 DEVMETHOD(device_shutdown, bus_generic_shutdown), 553 DEVMETHOD(device_suspend, gpiobus_suspend), 554 DEVMETHOD(device_resume, gpiobus_resume), 555 556 /* Bus interface */ 557 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 558 DEVMETHOD(bus_config_intr, bus_generic_config_intr), 559 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 560 DEVMETHOD(bus_set_resource, gpiobus_set_resource), 561 DEVMETHOD(bus_alloc_resource, gpiobus_alloc_resource), 562 DEVMETHOD(bus_release_resource, gpiobus_release_resource), 563 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 564 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 565 DEVMETHOD(bus_get_resource_list, gpiobus_get_resource_list), 566 DEVMETHOD(bus_add_child, gpiobus_add_child), 567 DEVMETHOD(bus_print_child, gpiobus_print_child), 568 DEVMETHOD(bus_child_pnpinfo_str, gpiobus_child_pnpinfo_str), 569 DEVMETHOD(bus_child_location_str, gpiobus_child_location_str), 570 DEVMETHOD(bus_hinted_child, gpiobus_hinted_child), 571 572 /* GPIO protocol */ 573 DEVMETHOD(gpiobus_acquire_bus, gpiobus_acquire_bus), 574 DEVMETHOD(gpiobus_release_bus, gpiobus_release_bus), 575 DEVMETHOD(gpiobus_pin_getflags, gpiobus_pin_getflags), 576 DEVMETHOD(gpiobus_pin_getcaps, gpiobus_pin_getcaps), 577 DEVMETHOD(gpiobus_pin_setflags, gpiobus_pin_setflags), 578 DEVMETHOD(gpiobus_pin_get, gpiobus_pin_get), 579 DEVMETHOD(gpiobus_pin_set, gpiobus_pin_set), 580 DEVMETHOD(gpiobus_pin_toggle, gpiobus_pin_toggle), 581 582 DEVMETHOD_END 583}; 584 585driver_t gpiobus_driver = { 586 "gpiobus", 587 gpiobus_methods, 588 sizeof(struct gpiobus_softc) 589}; 590 591devclass_t gpiobus_devclass; 592 593DRIVER_MODULE(gpiobus, gpio, gpiobus_driver, gpiobus_devclass, 0, 0); 594MODULE_VERSION(gpiobus, 1); 595