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
60struct 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
69struct 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
81struct 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
95struct gpioc_privs {
96	struct gpioc_cdevpriv		*priv;
97	SLIST_ENTRY(gpioc_privs)	next;
98};
99
100struct gpioc_pins {
101	struct gpioc_pin_intr	*pin;
102	int			eventcount;
103	int			firstevent;
104	SLIST_ENTRY(gpioc_pins)	next;
105};
106
107struct gpioc_pin_event {
108	struct gpioc_pins	*privpin;
109	sbintime_t		event_time;
110	bool			event_pin_state;
111};
112
113static MALLOC_DEFINE(M_GPIOC, "gpioc", "gpioc device data");
114
115static int	gpioc_allocate_pin_intr(struct gpioc_pin_intr*, uint32_t);
116static int	gpioc_release_pin_intr(struct gpioc_pin_intr*);
117static int	gpioc_attach_priv_pin(struct gpioc_cdevpriv*,
118		    struct gpioc_pin_intr*);
119static int	gpioc_detach_priv_pin(struct gpioc_cdevpriv*,
120		    struct gpioc_pin_intr*);
121static bool	gpioc_intr_reconfig_allowed(struct gpioc_cdevpriv*,
122		    struct gpioc_pin_intr *intr_conf);
123static uint32_t	gpioc_get_intr_config(struct gpioc_softc*,
124		    struct gpioc_cdevpriv*, uint32_t pin);
125static int	gpioc_set_intr_config(struct gpioc_softc*,
126		    struct gpioc_cdevpriv*, uint32_t, uint32_t);
127static void	gpioc_interrupt_handler(void*);
128
129static int	gpioc_kqread(struct knote*, long);
130static void	gpioc_kqdetach(struct knote*);
131
132static int	gpioc_probe(device_t dev);
133static int	gpioc_attach(device_t dev);
134static int	gpioc_detach(device_t dev);
135
136static void	gpioc_cdevpriv_dtor(void*);
137
138static d_open_t		gpioc_open;
139static d_read_t		gpioc_read;
140static d_ioctl_t	gpioc_ioctl;
141static d_poll_t		gpioc_poll;
142static d_kqfilter_t	gpioc_kqfilter;
143
144static 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
154static 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
162static struct gpioc_pin_event *
163next_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
173static struct gpioc_pin_event *
174next_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
184static size_t
185number_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
193static int
194gpioc_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
216error_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
224static int
225gpioc_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
255error_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
263static int
264gpioc_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
314static int
315gpioc_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
361static bool
362gpioc_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
381static uint32_t
382gpioc_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
406static int
407gpioc_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
473static void
474gpioc_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
559static int
560gpioc_probe(device_t dev)
561{
562	device_set_desc(dev, "GPIO controller");
563	return (0);
564}
565
566static int
567gpioc_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
609static int
610gpioc_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
630static void
631gpioc_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
676static int
677gpioc_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
678{
679	struct gpioc_cdevpriv *priv;
680	int err;
681
682	priv = malloc(sizeof(*priv), M_GPIOC, M_WAITOK | M_ZERO);
683	priv->sc = dev->si_drv1;
684	priv->report_option = GPIO_EVENT_REPORT_DETAIL;
685	err = devfs_set_cdevpriv(priv, gpioc_cdevpriv_dtor);
686	if (err != 0) {
687		gpioc_cdevpriv_dtor(priv);
688		return (err);
689	}
690	mtx_init(&priv->mtx, "gpioc priv", NULL, MTX_DEF);
691	knlist_init_mtx(&priv->selinfo.si_note, &priv->mtx);
692
693	/*
694	 * Allocate a circular buffer for events.  The scheme we use for summary
695	 * reporting assumes there will always be a pair of events available to
696	 * record the first/last events on any pin, so we allocate 2 * npins.
697	 * Even though we actually default to detailed event reporting, 2 *
698	 * npins isn't a horrible fifo size for that either.
699	 */
700	priv->numevents = priv->sc->sc_npins * 2;
701	priv->events = malloc(priv->numevents * sizeof(struct gpio_event_detail),
702	    M_GPIOC, M_WAITOK | M_ZERO);
703
704	return (0);
705}
706
707static int
708gpioc_read(struct cdev *dev, struct uio *uio, int ioflag)
709{
710	struct gpioc_cdevpriv *priv;
711	struct gpioc_pin_event *event;
712	union {
713		struct gpio_event_summary sum;
714		struct gpio_event_detail  evt;
715		uint8_t 		  data[1];
716	} recbuf;
717	size_t recsize;
718	int err;
719
720	if ((err = devfs_get_cdevpriv((void **)&priv)) != 0)
721		return (err);
722
723	if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY)
724		recsize = sizeof(struct gpio_event_summary);
725	else
726		recsize = sizeof(struct gpio_event_detail);
727
728	if (uio->uio_resid < recsize)
729		return (EINVAL);
730
731	mtx_lock(&priv->mtx);
732	while (priv->evidx_head == priv->evidx_tail) {
733		if (SLIST_EMPTY(&priv->pins)) {
734			err = ENXIO;
735			break;
736		} else if (ioflag & O_NONBLOCK) {
737			err = EWOULDBLOCK;
738			break;
739		} else {
740			err = mtx_sleep(priv, &priv->mtx, PCATCH, "gpintr", 0);
741			if (err != 0)
742				break;
743		}
744	}
745
746	while (err == 0 && uio->uio_resid >= recsize &&
747           priv->evidx_tail != priv->evidx_head) {
748		event = next_tail_event(priv);
749		if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY) {
750			recbuf.sum.gp_first_time = event->event_time;
751			recbuf.sum.gp_pin = event->privpin->pin->pin->pin;
752			recbuf.sum.gp_count = event->privpin->eventcount;
753			recbuf.sum.gp_first_state = event->event_pin_state;
754			event = next_tail_event(priv);
755			recbuf.sum.gp_last_time = event->event_time;
756			recbuf.sum.gp_last_state = event->event_pin_state;
757			event->privpin->eventcount = 0;
758			event->privpin->firstevent = 0;
759		} else {
760			recbuf.evt.gp_time = event->event_time;
761			recbuf.evt.gp_pin = event->privpin->pin->pin->pin;
762			recbuf.evt.gp_pinstate = event->event_pin_state;
763		}
764		mtx_unlock(&priv->mtx);
765		err = uiomove(recbuf.data, recsize, uio);
766		mtx_lock(&priv->mtx);
767	}
768	mtx_unlock(&priv->mtx);
769	return (err);
770}
771
772static int
773gpioc_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int fflag,
774    struct thread *td)
775{
776	device_t bus;
777	int max_pin, res;
778	struct gpioc_softc *sc = cdev->si_drv1;
779	struct gpioc_cdevpriv *priv;
780	struct gpio_pin pin;
781	struct gpio_req req;
782	struct gpio_access_32 *a32;
783	struct gpio_config_32 *c32;
784	struct gpio_event_config *evcfg;
785	uint32_t caps, intrflags;
786
787	bus = GPIO_GET_BUS(sc->sc_pdev);
788	if (bus == NULL)
789		return (EINVAL);
790	switch (cmd) {
791	case GPIOMAXPIN:
792		max_pin = -1;
793		res = GPIO_PIN_MAX(sc->sc_pdev, &max_pin);
794		bcopy(&max_pin, arg, sizeof(max_pin));
795		break;
796	case GPIOGETCONFIG:
797		bcopy(arg, &pin, sizeof(pin));
798		dprintf("get config pin %d\n", pin.gp_pin);
799		res = GPIO_PIN_GETFLAGS(sc->sc_pdev, pin.gp_pin,
800		    &pin.gp_flags);
801		/* Fail early */
802		if (res)
803			break;
804		res = devfs_get_cdevpriv((void **)&priv);
805		if (res)
806			break;
807		pin.gp_flags |= gpioc_get_intr_config(sc, priv,
808		    pin.gp_pin);
809		GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &pin.gp_caps);
810		GPIOBUS_PIN_GETNAME(bus, pin.gp_pin, pin.gp_name);
811		bcopy(&pin, arg, sizeof(pin));
812		break;
813	case GPIOSETCONFIG:
814		bcopy(arg, &pin, sizeof(pin));
815		dprintf("set config pin %d\n", pin.gp_pin);
816		res = devfs_get_cdevpriv((void **)&priv);
817		if (res != 0)
818			break;
819		res = GPIO_PIN_GETCAPS(sc->sc_pdev, pin.gp_pin, &caps);
820		if (res != 0)
821			break;
822		res = gpio_check_flags(caps, pin.gp_flags);
823		if (res != 0)
824			break;
825		intrflags = pin.gp_flags & GPIO_INTR_MASK;
826		/*
827		 * We can do only edge interrupts, and only if the
828		 * hardware supports that interrupt type on that pin.
829		 */
830		switch (intrflags) {
831		case GPIO_INTR_NONE:
832			break;
833		case GPIO_INTR_EDGE_RISING:
834		case GPIO_INTR_EDGE_FALLING:
835		case GPIO_INTR_EDGE_BOTH:
836			if ((intrflags & caps) == 0)
837				res = EOPNOTSUPP;
838			break;
839		default:
840			res = EINVAL;
841			break;
842		}
843		if (res != 0)
844			break;
845		res = GPIO_PIN_SETFLAGS(sc->sc_pdev, pin.gp_pin,
846		    (pin.gp_flags & ~GPIO_INTR_MASK));
847		if (res != 0)
848			break;
849		res = gpioc_set_intr_config(sc, priv, pin.gp_pin,
850		    intrflags);
851		break;
852	case GPIOGET:
853		bcopy(arg, &req, sizeof(req));
854		res = GPIO_PIN_GET(sc->sc_pdev, req.gp_pin,
855		    &req.gp_value);
856		dprintf("read pin %d -> %d\n",
857		    req.gp_pin, req.gp_value);
858		bcopy(&req, arg, sizeof(req));
859		break;
860	case GPIOSET:
861		bcopy(arg, &req, sizeof(req));
862		res = GPIO_PIN_SET(sc->sc_pdev, req.gp_pin,
863		    req.gp_value);
864		dprintf("write pin %d -> %d\n",
865		    req.gp_pin, req.gp_value);
866		break;
867	case GPIOTOGGLE:
868		bcopy(arg, &req, sizeof(req));
869		dprintf("toggle pin %d\n",
870		    req.gp_pin);
871		res = GPIO_PIN_TOGGLE(sc->sc_pdev, req.gp_pin);
872		break;
873	case GPIOSETNAME:
874		bcopy(arg, &pin, sizeof(pin));
875		dprintf("set name on pin %d\n", pin.gp_pin);
876		res = GPIOBUS_PIN_SETNAME(bus, pin.gp_pin,
877		    pin.gp_name);
878		break;
879	case GPIOACCESS32:
880		a32 = (struct gpio_access_32 *)arg;
881		res = GPIO_PIN_ACCESS_32(sc->sc_pdev, a32->first_pin,
882		    a32->clear_pins, a32->change_pins, &a32->orig_pins);
883		break;
884	case GPIOCONFIG32:
885		c32 = (struct gpio_config_32 *)arg;
886		res = GPIO_PIN_CONFIG_32(sc->sc_pdev, c32->first_pin,
887		    c32->num_pins, c32->pin_flags);
888		break;
889	case GPIOCONFIGEVENTS:
890		evcfg = (struct gpio_event_config *)arg;
891		res = devfs_get_cdevpriv((void **)&priv);
892		if (res != 0)
893			break;
894		/* If any pins have been configured, changes aren't allowed. */
895		if (!SLIST_EMPTY(&priv->pins)) {
896			res = EINVAL;
897			break;
898		}
899		if (evcfg->gp_report_type != GPIO_EVENT_REPORT_DETAIL &&
900		    evcfg->gp_report_type != GPIO_EVENT_REPORT_SUMMARY) {
901			res = EINVAL;
902			break;
903		}
904		priv->report_option = evcfg->gp_report_type;
905		/* Reallocate the events buffer if the user wants it bigger. */
906		if (priv->report_option == GPIO_EVENT_REPORT_DETAIL &&
907		    priv->numevents < evcfg->gp_fifo_size) {
908			free(priv->events, M_GPIOC);
909			priv->numevents = evcfg->gp_fifo_size;
910			priv->events = malloc(priv->numevents *
911			    sizeof(struct gpio_event_detail), M_GPIOC,
912			    M_WAITOK | M_ZERO);
913			priv->evidx_head = priv->evidx_tail = 0;
914		}
915		break;
916	case FIONBIO:
917		/*
918		 * This dummy handler is necessary to prevent fcntl()
919		 * from failing. The actual handling of non-blocking IO
920		 * is done using the O_NONBLOCK ioflag passed to the
921		 * read() syscall.
922		 */
923		res = 0;
924		break;
925	case FIOASYNC:
926		res = devfs_get_cdevpriv((void **)&priv);
927		if (res == 0) {
928			if (*(int *)arg == FASYNC)
929				priv->async = true;
930			else
931				priv->async = false;
932		}
933		break;
934	case FIOGETOWN:
935		res = devfs_get_cdevpriv((void **)&priv);
936		if (res == 0)
937			*(int *)arg = fgetown(&priv->sigio);
938		break;
939	case FIOSETOWN:
940		res = devfs_get_cdevpriv((void **)&priv);
941		if (res == 0)
942			res = fsetown(*(int *)arg, &priv->sigio);
943		break;
944	default:
945		return (ENOTTY);
946		break;
947	}
948
949	return (res);
950}
951
952static int
953gpioc_poll(struct cdev *dev, int events, struct thread *td)
954{
955	struct gpioc_cdevpriv *priv;
956	int err;
957	int revents;
958
959	revents = 0;
960
961	err = devfs_get_cdevpriv((void **)&priv);
962	if (err != 0) {
963		revents = POLLERR;
964		return (revents);
965	}
966
967	if (SLIST_EMPTY(&priv->pins)) {
968		revents = POLLHUP;
969		return (revents);
970	}
971
972	if (events & (POLLIN | POLLRDNORM)) {
973		if (priv->evidx_head != priv->evidx_tail)
974			revents |= events & (POLLIN | POLLRDNORM);
975		else
976			selrecord(td, &priv->selinfo);
977	}
978
979	return (revents);
980}
981
982static int
983gpioc_kqfilter(struct cdev *dev, struct knote *kn)
984{
985	struct gpioc_cdevpriv *priv;
986	struct knlist *knlist;
987	int err;
988
989	err = devfs_get_cdevpriv((void **)&priv);
990	if (err != 0)
991		return err;
992
993	if (SLIST_EMPTY(&priv->pins))
994		return (ENXIO);
995
996	switch(kn->kn_filter) {
997	case EVFILT_READ:
998		kn->kn_fop = &gpioc_read_filterops;
999		kn->kn_hook = (void *)priv;
1000		break;
1001	default:
1002		return (EOPNOTSUPP);
1003	}
1004
1005	knlist = &priv->selinfo.si_note;
1006	knlist_add(knlist, kn, 0);
1007
1008	return (0);
1009}
1010
1011static int
1012gpioc_kqread(struct knote *kn, long hint)
1013{
1014	struct gpioc_cdevpriv *priv = kn->kn_hook;
1015	size_t recsize;
1016
1017
1018	if (SLIST_EMPTY(&priv->pins)) {
1019		kn->kn_flags |= EV_EOF;
1020		return (1);
1021	} else {
1022		if (priv->evidx_head != priv->evidx_tail) {
1023			if (priv->report_option == GPIO_EVENT_REPORT_SUMMARY)
1024				recsize = sizeof(struct gpio_event_summary);
1025			else
1026				recsize = sizeof(struct gpio_event_detail);
1027			kn->kn_data = recsize * number_of_events(priv);
1028			return (1);
1029		}
1030	}
1031	return (0);
1032}
1033
1034static void
1035gpioc_kqdetach(struct knote *kn)
1036{
1037	struct gpioc_cdevpriv *priv = kn->kn_hook;
1038	struct knlist *knlist = &priv->selinfo.si_note;
1039
1040	knlist_remove(knlist, kn, 0);
1041}
1042
1043static device_method_t gpioc_methods[] = {
1044	/* Device interface */
1045	DEVMETHOD(device_probe,		gpioc_probe),
1046	DEVMETHOD(device_attach,	gpioc_attach),
1047	DEVMETHOD(device_detach,	gpioc_detach),
1048	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1049	DEVMETHOD(device_suspend,	bus_generic_suspend),
1050	DEVMETHOD(device_resume,	bus_generic_resume),
1051
1052	DEVMETHOD_END
1053};
1054
1055driver_t gpioc_driver = {
1056	"gpioc",
1057	gpioc_methods,
1058	sizeof(struct gpioc_softc)
1059};
1060
1061DRIVER_MODULE(gpioc, gpio, gpioc_driver, 0, 0);
1062MODULE_VERSION(gpioc, 1);
1063