xref: /freebsd/sys/dev/gpio/gpioc.c (revision 87b759f0fa1f7554d50ce640c40138512bbded44)
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 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 *
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 *
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
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
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
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
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
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
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
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
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
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
560 gpioc_probe(device_t dev)
561 {
562 	device_set_desc(dev, "GPIO controller");
563 	return (0);
564 }
565 
566 static int
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
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
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
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
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
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
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
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
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
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