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;

Reply via email to