On Tue, Mar 29, 2016 at 11:13:51PM +0200, Mark Kettenis wrote:
> Hi Jonathan, Joshua & other interested folks,
> 
> The diff below adds support for gpio interrupts for the Bay Trail GPIO
> controller.  The acpi gpio interface gets extended with an
> intr_establish() method that establishes an interrupt on a specific
> pin.  The pin is configured according to the flags that are passed.
> The interrupt is established at IPL_BIO.  This is similar to what the
> USB subsystem does.  The interrupt handler should call splxxx() as
> appropriate.  This means that keyboard interrupts will be blocked by
> pretty much all other interrupt handlers.  We can't easily avoid this.
> 
> The diff hooks this support up to the sdhc(4) driver.  Card insertions
> and de-insertions are now detected in the SD card slot of my Asus
> x205ta.
> 
> It should be fairly easy too hook up the keyboard interrupt on the
> Lenovo 100s.
> 
> ok?

It would be nice if the intr_establish at least returned an int to avoid
having to add simple functions to get around to different prototype.
Perhaps an empty intr_disestablish and adding the devname argument
like acpi_intr_establish?  Is it possible multiple callbacks may
need to be called for a single pin?

It ends up being a bit convoluted on the 100s but works with the
following.  Can now click and drag windows in x11...

dwiic0 at acpi0: I2C1 addr 0x90906000/0x1000 irq 32
iic0 at dwiic0
dwiic1 at acpi0: I2C2 addr 0x9090c000/0x1000 irq 33
iic1 at dwiic1
"10EC5640" at acpi0 not configured
dwiic2 at acpi0: I2C3 addr 0x9090e000/0x1000 irq 34
iic2 at dwiic2
 GPO2 pin 22
 tflags 0x12
 ppi 0x1
 drs 0x0
 dbt 0x0
ihidev0 at iic2 addr 0x5: int 22, vendor 0x6243 product 0x1, ENEE3730
ihidev0: 6 report ids
ikbd0 at ihidev0 reportid 1: 8 variable keys, 6 key codes
wskbd0 at ikbd0 mux 1
hid at ihidev0 reportid 2 not configured
hid at ihidev0 reportid 3 not configured
ims0 at ihidev0 reportid 4: 3 buttons, Z dir
wsmouse0 at ims0 mux 0
hid at ihidev0 reportid 5 not configured
hid at ihidev0 reportid 6 not configured
"ENEE3730" at acpi0 not configured
dwiic3 at acpi0: I2C4 addr 0x90910000/0x1000 irq 35
iic3 at dwiic3
dwiic4 at acpi0: I2C5 addr 0x90912000/0x1000 irq 36
iic4 at dwiic4

