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;