Module Name: src Committed By: jmcneill Date: Sun Dec 8 20:49:56 UTC 2024
Modified Files: src/sys/dev/i2c: files.i2c ihidev.c ihidev.h Log Message: ihidev: Add support for GPIO interrupts. To generate a diff of this commit: cvs rdiff -u -r1.127 -r1.128 src/sys/dev/i2c/files.i2c cvs rdiff -u -r1.30 -r1.31 src/sys/dev/i2c/ihidev.c cvs rdiff -u -r1.6 -r1.7 src/sys/dev/i2c/ihidev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/i2c/files.i2c diff -u src/sys/dev/i2c/files.i2c:1.127 src/sys/dev/i2c/files.i2c:1.128 --- src/sys/dev/i2c/files.i2c:1.127 Mon Nov 4 20:43:38 2024 +++ src/sys/dev/i2c/files.i2c Sun Dec 8 20:49:56 2024 @@ -1,4 +1,4 @@ -# $NetBSD: files.i2c,v 1.127 2024/11/04 20:43:38 brad Exp $ +# $NetBSD: files.i2c,v 1.128 2024/12/08 20:49:56 jmcneill Exp $ obsolete defflag opt_i2cbus.h I2C_SCAN define i2cbus { } @@ -324,7 +324,7 @@ file dev/i2c/asms.c asms define ihidbus {[ reportid = -1 ]} # HID root device for multiple report IDs -device ihidev: hid, ihidbus +device ihidev: hid, ihidbus, gpio attach ihidev at iic file dev/i2c/ihidev.c ihidev Index: src/sys/dev/i2c/ihidev.c diff -u src/sys/dev/i2c/ihidev.c:1.30 src/sys/dev/i2c/ihidev.c:1.31 --- src/sys/dev/i2c/ihidev.c:1.30 Mon Apr 29 21:25:34 2024 +++ src/sys/dev/i2c/ihidev.c Sun Dec 8 20:49:56 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: ihidev.c,v 1.30 2024/04/29 21:25:34 andvar Exp $ */ +/* $NetBSD: ihidev.c,v 1.31 2024/12/08 20:49:56 jmcneill Exp $ */ /* $OpenBSD ihidev.c,v 1.13 2017/04/08 02:57:23 deraadt Exp $ */ /*- @@ -53,8 +53,11 @@ * */ +#include "gpio.h" +#include "acpica.h" + #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ihidev.c,v 1.30 2024/04/29 21:25:34 andvar Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ihidev.c,v 1.31 2024/12/08 20:49:56 jmcneill Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -67,12 +70,13 @@ __KERNEL_RCSID(0, "$NetBSD: ihidev.c,v 1 #include <dev/hid/hid.h> -#if defined(__i386__) || defined(__amd64__) -# include "acpica.h" -#endif #if NACPICA > 0 #include <dev/acpi/acpivar.h> #include <dev/acpi/acpi_intr.h> +#include <dev/acpi/acpi_gpio.h> +#endif +#if NGPIO > 0 +#include <dev/gpio/gpiovar.h> #endif #include "locators.h" @@ -222,7 +226,8 @@ ihidev_attach(device_t parent, device_t locs[IHIDBUSCF_REPORTID] = IHIDEV_CLAIM_ALLREPORTID; dev = config_found(self, &iha, ihidev_print, CFARGS(.submatch = ihidev_submatch, - .locators = locs)); + .locators = locs, + .iattr = "ihidbus")); if (dev != NULL) { for (repid = 0; repid < sc->sc_nrepid; repid++) sc->sc_subdevs[repid] = device_private(dev); @@ -242,7 +247,8 @@ ihidev_attach(device_t parent, device_t locs[IHIDBUSCF_REPORTID] = repid; dev = config_found(self, &iha, ihidev_print, CFARGS(.submatch = ihidev_submatch, - .locators = locs)); + .locators = locs, + .iattr = "ihidbus")); sc->sc_subdevs[repid] = device_private(dev); } @@ -685,9 +691,13 @@ ihidev_intr_init(struct ihidev_softc *sc const struct acpi_irq * const irq = acpi_res_irq(&res, 0); if (irq == NULL) { - aprint_error_dev(sc->sc_dev, "no IRQ resource\n"); + aprint_debug_dev(sc->sc_dev, "no IRQ resource\n"); acpi_resource_cleanup(&res); +#if NGPIO > 0 + goto try_gpioint; +#else return false; +#endif } sc->sc_intr_type = @@ -704,6 +714,44 @@ ihidev_intr_init(struct ihidev_softc *sc aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", acpi_intr_string(sc->sc_ih, buf, sizeof(buf))); +#if NGPIO > 0 +try_gpioint: + if (sc->sc_ih == NULL) { + int pin, irqmode, error; + + rv = acpi_gpio_get_int(hdl, 0, &sc->sc_ih_gpio, &pin, &irqmode); + if (ACPI_FAILURE(rv)) { + aprint_error_dev(sc->sc_dev, + "can't find gpioint resource\n"); + return false; + } + device_printf(sc->sc_dev, "[GPIO] got controller %p\n", sc->sc_ih_gpio); + + sc->sc_ih_gpiomap.pm_map = sc->sc_ih_gpiopins; + error = gpio_pin_map(sc->sc_ih_gpio, pin, 1, + &sc->sc_ih_gpiomap); + if (error) { + aprint_error_dev(sc->sc_dev, "can't map pin %d\n", pin); + return false; + } + + sc->sc_ih = gpio_intr_establish(sc->sc_ih_gpio, + &sc->sc_ih_gpiomap, 0, IPL_VM, irqmode, ihidev_intr, sc); + if (sc->sc_ih == NULL) { + aprint_error_dev(sc->sc_dev, + "can't establish gpio interrupt\n"); + return false; + } + + sc->sc_intr_type = (irqmode & GPIO_INTR_LEVEL_MASK) ? + IST_LEVEL : IST_EDGE; + + gpio_intr_str(sc->sc_ih_gpio, &sc->sc_ih_gpiomap, 0, + irqmode, buf, sizeof(buf)); + aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", buf); + } +#endif + if (workqueue_create(&sc->sc_wq, device_xname(sc->sc_dev), ihidev_work, sc, PRI_NONE, IPL_TTY, WQ_MPSAFE)) { aprint_error_dev(sc->sc_dev, @@ -724,7 +772,13 @@ ihidev_intr_fini(struct ihidev_softc *sc { #if NACPICA > 0 if (sc->sc_ih != NULL) { - acpi_intr_disestablish(sc->sc_ih); + if (sc->sc_ih_gpio != NULL) { +#if NGPIO > 0 + gpio_intr_disestablish(sc->sc_ih_gpio, sc->sc_ih); +#endif + } else { + acpi_intr_disestablish(sc->sc_ih); + } } if (sc->sc_wq != NULL) { workqueue_destroy(sc->sc_wq); @@ -738,7 +792,13 @@ ihidev_intr_mask(struct ihidev_softc * c { if (sc->sc_intr_type == IST_LEVEL) { - acpi_intr_mask(sc->sc_ih); + if (sc->sc_ih_gpio != NULL) { +#if NGPIO > 0 + gpio_intr_mask(sc->sc_ih_gpio, sc->sc_ih); +#endif + } else { + acpi_intr_mask(sc->sc_ih); + } } } @@ -747,7 +807,13 @@ ihidev_intr_unmask(struct ihidev_softc * { if (sc->sc_intr_type == IST_LEVEL) { - acpi_intr_unmask(sc->sc_ih); + if (sc->sc_ih_gpio != NULL) { +#if NGPIO > 0 + gpio_intr_unmask(sc->sc_ih_gpio, sc->sc_ih); +#endif + } else { + acpi_intr_unmask(sc->sc_ih); + } } } Index: src/sys/dev/i2c/ihidev.h diff -u src/sys/dev/i2c/ihidev.h:1.6 src/sys/dev/i2c/ihidev.h:1.7 --- src/sys/dev/i2c/ihidev.h:1.6 Fri Jan 14 22:25:49 2022 +++ src/sys/dev/i2c/ihidev.h Sun Dec 8 20:49:56 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: ihidev.h,v 1.6 2022/01/14 22:25:49 riastradh Exp $ */ +/* $NetBSD: ihidev.h,v 1.7 2024/12/08 20:49:56 jmcneill Exp $ */ /* $OpenBSD ihidev.h,v 1.4 2016/01/31 18:24:35 jcs Exp $ */ /*- @@ -107,8 +107,10 @@ struct i2c_hid_desc { #include <sys/device.h> #include <sys/mutex.h> #include <sys/workqueue.h> +#include <sys/gpio.h> #include <dev/i2c/i2cvar.h> +#include <dev/gpio/gpiovar.h> struct ihidev_softc { device_t sc_dev; @@ -118,6 +120,9 @@ struct ihidev_softc { kmutex_t sc_lock; void * sc_ih; + void * sc_ih_gpio; + struct gpio_pinmap sc_ih_gpiomap; + int sc_ih_gpiopins[1]; struct workqueue *sc_wq; struct work sc_work; volatile unsigned sc_work_pending;