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 ---