Index: acpi/dwiic.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dwiic.c,v
retrieving revision 1.12
diff -u -p -r1.12 dwiic.c
--- acpi/dwiic.c        29 Mar 2016 22:35:09 -0000      1.12
+++ acpi/dwiic.c        30 Mar 2016 00:56:40 -0000
@@ -123,6 +123,10 @@ struct dwiic_crs {
        uint32_t addr_bas;
        uint32_t addr_len;
        uint16_t i2c_addr;
+       struct aml_node *devnode;
+       struct aml_node *gpio_int_node;
+       uint16_t gpio_int_pin;
+       uint16_t gpio_int_flags;
 };
 
 struct dwiic_softc {
@@ -238,6 +242,7 @@ dwiic_attach(struct device *parent, stru
                return;
        }
        memset(&crs, 0, sizeof(crs));
+       crs.devnode = sc->sc_devnode;
        aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
        aml_freevalue(&res);
 
@@ -374,6 +379,8 @@ int
 dwiic_acpi_parse_crs(union acpi_resource *crs, void *arg)
 {
        struct dwiic_crs *sc_crs = arg;
+       struct aml_node *node;
+       uint16_t pin;
 
        switch (AML_CRSTYPE(crs)) {
        case SR_IRQ:
@@ -386,6 +393,22 @@ dwiic_acpi_parse_crs(union acpi_resource
                sc_crs->irq_flags = crs->lr_extirq.flags;
                break;
 
+       case LR_GPIO:
+               node = aml_searchname(sc_crs->devnode,
+                   (char *)&crs->pad[crs->lr_gpio.res_off]);
+               pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off];
+               printf(" %s pin %d\n", node->name, pin);
+               if (crs->lr_gpio.type == LR_GPIO_INT) {
+                       sc_crs->gpio_int_node = node;
+                       sc_crs->gpio_int_pin = pin;
+                       sc_crs->gpio_int_flags = crs->lr_gpio.tflags;
+               }
+               printf(" tflags 0x%x\n", crs->lr_gpio.tflags);
+               printf(" ppi 0x%x\n", crs->lr_gpio._ppi);
+               printf(" drs 0x%x\n", crs->lr_gpio._drs);
+               printf(" dbt 0x%x\n", crs->lr_gpio._dbt);
+               break;
+
        case LR_MEM32:
                sc_crs->addr_min = letoh32(crs->lr_m32._min);
                sc_crs->addr_len = letoh32(crs->lr_m32._len);
@@ -553,18 +576,27 @@ dwiic_acpi_foundhid(struct aml_node *nod
                return (0);
        }
        memset(&crs, 0, sizeof(crs));
+       crs.devnode = sc->sc_devnode;
        aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
        aml_freevalue(&res);
 
-       if (crs.irq_int <= 0) {
+       if (crs.gpio_int_node && crs.gpio_int_node->gpio) {
+               struct acpi_gpio *gpio = crs.gpio_int_node->gpio;
+               ia.ia_int = crs.gpio_int_pin;
+               ia.ia_int_flags = crs.gpio_int_flags;
+               ia.acpi_gpio = gpio;
+       } else {
+               ia.ia_int = crs.irq_int;
+               ia.ia_int_flags = crs.irq_flags;
+               ia.acpi_gpio = NULL;
+       }
+       ia.ia_addr = crs.i2c_addr;
+
+       if (ia.ia_int <= 0) {
                printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname,
                    aml_nodename(node->parent));
                return 0;
        }
-
-       ia.ia_int = crs.irq_int;
-       ia.ia_int_flags = crs.irq_flags;
-       ia.ia_addr = crs.i2c_addr;
 
        if (config_found(sc->sc_iic, &ia, dwiic_i2c_print))
                return 0;
Index: i2c/i2cvar.h
===================================================================
RCS file: /cvs/src/sys/dev/i2c/i2cvar.h,v
retrieving revision 1.13
diff -u -p -r1.13 i2cvar.h
--- i2c/i2cvar.h        12 Jan 2016 17:30:23 -0000      1.13
+++ i2c/i2cvar.h        30 Mar 2016 00:31:45 -0000
@@ -110,6 +110,7 @@ struct i2c_attach_args {
        int             ia_int_flags;   /* IRQ flags */
        char            *ia_name;       /* chip name */
        void            *ia_cookie;     /* pass extra info from bus to dev */
+       void            *acpi_gpio;
 };
 
 /*
Index: i2c/ihidev.c
===================================================================
RCS file: /cvs/src/sys/dev/i2c/ihidev.c,v
retrieving revision 1.9
diff -u -p -r1.9 ihidev.c
--- i2c/ihidev.c        29 Jan 2016 17:11:58 -0000      1.9
+++ i2c/ihidev.c        30 Mar 2016 00:59:47 -0000
@@ -30,8 +30,11 @@
 
 #include <dev/hid/hid.h>
 
-/* XXX */
+#if defined(__i386__) || defined(__amd64__)
+#include "acpi.h"
 #include <dev/acpi/acpivar.h>
+#include <dev/acpi/amltypes.h>
+#endif
 
 /* #define IHIDEV_DEBUG */
 
@@ -66,6 +69,7 @@ int   ihidev_detach(struct device *, int);
 
 int    ihidev_hid_command(struct ihidev_softc *, int, void *);
 int    ihidev_intr(void *);
+void   ihidev_intr_gpio(void *);
 int    ihidev_reset(struct ihidev_softc *);
 int    ihidev_hid_desc_parse(struct ihidev_softc *);
 
@@ -156,6 +160,13 @@ ihidev_attach(struct device *parent, str
        sc->sc_ibuf = malloc(sc->sc_isize, M_DEVBUF, M_NOWAIT | M_ZERO);
 
        /* register interrupt with system */
+#if NACPI > 0
+       if (ia->ia_int > 0 && ia->acpi_gpio != NULL) {
+               struct acpi_gpio *gpio = ia->acpi_gpio;
+               gpio->intr_establish(gpio->cookie, ia->ia_int,
+                   ia->ia_int_flags, ihidev_intr_gpio, sc);
+       } else
+#endif
        if (ia->ia_int > 0) {
                /* XXX: don't assume this uses acpi_intr_establish */
                sc->sc_ih = acpi_intr_establish(ia->ia_int, ia->ia_int_flags,
@@ -618,6 +629,12 @@ ihidev_intr(void *arg)
        scd->sc_intr(scd, p, psize);
 
        return (1);
+}
+
+void
+ihidev_intr_gpio(void *arg)
+{
+       ihidev_intr(arg);
 }
 
 int

Reply via email to