gpioc.c (7648bc9fee8dec6cb3c4941e0165a930fbe8dcb0) | gpioc.c (ff3468ac94597efdcbc56f372528dfc98b114dac) |
---|---|
1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org> 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 --- 21 unchanged lines hidden (view full) --- 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/conf.h> 36#include <sys/gpio.h> 37#include <sys/ioccom.h> | 1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2009 Oleksandr Tymoshenko <gonzo@freebsd.org> 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 --- 21 unchanged lines hidden (view full) --- 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/bus.h> 35#include <sys/conf.h> 36#include <sys/gpio.h> 37#include <sys/ioccom.h> |
38#include <sys/filio.h> 39#include <sys/fcntl.h> 40#include <sys/sigio.h> 41#include <sys/signalvar.h> |
|
38#include <sys/kernel.h> 39#include <sys/malloc.h> | 42#include <sys/kernel.h> 43#include <sys/malloc.h> |
44#include <sys/uio.h> 45#include <sys/poll.h> 46#include <sys/selinfo.h> |
|
40#include <sys/module.h> 41 42#include <dev/gpio/gpiobusvar.h> 43 44#include "gpio_if.h" 45#include "gpiobus_if.h" 46 47#undef GPIOC_DEBUG 48#ifdef GPIOC_DEBUG 49#define dprintf printf | 47#include <sys/module.h> 48 49#include <dev/gpio/gpiobusvar.h> 50 51#include "gpio_if.h" 52#include "gpiobus_if.h" 53 54#undef GPIOC_DEBUG 55#ifdef GPIOC_DEBUG 56#define dprintf printf |
57#define ddevice_printf device_printf |
|
50#else 51#define dprintf(x, arg...) | 58#else 59#define dprintf(x, arg...) |
60#define ddevice_printf(dev, x, arg...) |
|
52#endif 53 | 61#endif 62 |
54static int gpioc_probe(device_t dev); 55static int gpioc_attach(device_t dev); 56static int gpioc_detach(device_t dev); | 63struct gpioc_softc { 64 device_t sc_dev; /* gpiocX dev */ 65 device_t sc_pdev; /* gpioX dev */ 66 struct cdev *sc_ctl_dev; /* controller device */ 67 int sc_unit; 68 int sc_npins; 69 struct gpioc_pin_intr *sc_pin_intr; 70}; |
57 | 71 |
72struct gpioc_pin_intr { 73 struct gpioc_softc *sc; 74 gpio_pin_t pin; 75 bool config_locked; 76 int intr_rid; 77 struct resource *intr_res; 78 void *intr_cookie; 79 struct mtx mtx; 80 SLIST_HEAD(gpioc_privs_list, gpioc_privs) privs; 81}; 82 83 84struct gpioc_cdevpriv { 85 struct gpioc_softc *sc; 86 struct selinfo selinfo; 87 bool async; 88 uint8_t report_option; 89 struct sigio *sigio; 90 struct mtx mtx; 91 struct gpioc_pin_event *events; 92 int numevents; 93 int evidx_head; 94 int evidx_tail; 95 SLIST_HEAD(gpioc_pins_list, gpioc_pins) pins; 96}; 97 98struct gpioc_privs { 99 struct gpioc_cdevpriv *priv; 100 SLIST_ENTRY(gpioc_privs) next; 101}; 102 103struct gpioc_pins { 104 struct gpioc_pin_intr *pin; 105 int eventcount; 106 int firstevent; 107 SLIST_ENTRY(gpioc_pins) next; 108}; 109 110struct gpioc_pin_event { 111 struct gpioc_pins *privpin; 112 sbintime_t event_time; 113 bool event_pin_state; 114}; 115 116static MALLOC_DEFINE(M_GPIOC, "gpioc", "gpioc device data"); 117 118static int gpioc_allocate_pin_intr(struct gpioc_pin_intr*, uint32_t); 119static int gpioc_release_pin_intr(struct gpioc_pin_intr*); 120static int gpioc_attach_priv_pin(struct gpioc_cdevpriv*, 121 struct gpioc_pin_intr*); 122static int gpioc_detach_priv_pin(struct gpioc_cdevpriv*, 123 struct gpioc_pin_intr*); 124static bool gpioc_intr_reconfig_allowed(struct gpioc_cdevpriv*, 125 struct gpioc_pin_intr *intr_conf); 126static uint32_t gpioc_get_intr_config(struct gpioc_softc*, 127 struct gpioc_cdevpriv*, uint32_t pin); 128static int gpioc_set_intr_config(struct gpioc_softc*, 129 struct gpioc_cdevpriv*, uint32_t, uint32_t); 130static void gpioc_interrupt_handler(void*); 131 132static int gpioc_kqread(struct knote*, long); 133static void gpioc_kqdetach(struct knote*); 134 135static int gpioc_probe(device_t dev); 136static int gpioc_attach(device_t dev); 137static int gpioc_detach(device_t dev); 138 139static void gpioc_cdevpriv_dtor(void*); 140 141static d_open_t gpioc_open; 142static d_read_t gpioc_read; |
|
58static d_ioctl_t gpioc_ioctl; | 143static d_ioctl_t gpioc_ioctl; |
144static d_poll_t gpioc_poll; 145static d_kqfilter_t gpioc_kqfilter; |
|
59 60static struct cdevsw gpioc_cdevsw = { 61 .d_version = D_VERSION, | 146 147static struct cdevsw gpioc_cdevsw = { 148 .d_version = D_VERSION, |
149 .d_open = gpioc_open, 150 .d_read = gpioc_read, |
|
62 .d_ioctl = gpioc_ioctl, | 151 .d_ioctl = gpioc_ioctl, |
152 .d_poll = gpioc_poll, 153 .d_kqfilter = gpioc_kqfilter, |
|
63 .d_name = "gpioc", 64}; 65 | 154 .d_name = "gpioc", 155}; 156 |
66struct gpioc_softc { 67 device_t sc_dev; /* gpiocX dev */ 68 device_t sc_pdev; /* gpioX dev */ 69 struct cdev *sc_ctl_dev; /* controller device */ 70 int sc_unit; | 157static struct filterops gpioc_read_filterops = { 158 .f_isfd = true, 159 .f_attach = NULL, 160 .f_detach = gpioc_kqdetach, 161 .f_event = gpioc_kqread, 162 .f_touch = NULL |
71}; 72 | 163}; 164 |
165static struct gpioc_pin_event * 166next_head_event(struct gpioc_cdevpriv *priv) 167{ 168 struct gpioc_pin_event *rv; 169 170 rv = &priv->events[priv->evidx_head++]; 171 if (priv->evidx_head == priv->numevents) 172 priv->evidx_head = 0; 173 return (rv); 174} 175 176static struct gpioc_pin_event * 177next_tail_event(struct gpioc_cdevpriv *priv) 178{ 179 struct gpioc_pin_event *rv; 180 181 rv = &priv->events[priv->evidx_tail++]; 182 if (priv->evidx_tail == priv->numevents) 183 priv->evidx_tail = 0; 184 return (rv); 185} 186 187static size_t 188number_of_events(struct gpioc_cdevpriv *priv) 189{ 190 if (priv->evidx_head >= priv->evidx_tail) 191 return (priv->evidx_head - priv->evidx_tail); 192 else 193 return (priv->numevents + priv->evidx_head - priv->evidx_tail); 194} 195 |
|
73static int | 196static int |
197gpioc_allocate_pin_intr(struct gpioc_pin_intr *intr_conf, uint32_t flags) 198{ 199 int err; 200 201 intr_conf->config_locked = true; 202 mtx_unlock(&intr_conf->mtx); 203 204 intr_conf->intr_res = gpio_alloc_intr_resource(intr_conf->pin->dev, 205 &intr_conf->intr_rid, RF_ACTIVE, intr_conf->pin, flags); 206 if (intr_conf->intr_res == NULL) { 207 err = ENXIO; 208 goto error_exit; 209 } 210 211 err = bus_setup_intr(intr_conf->pin->dev, intr_conf->intr_res, 212 INTR_TYPE_MISC | INTR_MPSAFE, NULL, gpioc_interrupt_handler, 213 intr_conf, &intr_conf->intr_cookie); 214 if (err != 0) 215 goto error_exit; 216 217 intr_conf->pin->flags = flags; 218 219error_exit: 220 mtx_lock(&intr_conf->mtx); 221 intr_conf->config_locked = false; 222 wakeup(&intr_conf->config_locked); 223 224 return (err); 225} 226 227static int 228gpioc_release_pin_intr(struct gpioc_pin_intr *intr_conf) 229{ 230 int err; 231 232 intr_conf->config_locked = true; 233 mtx_unlock(&intr_conf->mtx); 234 235 if (intr_conf->intr_cookie != NULL) { 236 err = bus_teardown_intr(intr_conf->pin->dev, 237 intr_conf->intr_res, intr_conf->intr_cookie); 238 if (err != 0) 239 goto error_exit; 240 else 241 intr_conf->intr_cookie = NULL; 242 } 243 244 if (intr_conf->intr_res != NULL) { 245 err = bus_release_resource(intr_conf->pin->dev, SYS_RES_IRQ, 246 intr_conf->intr_rid, intr_conf->intr_res); 247 if (err != 0) 248 goto error_exit; 249 else { 250 intr_conf->intr_rid = 0; 251 intr_conf->intr_res = NULL; 252 } 253 } 254 255 intr_conf->pin->flags = 0; 256 err = 0; 257 258error_exit: 259 mtx_lock(&intr_conf->mtx); 260 intr_conf->config_locked = false; 261 wakeup(&intr_conf->config_locked); 262 263 return (err); 264} 265 266static int 267gpioc_attach_priv_pin(struct gpioc_cdevpriv *priv, 268 struct gpioc_pin_intr *intr_conf) 269{ 270 struct gpioc_privs *priv_link; 271 struct gpioc_pins *pin_link; 272 unsigned int consistency_a, consistency_b; 273 274 consistency_a = 0; 275 consistency_b = 0; 276 mtx_assert(&intr_conf->mtx, MA_OWNED); 277 mtx_lock(&priv->mtx); 278 SLIST_FOREACH(priv_link, &intr_conf->privs, next) { 279 if (priv_link->priv == priv) 280 consistency_a++; 281 } 282 KASSERT(consistency_a <= 1, 283 ("inconsistent links between pin config and cdevpriv")); 284 SLIST_FOREACH(pin_link, &priv->pins, next) { 285 if (pin_link->pin == intr_conf) 286 consistency_b++; 287 } 288 KASSERT(consistency_a == consistency_b, 289 ("inconsistent links between pin config and cdevpriv")); 290 if (consistency_a == 1 && consistency_b == 1) { 291 mtx_unlock(&priv->mtx); 292 return (EEXIST); 293 } 294 priv_link = malloc(sizeof(struct gpioc_privs), M_GPIOC, 295 M_NOWAIT | M_ZERO); 296 if (priv_link == NULL) 297 { 298 mtx_unlock(&priv->mtx); 299 return (ENOMEM); 300 } 301 pin_link = malloc(sizeof(struct gpioc_pins), M_GPIOC, 302 M_NOWAIT | M_ZERO); 303 if (pin_link == NULL) { 304 mtx_unlock(&priv->mtx); 305 return (ENOMEM); 306 } 307 priv_link->priv = priv; 308 pin_link->pin = intr_conf; 309 SLIST_INSERT_HEAD(&intr_conf->privs, priv_link, next); 310 SLIST_INSERT_HEAD(&priv->pins, pin_link, next); 311 mtx_unlock(&priv->mtx); 312 313 return (0); 314} 315 316static int 317gpioc_detach_priv_pin(struct gpioc_cdevpriv *priv, 318 struct gpioc_pin_intr *intr_conf) 319{ 320 struct gpioc_privs *priv_link, *priv_link_temp; 321 struct gpioc_pins *pin_link, *pin_link_temp; 322 unsigned int consistency_a, consistency_b; 323 324 consistency_a = 0; 325 consistency_b = 0; 326 mtx_assert(&intr_conf->mtx, MA_OWNED); 327 mtx_lock(&priv->mtx); 328 SLIST_FOREACH_SAFE(priv_link, &intr_conf->privs, next, priv_link_temp) { 329 if (priv_link->priv == priv) { 330 SLIST_REMOVE(&intr_conf->privs, priv_link, gpioc_privs, 331 next); 332 free(priv_link, M_GPIOC); 333 consistency_a++; 334 } 335 } 336 KASSERT(consistency_a <= 1, 337 ("inconsistent links between pin config and cdevpriv")); 338 SLIST_FOREACH_SAFE(pin_link, &priv->pins, next, pin_link_temp) { 339 if (pin_link->pin == intr_conf) { 340 /* 341 * If the pin we're removing has events in the priv's 342 * event fifo, we can't leave dangling pointers from 343 * those events to the gpioc_pins struct we're about to 344 * free. We also can't remove random items and leave 345 * holes in the events fifo, so just empty it out. 346 */ 347 if (pin_link->eventcount > 0) { 348 priv->evidx_head = priv->evidx_tail = 0; 349 } 350 SLIST_REMOVE(&priv->pins, pin_link, gpioc_pins, next); 351 free(pin_link, M_GPIOC); 352 consistency_b++; 353 } 354 } 355 KASSERT(consistency_a == consistency_b, 356 ("inconsistent links between pin config and cdevpriv")); 357 mtx_unlock(&priv->mtx); 358 359 return (0); 360} 361 362static bool 363gpioc_intr_reconfig_allowed(struct gpioc_cdevpriv *priv, 364 struct gpioc_pin_intr *intr_conf) 365{ 366 struct gpioc_privs *priv_link; 367 368 mtx_assert(&intr_conf->mtx, MA_OWNED); 369 370 if (SLIST_EMPTY(&intr_conf->privs)) 371 return (true); 372 373 SLIST_FOREACH(priv_link, &intr_conf->privs, next) { 374 if (priv_link->priv != priv) 375 return (false); 376 } 377 378 return (true); 379} 380 381 382static uint32_t 383gpioc_get_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, 384 uint32_t pin) 385{ 386 struct gpioc_pin_intr *intr_conf = &sc->sc_pin_intr[pin]; 387 struct gpioc_privs *priv_link; 388 uint32_t flags; 389 390 flags = intr_conf->pin->flags; 391 392 if (flags == 0) 393 return (0); 394 395 mtx_lock(&intr_conf->mtx); 396 SLIST_FOREACH(priv_link, &intr_conf->privs, next) { 397 if (priv_link->priv == priv) { 398 flags |= GPIO_INTR_ATTACHED; 399 break; 400 } 401 } 402 mtx_unlock(&intr_conf->mtx); 403 404 return (flags); 405} 406 407static int 408gpioc_set_intr_config(struct gpioc_softc *sc, struct gpioc_cdevpriv *priv, 409 uint32_t pin, uint32_t flags) 410{ 411 struct gpioc_pin_intr *intr_conf = &sc->sc_pin_intr[pin]; 412 int res; 413 414 res = 0; 415 if (intr_conf->pin->flags == 0 && flags == 0) { 416 /* No interrupt configured and none requested: Do nothing. */ 417 return (0); 418 } 419 mtx_lock(&intr_conf->mtx); 420 while (intr_conf->config_locked == true) 421 mtx_sleep(&intr_conf->config_locked, &intr_conf->mtx, 0, 422 "gpicfg", 0); 423 if (intr_conf->pin->flags == 0 && flags != 0) { 424 /* 425 * No interrupt is configured, but one is requested: Allocate 426 * and setup interrupt on the according pin. 427 */ 428 res = gpioc_allocate_pin_intr(intr_conf, flags); 429 if (res == 0) 430 res = gpioc_attach_priv_pin(priv, intr_conf); 431 if (res == EEXIST) 432 res = 0; 433 } else if (intr_conf->pin->flags == flags) { 434 /* 435 * Same interrupt requested as already configured: Attach the 436 * cdevpriv to the corresponding pin. 437 */ 438 res = gpioc_attach_priv_pin(priv, intr_conf); 439 if (res == EEXIST) 440 res = 0; 441 } else if (intr_conf->pin->flags != 0 && flags == 0) { 442 /* 443 * Interrupt configured, but none requested: Teardown and 444 * release the pin when no other cdevpriv is attached. Otherwise 445 * just detach pin and cdevpriv from each other. 446 */ 447 if (gpioc_intr_reconfig_allowed(priv, intr_conf)) { 448 res = gpioc_release_pin_intr(intr_conf); 449 } 450 if (res == 0) 451 res = gpioc_detach_priv_pin(priv, intr_conf); 452 } else { 453 /* 454 * Other flag requested than configured: Reconfigure when no 455 * other cdevpriv is are attached to the pin. 456 */ 457 if (!gpioc_intr_reconfig_allowed(priv, intr_conf)) 458 res = EBUSY; 459 else { 460 res = gpioc_release_pin_intr(intr_conf); 461 if (res == 0) 462 res = gpioc_allocate_pin_intr(intr_conf, flags); 463 if (res == 0) 464 res = gpioc_attach_priv_pin(priv, intr_conf); 465 if (res == EEXIST) 466 res = 0; 467 } 468 } 469 mtx_unlock(&intr_conf->mtx); 470 471 return (res); 472} 473 474static void 475gpioc_interrupt_handler(void *arg) 476{ 477 struct gpioc_pin_intr *intr_conf; 478 struct gpioc_privs *privs; 479 struct gpioc_softc *sc; 480 sbintime_t evtime; 481 uint32_t pin_state; 482 483 intr_conf = arg; 484 sc = intr_conf->sc; 485 486 /* Capture time and pin state first. */ 487 evtime = sbinuptime(); 488 if (intr_conf->pin->flags & GPIO_INTR_EDGE_BOTH) 489 GPIO_PIN_GET(sc->sc_pdev, intr_conf->pin->pin, &pin_state); 490 else if (intr_conf->pin->flags & GPIO_INTR_EDGE_RISING) 491 pin_state = true; 492 else 493 pin_state = false; 494 495 mtx_lock(&intr_conf->mtx); 496 497 if (intr_conf->config_locked == true) { 498 ddevice_printf(sc->sc_dev, "Interrupt configuration in " 499 "progress. Discarding interrupt on pin %d.\n", 500 intr_conf->pin->pin); 501 mtx_unlock(&intr_conf->mtx); 502 return; 503 } 504 505 if (SLIST_EMPTY(&intr_conf->privs)) { 506 ddevice_printf(sc->sc_dev, "No file descriptor associated with " 507 "occurred interrupt on pin %d.\n", intr_conf->pin->pin); 508 mtx_unlock(&intr_conf->mtx); 509 return; 510 } 511 512 SLIST_FOREACH(privs, &intr_conf->privs, next) { 513 struct gpioc_cdevpriv *priv = privs->priv; 514 struct gpioc_pins *privpin; 515 struct gpioc_pin_event *event; 516 mtx_lock(&priv->mtx); 517 SLIST_FOREACH(privpin, &priv->pins, next) { 518 if (privpin->pin == intr_conf) 519 break; 520 } 521 if (privpin == NULL) { 522 /* Should be impossible. */ 523 ddevice_printf(sc->sc_dev, "Cannot find privpin\n"); 524 mtx_unlock(&priv->mtx); 525 continue; 526 } 527 528 if (priv->report_option == GPIO_EVENT_REPORT_DETAIL) { 529 event = next_head_event(priv); 530 /* If head is overtaking tail, advance tail. */ 531 if (priv->evidx_head == priv->evidx_tail) 532 next_tail_event(priv); 533 } else { 534 if (privpin->eventcount > 0) 535 event = &priv->events[privpin->firstevent + 1]; 536 else { 537 privpin->firstevent = priv->evidx_head; 538 event = next_head_event(priv); 539 event->privpin = privpin; 540 event->event_time = evtime; 541 event->event_pin_state = pin_state; 542 event = next_head_event(priv); 543 } 544 ++privpin->eventcount; 545 } 546 event->privpin = privpin; 547 event->event_time = evtime; 548 event->event_pin_state = pin_state; 549 wakeup(priv); 550 selwakeup(&priv->selinfo); 551 KNOTE_LOCKED(&priv->selinfo.si_note, 0); 552 if (priv->async == true && priv->sigio != NULL) 553 pgsigio(&priv->sigio, SIGIO, 0); 554 mtx_unlock(&priv->mtx); 555 } 556 557 mtx_unlock(&intr_conf->mtx); 558} 559 560static int |
|
74gpioc_probe(device_t dev) 75{ 76 device_set_desc(dev, "GPIO controller"); 77 return (0); 78} 79 80static int 81gpioc_attach(device_t dev) 82{ 83 int err; 84 struct gpioc_softc *sc; 85 struct make_dev_args devargs; 86 87 sc = device_get_softc(dev); 88 sc->sc_dev = dev; 89 sc->sc_pdev = device_get_parent(dev); 90 sc->sc_unit = device_get_unit(dev); | 561gpioc_probe(device_t dev) 562{ 563 device_set_desc(dev, "GPIO controller"); 564 return (0); 565} 566 567static int 568gpioc_attach(device_t dev) 569{ 570 int err; 571 struct gpioc_softc *sc; 572 struct make_dev_args devargs; 573 574 sc = device_get_softc(dev); 575 sc->sc_dev = dev; 576 sc->sc_pdev = device_get_parent(dev); 577 sc->sc_unit = device_get_unit(dev); |
578 579 err = GPIO_PIN_MAX(sc->sc_pdev, &sc->sc_npins); 580 sc->sc_npins++; /* Number of pins is one more than max pin number. */ 581 if (err != 0) 582 return (err); 583 sc->sc_pin_intr = malloc(sizeof(struct gpioc_pin_intr) * sc->sc_npins, 584 M_GPIOC, M_WAITOK | M_ZERO); 585 for (int i = 0; i <= sc->sc_npins; i++) { 586 sc->sc_pin_intr[i].pin = malloc(sizeof(struct gpiobus_pin), 587 M_GPIOC, M_WAITOK | M_ZERO); 588 sc->sc_pin_intr[i].sc = sc; 589 sc->sc_pin_intr[i].pin->pin = i; 590 sc->sc_pin_intr[i].pin->dev = sc->sc_pdev; 591 mtx_init(&sc->sc_pin_intr[i].mtx, "gpioc pin", NULL, MTX_DEF); 592 SLIST_INIT(&sc->sc_pin_intr[i].privs); 593 } 594 |
|
91 make_dev_args_init(&devargs); 92 devargs.mda_devsw = &gpioc_cdevsw; 93 devargs.mda_uid = UID_ROOT; 94 devargs.mda_gid = GID_WHEEL; 95 devargs.mda_mode = 0600; 96 devargs.mda_si_drv1 = sc; 97 err = make_dev_s(&devargs, &sc->sc_ctl_dev, "gpioc%d", sc->sc_unit); 98 if (err != 0) { | 595 make_dev_args_init(&devargs); 596 devargs.mda_devsw = &gpioc_cdevsw; 597 devargs.mda_uid = UID_ROOT; 598 devargs.mda_gid = GID_WHEEL; 599 devargs.mda_mode = 0600; 600 devargs.mda_si_drv1 = sc; 601 err = make_dev_s(&devargs, &sc->sc_ctl_dev, "gpioc%d", sc->sc_unit); 602 if (err != 0) { |
99 printf("Failed to create gpioc%d", sc->sc_unit); | 603 device_printf(dev, "Failed to create gpioc%d", sc->sc_unit); |
100 return (ENXIO); 101 } 102 103 return (0); 104} 105 106static int 107gpioc_detach(device_t dev) 108{ 109 struct gpioc_softc *sc = device_get_softc(dev); 110 int err; 111 112 if (sc->sc_ctl_dev) 113 destroy_dev(sc->sc_ctl_dev); 114 | 604 return (ENXIO); 605 } 606 607 return (0); 608} 609 610static int 611gpioc_detach(device_t dev) 612{ 613 struct gpioc_softc *sc = device_get_softc(dev); 614 int err; 615 616 if (sc->sc_ctl_dev) 617 destroy_dev(sc->sc_ctl_dev); 618 |
619 for (int i = 0; i <= sc->sc_npins; i++) { 620 mtx_destroy(&sc->sc_pin_intr[i].mtx); 621 free(&sc->sc_pin_intr[i].pin, M_GPIOC); 622 } 623 free(sc->sc_pin_intr, M_GPIOC); 624 |
|
115 if ((err = bus_generic_detach(dev)) != 0) 116 return (err); 117 118 return (0); 119} 120 | 625 if ((err = bus_generic_detach(dev)) != 0) 626 return (err); 627 628 return (0); 629} 630 |
631static void 632gpioc_cdevpriv_dtor(void *data) 633{ 634 struct gpioc_cdevpriv *priv; 635 struct gpioc_privs *priv_link, *priv_link_temp; 636 struct gpioc_pins *pin_link, *pin_link_temp; 637 unsigned int consistency; 638 639 priv = data; 640 641 SLIST_FOREACH_SAFE(pin_link, &priv->pins, next, pin_link_temp) { 642 consistency = 0; 643 mtx_lock(&pin_link->pin->mtx); 644 while (pin_link->pin->config_locked == true) 645 mtx_sleep(&pin_link->pin->config_locked, 646 &pin_link->pin->mtx, 0, "gpicfg", 0); 647 SLIST_FOREACH_SAFE(priv_link, &pin_link->pin->privs, next, 648 priv_link_temp) { 649 if (priv_link->priv == priv) { 650 SLIST_REMOVE(&pin_link->pin->privs, priv_link, 651 gpioc_privs, next); 652 free(priv_link, M_GPIOC); 653 consistency++; 654 } 655 } 656 KASSERT(consistency == 1, 657 ("inconsistent links between pin config and cdevpriv")); 658 if (gpioc_intr_reconfig_allowed(priv, pin_link->pin)) { 659 gpioc_release_pin_intr(pin_link->pin); 660 } 661 mtx_unlock(&pin_link->pin->mtx); 662 SLIST_REMOVE(&priv->pins, pin_link, gpioc_pins, next); 663 free(pin_link, M_GPIOC); 664 } 665 666 wakeup(&priv); 667 knlist_clear(&priv->selinfo.si_note, 0); 668 seldrain(&priv->selinfo); 669 knlist_destroy(&priv->selinfo.si_note); 670 funsetown(&priv->sigio); 671 672 mtx_destroy(&priv->mtx); 673 free(priv->events, M_GPIOC); 674 free(data, M_GPIOC); 675} 676 677static int 678gpioc_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 679{ 680 struct gpioc_cdevpriv *priv; 681 int err; 682 683 priv = malloc(sizeof(*priv), M_GPIOC, M_WAITOK | M_ZERO); 684 priv->sc = dev->si_drv1; 685 priv->report_option = GPIO_EVENT_REPORT_DETAIL; 686 err = devfs_set_cdevpriv(priv, gpioc_cdevpriv_dtor); 687 if (err != 0) { 688 gpioc_cdevpriv_dtor(priv); 689 return (err); 690 } 691 mtx_init(&priv->mtx, "gpioc priv", NULL, MTX_DEF); 692 knlist_init_mtx(&priv->selinfo.si_note, &priv->mtx); 693 694 /* 695 * Allocate a circular buffer for events. The scheme we use for summary 696 * reporting assumes there will always be a pair of events available to 697 * record the first/last events on any pin, so we allocate 2 * npins. 698 * Even though we actually default to detailed event reporting, 2 * 699 * npins isn't a horrible fifo size for that either. 700 */ 701 priv->numevents = priv->sc->sc_npins * 2; 702 priv->events = malloc(priv->numevents * sizeof(struct gpio_event_detail), 703 M_GPIOC, M_WAITOK | M_ZERO); 704 705 return (0); 706} 707 708static int 709gpioc_read(struct cdev *dev, struct uio *uio, int ioflag) 710{ 711 struct gpioc_cdevpriv *priv; 712 struct gpioc_pin_event *event; 713 union { 714 struct gpio_event_summary sum; 715 struct gpio_event_detail evt; 716 uint8_t data[1]; 717 } recbuf; 718 size_t recsize; 719 int err; 720 721 if ((err = devfs_get_cdevpriv((void **)&priv)) != 0) 722 return (err); 723 724 if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY) 725 recsize = sizeof(struct gpio_event_summary); 726 else 727 recsize = sizeof(struct gpio_event_detail); 728 729 if (uio->uio_resid < recsize) 730 return (EINVAL); 731 732 mtx_lock(&priv->mtx); 733 while (priv->evidx_head == priv->evidx_tail) { 734 if (SLIST_EMPTY(&priv->pins)) { 735 err = ENXIO; 736 break; 737 } else if (ioflag & O_NONBLOCK) { 738 err = EWOULDBLOCK; 739 break; 740 } else { 741 err = mtx_sleep(priv, &priv->mtx, PCATCH, "gpintr", 0); 742 if (err != 0) 743 break; 744 } 745 } 746 747 while (err == 0 && uio->uio_resid >= recsize && 748 priv->evidx_tail != priv->evidx_head) { 749 event = next_tail_event(priv); 750 if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY) { 751 recbuf.sum.gp_first_time = event->event_time; 752 recbuf.sum.gp_pin = event->privpin->pin->pin->pin; 753 recbuf.sum.gp_count = event->privpin->eventcount; 754 recbuf.sum.gp_first_state = event->event_pin_state; 755 event = next_tail_event(priv); 756 recbuf.sum.gp_last_time = event->event_time; 757 recbuf.sum.gp_last_state = event->event_pin_state; 758 event->privpin->eventcount = 0; 759 event->privpin->firstevent = 0; 760 } else { 761 recbuf.evt.gp_time = event->event_time; 762 recbuf.evt.gp_pin = event->privpin->pin->pin->pin; 763 recbuf.evt.gp_pinstate = event->event_pin_state; 764 } 765 mtx_unlock(&priv->mtx); 766 err = uiomove(recbuf.data, recsize, uio); 767 mtx_lock(&priv->mtx); 768 } 769 mtx_unlock(&priv->mtx); 770 return (err); 771} 772 |
|
121static int 122gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 123 struct thread *td) 124{ 125 device_t bus; 126 int max_pin, res; 127 struct gpioc_softc *sc = cdev->si_drv1; | 773static int 774gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag, 775 struct thread *td) 776{ 777 device_t bus; 778 int max_pin, res; 779 struct gpioc_softc *sc = cdev->si_drv1; |
780 struct gpioc_cdevpriv *priv; |
|
128 struct gpio_pin pin; 129 struct gpio_req req; 130 struct gpio_access_32 *a32; 131 struct gpio_config_32 *c32; | 781 struct gpio_pin pin; 782 struct gpio_req req; 783 struct gpio_access_32 *a32; 784 struct gpio_config_32 *c32; |
132 uint32_t caps; | 785 struct gpio_event_config *evcfg; 786 uint32_t caps, intrflags; |
133 134 bus = GPIO_GET_BUS(sc->sc_pdev); 135 if (bus == NULL) 136 return (EINVAL); 137 switch (cmd) { | 787 788 bus = GPIO_GET_BUS(sc->sc_pdev); 789 if (bus == NULL) 790 return (EINVAL); 791 switch (cmd) { |
138 case GPIOMAXPIN: 139 max_pin = -1; 140 res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin); 141 bcopy(&max_pin, arg, sizeof(max_pin)); | 792 case GPIOMAXPIN: 793 max_pin = -1; 794 res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin); 795 bcopy(&max_pin, arg, sizeof(max_pin)); 796 break; 797 case GPIOGETCONFIG: 798 bcopy(arg, &pin, sizeof(pin)); 799 dprintf("get config pin %d\n", pin.gp_pin); 800 res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, 801 &pin.gp_flags); 802 /* Fail early */ 803 if (res) |
142 break; | 804 break; |
143 case GPIOGETCONFIG: 144 bcopy(arg, &pin, sizeof(pin)); 145 dprintf("get config pin %d\n", pin.gp_pin); 146 res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin, 147 &pin.gp_flags); 148 /* Fail early */ 149 if (res) 150 break; 151 GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); 152 GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name); 153 bcopy(&pin, arg, sizeof(pin)); | 805 res = devfs_get_cdevpriv((void **)&priv); 806 if (res) |
154 break; | 807 break; |
155 case GPIOSETCONFIG: 156 bcopy(arg, &pin, sizeof(pin)); 157 dprintf("set config pin %d\n", pin.gp_pin); 158 res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps); 159 if (res == 0) 160 res = gpio_check_flags(caps, pin.gp_flags); 161 if (res == 0) 162 res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, 163 pin.gp_flags); | 808 pin.gp_flags |= gpioc_get_intr_config(sc, priv, 809 pin.gp_pin); 810 GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps); 811 GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name); 812 bcopy(&pin, arg, sizeof(pin)); 813 break; 814 case GPIOSETCONFIG: 815 bcopy(arg, &pin, sizeof(pin)); 816 dprintf("set config pin %d\n", pin.gp_pin); 817 res = devfs_get_cdevpriv((void **)&priv); 818 if (res != 0) |
164 break; | 819 break; |
165 case GPIOGET: 166 bcopy(arg, &req, sizeof(req)); 167 res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin, 168 &req.gp_value); 169 dprintf("read pin %d -> %d\n", 170 req.gp_pin, req.gp_value); 171 bcopy(&req, arg, sizeof(req)); | 820 res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps); 821 if (res != 0) |
172 break; | 822 break; |
173 case GPIOSET: 174 bcopy(arg, &req, sizeof(req)); 175 res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 176 req.gp_value); 177 dprintf("write pin %d -> %d\n", 178 req.gp_pin, req.gp_value); | 823 res = gpio_check_flags(caps, pin.gp_flags); 824 if (res != 0) |
179 break; | 825 break; |
180 case GPIOTOGGLE: 181 bcopy(arg, &req, sizeof(req)); 182 dprintf("toggle pin %d\n", 183 req.gp_pin); 184 res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin); | 826 intrflags = pin.gp_flags & GPIO_INTR_MASK; 827 /* 828 * We can do only edge interrupts, and only if the 829 * hardware supports that interrupt type on that pin. 830 */ 831 switch (intrflags) { 832 case GPIO_INTR_NONE: |
185 break; | 833 break; |
186 case GPIOSETNAME: 187 bcopy(arg, &pin, sizeof(pin)); 188 dprintf("set name on pin %d\n", pin.gp_pin); 189 res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin, 190 pin.gp_name); | 834 case GPIO_INTR_EDGE_RISING: 835 case GPIO_INTR_EDGE_FALLING: 836 case GPIO_INTR_EDGE_BOTH: 837 if ((intrflags & caps) == 0) 838 res = EOPNOTSUPP; |
191 break; | 839 break; |
192 case GPIOACCESS32: 193 a32 = (struct gpio_access_32 *)arg; 194 res = GPIO_PIN_ACCESS_32(sc->sc_pdev, a32->first_pin, 195 a32->clear_pins, a32->change_pins, &a32->orig_pins); | 840 default: 841 res = EINVAL; |
196 break; | 842 break; |
197 case GPIOCONFIG32: 198 c32 = (struct gpio_config_32 *)arg; 199 res = GPIO_PIN_CONFIG_32(sc->sc_pdev, c32->first_pin, 200 c32->num_pins, c32->pin_flags); | 843 } 844 if (res != 0) |
201 break; | 845 break; |
202 default: 203 return (ENOTTY); | 846 res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin, 847 (pin.gp_flags & ~GPIO_INTR_MASK)); 848 if (res != 0) |
204 break; | 849 break; |
850 res = gpioc_set_intr_config(sc, priv, pin.gp_pin, 851 intrflags); 852 break; 853 case GPIOGET: 854 bcopy(arg, &req, sizeof(req)); 855 res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin, 856 &req.gp_value); 857 dprintf("read pin %d -> %d\n", 858 req.gp_pin, req.gp_value); 859 bcopy(&req, arg, sizeof(req)); 860 break; 861 case GPIOSET: 862 bcopy(arg, &req, sizeof(req)); 863 res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin, 864 req.gp_value); 865 dprintf("write pin %d -> %d\n", 866 req.gp_pin, req.gp_value); 867 break; 868 case GPIOTOGGLE: 869 bcopy(arg, &req, sizeof(req)); 870 dprintf("toggle pin %d\n", 871 req.gp_pin); 872 res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin); 873 break; 874 case GPIOSETNAME: 875 bcopy(arg, &pin, sizeof(pin)); 876 dprintf("set name on pin %d\n", pin.gp_pin); 877 res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin, 878 pin.gp_name); 879 break; 880 case GPIOACCESS32: 881 a32 = (struct gpio_access_32 *)arg; 882 res = GPIO_PIN_ACCESS_32(sc->sc_pdev, a32->first_pin, 883 a32->clear_pins, a32->change_pins, &a32->orig_pins); 884 break; 885 case GPIOCONFIG32: 886 c32 = (struct gpio_config_32 *)arg; 887 res = GPIO_PIN_CONFIG_32(sc->sc_pdev, c32->first_pin, 888 c32->num_pins, c32->pin_flags); 889 break; 890 case GPIOCONFIGEVENTS: 891 evcfg = (struct gpio_event_config *)arg; 892 res = devfs_get_cdevpriv((void **)&priv); 893 if (res != 0) 894 break; 895 /* If any pins have been configured, changes aren't allowed. */ 896 if (!SLIST_EMPTY(&priv->pins)) { 897 res = EINVAL; 898 break; 899 } 900 if (evcfg->gp_report_type != GPIO_EVENT_REPORT_DETAIL && 901 evcfg->gp_report_type != GPIO_EVENT_REPORT_SUMMARY) { 902 res = EINVAL; 903 break; 904 } 905 priv->report_option = evcfg->gp_report_type; 906 /* Reallocate the events buffer if the user wants it bigger. */ 907 if (priv->report_option == GPIO_EVENT_REPORT_DETAIL && 908 priv->numevents < evcfg->gp_fifo_size) { 909 free(priv->events, M_GPIOC); 910 priv->numevents = evcfg->gp_fifo_size; 911 priv->events = malloc(priv->numevents * 912 sizeof(struct gpio_event_detail), M_GPIOC, 913 M_WAITOK | M_ZERO); 914 priv->evidx_head = priv->evidx_tail = 0; 915 } 916 break; 917 case FIONBIO: 918 /* 919 * This dummy handler is necessary to prevent fcntl() 920 * from failing. The actual handling of non-blocking IO 921 * is done using the O_NONBLOCK ioflag passed to the 922 * read() syscall. 923 */ 924 res = 0; 925 break; 926 case FIOASYNC: 927 res = devfs_get_cdevpriv((void **)&priv); 928 if (res == 0) { 929 if (*(int *)arg == FASYNC) 930 priv->async = true; 931 else 932 priv->async = false; 933 } 934 break; 935 case FIOGETOWN: 936 res = devfs_get_cdevpriv((void **)&priv); 937 if (res == 0) 938 *(int *)arg = fgetown(&priv->sigio); 939 break; 940 case FIOSETOWN: 941 res = devfs_get_cdevpriv((void **)&priv); 942 if (res == 0) 943 res = fsetown(*(int *)arg, &priv->sigio); 944 break; 945 default: 946 return (ENOTTY); 947 break; |
|
205 } 206 207 return (res); 208} 209 | 948 } 949 950 return (res); 951} 952 |
953static int 954gpioc_poll(struct cdev *dev, int events, struct thread *td) 955{ 956 struct gpioc_cdevpriv *priv; 957 int err; 958 int revents; 959 960 revents = 0; 961 962 err = devfs_get_cdevpriv((void **)&priv); 963 if (err != 0) { 964 revents = POLLERR; 965 return (revents); 966 } 967 968 if (SLIST_EMPTY(&priv->pins)) { 969 revents = POLLHUP; 970 return (revents); 971 } 972 973 if (events & (POLLIN | POLLRDNORM)) { 974 if (priv->evidx_head != priv->evidx_tail) 975 revents |= events & (POLLIN | POLLRDNORM); 976 else 977 selrecord(td, &priv->selinfo); 978 } 979 980 return (revents); 981} 982 983static int 984gpioc_kqfilter(struct cdev *dev, struct knote *kn) 985{ 986 struct gpioc_cdevpriv *priv; 987 struct knlist *knlist; 988 int err; 989 990 err = devfs_get_cdevpriv((void **)&priv); 991 if (err != 0) 992 return err; 993 994 if (SLIST_EMPTY(&priv->pins)) 995 return (ENXIO); 996 997 switch(kn->kn_filter) { 998 case EVFILT_READ: 999 kn->kn_fop = &gpioc_read_filterops; 1000 kn->kn_hook = (void *)priv; 1001 break; 1002 default: 1003 return (EOPNOTSUPP); 1004 } 1005 1006 knlist = &priv->selinfo.si_note; 1007 knlist_add(knlist, kn, 0); 1008 1009 return (0); 1010} 1011 1012static int 1013gpioc_kqread(struct knote *kn, long hint) 1014{ 1015 struct gpioc_cdevpriv *priv = kn->kn_hook; 1016 size_t recsize; 1017 1018 1019 if (SLIST_EMPTY(&priv->pins)) { 1020 kn->kn_flags |= EV_EOF; 1021 return (1); 1022 } else { 1023 if (priv->evidx_head != priv->evidx_tail) { 1024 if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY) 1025 recsize = sizeof(struct gpio_event_summary); 1026 else 1027 recsize = sizeof(struct gpio_event_detail); 1028 kn->kn_data = recsize * number_of_events(priv); 1029 return (1); 1030 } 1031 } 1032 return (0); 1033} 1034 1035static void 1036gpioc_kqdetach(struct knote *kn) 1037{ 1038 struct gpioc_cdevpriv *priv = kn->kn_hook; 1039 struct knlist *knlist = &priv->selinfo.si_note; 1040 1041 knlist_remove(knlist, kn, 0); 1042} 1043 |
|
210static device_method_t gpioc_methods[] = { 211 /* Device interface */ 212 DEVMETHOD(device_probe, gpioc_probe), 213 DEVMETHOD(device_attach, gpioc_attach), 214 DEVMETHOD(device_detach, gpioc_detach), 215 DEVMETHOD(device_shutdown, bus_generic_shutdown), 216 DEVMETHOD(device_suspend, bus_generic_suspend), 217 DEVMETHOD(device_resume, bus_generic_resume), --- 14 unchanged lines hidden --- | 1044static device_method_t gpioc_methods[] = { 1045 /* Device interface */ 1046 DEVMETHOD(device_probe, gpioc_probe), 1047 DEVMETHOD(device_attach, gpioc_attach), 1048 DEVMETHOD(device_detach, gpioc_detach), 1049 DEVMETHOD(device_shutdown, bus_generic_shutdown), 1050 DEVMETHOD(device_suspend, bus_generic_suspend), 1051 DEVMETHOD(device_resume, bus_generic_resume), --- 14 unchanged lines hidden --- |