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