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