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