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