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