Module Name: src Committed By: thorpej Date: Sat May 19 14:15:40 UTC 2018
Modified Files: src/distrib/sets/lists/man: mi src/distrib/sets/lists/modules: mi src/share/man/man4: Makefile src/sys/dev/gpio: files.gpio src/sys/modules: Makefile Added Files: src/share/man/man4: gpioirq.4 src/sys/dev/gpio: gpioirq.c src/sys/modules/gpioirq: Makefile gpioirq.ioconf Log Message: Add an example "gpioirq" driver that demonstrates interrupts on GPIO pins. Will be enhanced in the future to support sending events to user space on edge-triggered interrupt events. Based on initial work by Brad Spencer. PR kern/51676 To generate a diff of this commit: cvs rdiff -u -r1.1586 -r1.1587 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.114 -r1.115 src/distrib/sets/lists/modules/mi cvs rdiff -u -r1.652 -r1.653 src/share/man/man4/Makefile cvs rdiff -u -r0 -r1.1 src/share/man/man4/gpioirq.4 cvs rdiff -u -r1.14 -r1.15 src/sys/dev/gpio/files.gpio cvs rdiff -u -r0 -r1.1 src/sys/dev/gpio/gpioirq.c cvs rdiff -u -r1.202 -r1.203 src/sys/modules/Makefile cvs rdiff -u -r0 -r1.1 src/sys/modules/gpioirq/Makefile \ src/sys/modules/gpioirq/gpioirq.ioconf Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1586 src/distrib/sets/lists/man/mi:1.1587 --- src/distrib/sets/lists/man/mi:1.1586 Tue May 15 00:54:01 2018 +++ src/distrib/sets/lists/man/mi Sat May 19 14:15:39 2018 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1586 2018/05/15 00:54:01 nat Exp $ +# $NetBSD: mi,v 1.1587 2018/05/19 14:15:39 thorpej Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -1123,6 +1123,7 @@ ./usr/share/man/cat4/gpioiic.0 man-sys-catman .cat ./usr/share/man/cat4/gpiolock.0 man-sys-catman .cat ./usr/share/man/cat4/gpioow.0 man-sys-catman .cat +./usr/share/man/cat4/gpioirq.0 man-sys-catman .cat ./usr/share/man/cat4/gpiopwm.0 man-sys-catman .cat ./usr/share/man/cat4/gpiosim.0 man-sys-catman .cat ./usr/share/man/cat4/gre.0 man-sys-catman .cat @@ -4263,6 +4264,7 @@ ./usr/share/man/html4/gpioiic.html man-sys-htmlman html ./usr/share/man/html4/gpiolock.html man-sys-htmlman html ./usr/share/man/html4/gpioow.html man-sys-htmlman html +./usr/share/man/html4/gpioirq.html man-sys-htmlman html ./usr/share/man/html4/gpiopwm.html man-sys-htmlman html ./usr/share/man/html4/gpiosim.html man-sys-htmlman html ./usr/share/man/html4/gre.html man-sys-htmlman html @@ -7177,6 +7179,7 @@ ./usr/share/man/man4/gpioiic.4 man-sys-man .man ./usr/share/man/man4/gpiolock.4 man-sys-man .man ./usr/share/man/man4/gpioow.4 man-sys-man .man +./usr/share/man/man4/gpioirq.4 man-sys-man .man ./usr/share/man/man4/gpiopwm.4 man-sys-man .man ./usr/share/man/man4/gpiosim.4 man-sys-man .man ./usr/share/man/man4/gre.4 man-sys-man .man Index: src/distrib/sets/lists/modules/mi diff -u src/distrib/sets/lists/modules/mi:1.114 src/distrib/sets/lists/modules/mi:1.115 --- src/distrib/sets/lists/modules/mi:1.114 Tue Jan 9 03:31:14 2018 +++ src/distrib/sets/lists/modules/mi Sat May 19 14:15:39 2018 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.114 2018/01/09 03:31:14 christos Exp $ +# $NetBSD: mi,v 1.115 2018/05/19 14:15:39 thorpej Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -132,6 +132,8 @@ ./@MODULEDIR@/gpio/gpio.kmod base-kernel-modules kmod ./@MODULEDIR@/gpioiic base-kernel-modules kmod ./@MODULEDIR@/gpioiic/gpioiic.kmod base-kernel-modules kmod +./@MODULEDIR@/gpioirq base-kernel-modules kmod +./@MODULEDIR@/gpioirq/gpioirq.kmod base-kernel-modules kmod ./@MODULEDIR@/gpioow base-kernel-modules kmod ./@MODULEDIR@/gpioow/gpioow.kmod base-kernel-modules kmod ./@MODULEDIR@/gpiosim base-kernel-modules kmod Index: src/share/man/man4/Makefile diff -u src/share/man/man4/Makefile:1.652 src/share/man/man4/Makefile:1.653 --- src/share/man/man4/Makefile:1.652 Wed May 9 08:22:53 2018 +++ src/share/man/man4/Makefile Sat May 19 14:15:39 2018 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.652 2018/05/09 08:22:53 msaitoh Exp $ +# $NetBSD: Makefile,v 1.653 2018/05/19 14:15:39 thorpej Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 \ @@ -26,8 +26,8 @@ MAN= aac.4 ac97.4 acardide.4 aceride.4 a fast_ipsec.4 fd.4 filemon.4 finsio.4 flash.4 fpa.4 fms.4 fss.4 \ fujbp.4 full.4 fxp.4 \ gcscaudio.4 gem.4 genfb.4 gentbi.4 geodeide.4 \ - glxtphy.4 gpib.4 gpio.4 gpiolock.4 gpiopwm.4 gpiosim.4 gre.4 \ - gphyter.4 gsip.4 \ + glxtphy.4 gpib.4 gpio.4 gpioirq.4 gpiolock.4 gpiopwm.4 \ + gpiosim.4 gre.4 gphyter.4 gsip.4 \ hdaudio.4 hifn.4 hme.4 hpacel.4 hpqlb.4 hptide.4 hythygtemp.4 \ ibmcd.4 ibmhawk.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \ ifmedia.4 igmafb.4 igphy.4 igsfb.4 iha.4 ihidev.4 ihphy.4 iic.4 ims.4 \ Index: src/sys/dev/gpio/files.gpio diff -u src/sys/dev/gpio/files.gpio:1.14 src/sys/dev/gpio/files.gpio:1.15 --- src/sys/dev/gpio/files.gpio:1.14 Thu Oct 15 09:07:49 2015 +++ src/sys/dev/gpio/files.gpio Sat May 19 14:15:39 2018 @@ -1,4 +1,4 @@ -# $NetBSD: files.gpio,v 1.14 2015/10/15 09:07:49 jmcneill Exp $ +# $NetBSD: files.gpio,v 1.15 2018/05/19 14:15:39 thorpej Exp $ define gpio {[offset = -1], [mask = 0], [flag = 0]} @@ -39,3 +39,8 @@ file dev/gpio/gpiorfkill.c gpiorfkill device gpiobutton: gpiobus, sysmon_power, sysmon_taskq attach gpiobutton at gpio file dev/gpio/gpiobutton.c gpiobutton + +# GPIO interrupt example +device gpioirq: gpiobus +attach gpioirq at gpio +file dev/gpio/gpioirq.c gpioirq Index: src/sys/modules/Makefile diff -u src/sys/modules/Makefile:1.202 src/sys/modules/Makefile:1.203 --- src/sys/modules/Makefile:1.202 Mon Feb 26 07:29:24 2018 +++ src/sys/modules/Makefile Sat May 19 14:15:40 2018 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.202 2018/02/26 07:29:24 pgoyette Exp $ +# $NetBSD: Makefile,v 1.203 2018/05/19 14:15:40 thorpej Exp $ .include <bsd.own.mk> @@ -47,6 +47,7 @@ SUBDIR+= gpio SUBDIR+= gpioiic SUBDIR+= gpioow SUBDIR+= gpiosim +SUBDIR+= gpioirq SUBDIR+= hfs SUBDIR+= hythygtemp SUBDIR+= si70xxtemp Added files: Index: src/share/man/man4/gpioirq.4 diff -u /dev/null src/share/man/man4/gpioirq.4:1.1 --- /dev/null Sat May 19 14:15:40 2018 +++ src/share/man/man4/gpioirq.4 Sat May 19 14:15:39 2018 @@ -0,0 +1,97 @@ +.\" $NetBSD: gpioirq.4,v 1.1 2018/05/19 14:15:39 thorpej Exp $ +.\" +.\" Copyright (c) 2016 Brad Spencer <b...@anduin.eldar.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd May 11, 2018 +.Dt GPIOIRQ 4 +.Os +.Sh NAME +.Nm gpioirq +.Nd Install an interrupt handler on a GPIO pin +.Sh SYNOPSIS +.Cd "gpioirq* at gpio? offset 0 mask 0x1 flag 0x00" +.Sh DESCRIPTION +The +.Nm +driver attaches an interrupt handler to a single GPIO pin. +.Pp +The pin number is specified in the kernel configuration file with the +.Ar offset +locator. +The +.Ar mask +locator should always be 0x1. +.Pp +The +.Ar flag +locator specifies the interrupt mode to use: +.Bl -tag -width "XXXXXXXX" +.It Dv 0x01 +Interrupt on the positive +.Pq rising +edge of the pin. +.It Dv 0x02 +Interrupt on the negative +.Pq falling +edge of the pin. +.It Dv 0x04 +Interrupt on both edges of the pin. +.It Dv 0x08 +Assert the intrerrupt as long as the pin is high. +.It Dv 0x10 +Assert the interrupt as long as the pin is low. +.El +.Pp +Note that the interrupts modes are mutually-exclusive, and exactly one +interrupt mode must be specified. +These flags correspond to the +.Dv GPIO_INTR +mode bits defined in +.Pa sys/gpio.h . +In addition to the interrupt mode, setting +.Dv 0x1000 +in +.Ar flags +will enable the printing of a message to the console whenever the +interrupt handler is called. +.Pp +The +.Ar offset , +.Ar mask , +and +.Ar flag +locators can also be specified when +.Nm +is attached at runtime using the +.Dv GPIOATTACH +.Xr ioctl 2 +on the +.Xr gpio 4 +device. +.Sh SEE ALSO +.Xr gpio 4 , +.Xr drvctl 8 , +.Xr gpioctl 8 +.Sh HISTORY +The +.Nm +driver first appeared in +.Nx 9.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Brad Spencer Aq Mt b...@anduin.eldar.org Index: src/sys/dev/gpio/gpioirq.c diff -u /dev/null src/sys/dev/gpio/gpioirq.c:1.1 --- /dev/null Sat May 19 14:15:40 2018 +++ src/sys/dev/gpio/gpioirq.c Sat May 19 14:15:39 2018 @@ -0,0 +1,228 @@ +/* $NetBSD: gpioirq.c,v 1.1 2018/05/19 14:15:39 thorpej Exp $ */ + +/* + * Copyright (c) 2016 Brad Spencer <b...@anduin.eldar.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: gpioirq.c,v 1.1 2018/05/19 14:15:39 thorpej Exp $"); + +/* + * Example GPIO driver that uses interrupts. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/gpio.h> +#include <sys/module.h> + +#include <dev/gpio/gpiovar.h> + +#define GPIOIRQ_NPINS 1 + +struct gpioirq_softc { + device_t sc_dev; + void * sc_gpio; + struct gpio_pinmap sc_map; + int _map[GPIOIRQ_NPINS]; + char sc_intrstr[128]; + void * sc_ih; + kmutex_t sc_lock; + bool sc_verbose; + bool sc_functional; +}; + +#define GPIOIRQ_FLAGS_IRQMODE GPIO_INTR_MODE_MASK +#define GPIOIRQ_FLAGS_VERBOSE 0x1000 + +static int gpioirq_match(device_t, cfdata_t, void *); +static void gpioirq_attach(device_t, device_t, void *); +static int gpioirq_detach(device_t, int); +static int gpioirq_activate(device_t, enum devact); + +static int gpioirq_intr(void *); + +CFATTACH_DECL_NEW(gpioirq, sizeof(struct gpioirq_softc), + gpioirq_match, gpioirq_attach, + gpioirq_detach, gpioirq_activate); + +extern struct cfdriver gpioirq_cd; + +static int +gpioirq_match(device_t parent, cfdata_t cf, void *aux) +{ + struct gpio_attach_args *ga = aux; + int npins; + + if (strcmp(ga->ga_dvname, cf->cf_name)) + return (0); + + if (ga->ga_offset == -1) + return (0); + + npins = gpio_npins(ga->ga_mask); + if (npins > 1) + return (0); + + return (1); +} + +static void +gpioirq_attach(device_t parent, device_t self, void *aux) +{ + struct gpioirq_softc *sc = device_private(self); + struct gpio_attach_args *ga = aux; + int npins = gpio_npins(ga->ga_mask); + int irqmode, flags; + + sc->sc_dev = self; + + /* Map pins */ + sc->sc_gpio = ga->ga_gpio; + sc->sc_map.pm_map = sc->_map; + + /* We always map just 1 pin. */ + if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, + npins ? ga->ga_mask : 0x1, &sc->sc_map)) { + aprint_error(": can't map pins\n"); + return; + } + + aprint_normal("\n"); + + if (ga->ga_flags & GPIOIRQ_FLAGS_VERBOSE) + sc->sc_verbose = true; + + irqmode = ga->ga_flags & GPIOIRQ_FLAGS_IRQMODE; + + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_VM); + + if (!gpio_intr_str(sc->sc_gpio, &sc->sc_map, 0, irqmode, + sc->sc_intrstr, sizeof(sc->sc_intrstr))) { + aprint_error_dev(self, "failed to decode interrupt\n"); + return; + } + + if (!gpio_pin_irqmode_issupported(sc->sc_gpio, &sc->sc_map, 0, + irqmode)) { + aprint_error_dev(self, + "irqmode not supported: %s\n", sc->sc_intrstr); + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + return; + } + + flags = gpio_pin_get_conf(sc->sc_gpio, &sc->sc_map, 0); + flags = (flags & ~(GPIO_PIN_OUTPUT|GPIO_PIN_INOUT)) | + GPIO_PIN_INPUT; + if (!gpio_pin_set_conf(sc->sc_gpio, &sc->sc_map, 0, flags)) { + aprint_error_dev(sc->sc_dev, "pin not capable of input\n"); + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + return; + } + + sc->sc_ih = gpio_intr_establish(sc->sc_gpio, &sc->sc_map, 0, IPL_VM, + irqmode | GPIO_INTR_MPSAFE, + gpioirq_intr, sc); + if (sc->sc_ih == NULL) { + aprint_error_dev(self, + "unable to establish interrupt on %s\n", sc->sc_intrstr); + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + return; + } + aprint_normal_dev(self, "interrupting on %s\n", sc->sc_intrstr); + + sc->sc_functional = true; +} + +int +gpioirq_intr(void *arg) +{ + struct gpioirq_softc *sc = arg; + int val; + + mutex_enter(&sc->sc_lock); + + val = gpio_pin_read(sc->sc_gpio, &sc->sc_map, 0); + + if (sc->sc_verbose) + printf("%s: interrupt on %s --> %d\n", + device_xname(sc->sc_dev), sc->sc_intrstr, val); + + mutex_exit(&sc->sc_lock); + + return (1); +} + +int +gpioirq_detach(device_t self, int flags) +{ + struct gpioirq_softc *sc = device_private(self); + + /* Clear the handler and disable the interrupt. */ + gpio_intr_disestablish(sc->sc_gpio, sc->sc_ih); + + /* Release the pin. */ + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + + return (0); +} + +int +gpioirq_activate(device_t self, enum devact act) +{ + + switch (act) { + case DVACT_DEACTIVATE: + /* We don't really need to do anything. */ + return (0); + default: + return (EOPNOTSUPP); + } +} + +MODULE(MODULE_CLASS_DRIVER, gpioirq, "gpio"); + +#ifdef _MODULE +#include "ioconf.c" +#endif + +static int +gpioirq_modcmd(modcmd_t cmd, void *opaque) +{ + int error = 0; + + switch (cmd) { + case MODULE_CMD_INIT: +#ifdef _MODULE + error = config_init_component(cfdriver_ioconf_gpioirq, + cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq); + if (error) + aprint_error("%s: unable to init component\n", + gpioirq_cd.cd_name); +#endif + break; + case MODULE_CMD_FINI: +#ifdef _MODULE + config_fini_component(cfdriver_ioconf_gpioirq, + cfattach_ioconf_gpioirq, cfdata_ioconf_gpioirq); +#endif + break; + default: + error = ENOTTY; + } + + return (error); +} Index: src/sys/modules/gpioirq/Makefile diff -u /dev/null src/sys/modules/gpioirq/Makefile:1.1 --- /dev/null Sat May 19 14:15:40 2018 +++ src/sys/modules/gpioirq/Makefile Sat May 19 14:15:40 2018 @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.1 2018/05/19 14:15:40 thorpej Exp $ + +.include "../Makefile.inc" + +.PATH: ${S}/dev/gpio + +KMOD= gpioirq +IOCONF= gpioirq.ioconf +SRCS= gpioirq.c + +CPPFLAGS+= -I${S}/gpio + +.include <bsd.kmodule.mk> Index: src/sys/modules/gpioirq/gpioirq.ioconf diff -u /dev/null src/sys/modules/gpioirq/gpioirq.ioconf:1.1 --- /dev/null Sat May 19 14:15:40 2018 +++ src/sys/modules/gpioirq/gpioirq.ioconf Sat May 19 14:15:40 2018 @@ -0,0 +1,8 @@ +# $NetBSD: gpioirq.ioconf,v 1.1 2018/05/19 14:15:40 thorpej Exp $ + +ioconf gpioirq + +include "conf/files" + +pseudo-root gpio* +gpioirq* at gpio? offset ? mask ? flag ?