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