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?


Index: acpi/amltypes.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/amltypes.h,v
retrieving revision 1.41
diff -u -p -r1.41 amltypes.h
--- acpi/amltypes.h     28 Mar 2016 17:27:57 -0000      1.41
+++ acpi/amltypes.h     29 Mar 2016 21:04:45 -0000
@@ -367,6 +367,7 @@ struct acpi_pci {
 struct acpi_gpio {
        void    *cookie;
        int     (*read_pin)(void *, int);
+       void    (*intr_establish)(void *, int, int, void (*)(void *), void *);
 };
 
 struct aml_node {
Index: acpi/bytgpio.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/bytgpio.c,v
retrieving revision 1.3
diff -u -p -r1.3 bytgpio.c
--- acpi/bytgpio.c      29 Mar 2016 18:04:09 -0000      1.3
+++ acpi/bytgpio.c      29 Mar 2016 21:04:45 -0000
@@ -25,8 +25,22 @@
 #include <dev/acpi/amltypes.h>
 #include <dev/acpi/dsdt.h>
 
+#define BYTGPIO_CONF_GD_LEVEL  0x01000000
+#define BYTGPIO_CONF_GD_TPE    0x02000000
+#define BYTGPIO_CONF_GD_TNE    0x04000000
+#define BYTGPIO_CONF_GD_MASK   0x0f000000
+
 #define BYTGPIO_PAD_VAL                0x00000001
 
+#define BYTGPIO_IRQ_TS_0       0x800
+#define BYTGPIO_IRQ_TS_1       0x804
+#define BYTGPIO_IRQ_TS_2       0x808
+
+struct bytgpio_intrhand {
+       void (*ih_func)(void *);
+       void *ih_arg;
+};
+
 struct bytgpio_softc {
        struct device sc_dev;
        struct acpi_softc *sc_acpi;
@@ -43,6 +57,7 @@ struct bytgpio_softc {
 
        const int *sc_pins;
        int sc_npins;
+       struct bytgpio_intrhand *sc_pin_ih;
 
        struct acpi_gpio sc_gpio;
 };
@@ -90,6 +105,7 @@ const int byt_sus_pins[] = {
 
 int    bytgpio_parse_resources(union acpi_resource *, void *);
 int    bytgpio_read_pin(void *, int);
+void   bytgpio_intr_establish(void *, int, int, void (*)(), void *);
 int    bytgpio_intr(void *);
 
 int
@@ -149,29 +165,39 @@ bytgpio_attach(struct device *parent, st
                return;
        }
 
+       sc->sc_pin_ih = mallocarray(sc->sc_npins, sizeof(*sc->sc_pin_ih),
+           M_DEVBUF, M_NOWAIT | M_ZERO);
+       if (sc->sc_pin_ih == NULL) {
+               printf("\n");
+               return;
+       }
+
        printf(" irq %d", sc->sc_irq);
 
        sc->sc_memt = aaa->aaa_memt;
        if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0,
            &sc->sc_memh)) {
                printf(", can't map registers\n");
-               return;
+               goto fail;
        }
 
-#if 0
        sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO,
            bytgpio_intr, sc, sc->sc_dev.dv_xname);
        if (sc->sc_ih == NULL) {
                printf(", can't establish interrupt\n");
-               return;
+               goto fail;
        }
-#endif
 
        sc->sc_gpio.cookie = sc;
        sc->sc_gpio.read_pin = bytgpio_read_pin;
+       sc->sc_gpio.intr_establish = bytgpio_intr_establish;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        printf(", %d pins\n", sc->sc_npins);
+       return;
+
+fail:
+       free(sc->sc_pin_ih, M_DEVBUF, sc->sc_npins * sizeof(*sc->sc_pin_ih));
 }
 
 int
@@ -207,25 +233,52 @@ bytgpio_read_pin(void *cookie, int pin)
        return (reg & BYTGPIO_PAD_VAL);
 }
 
-#if 0
+void
+bytgpio_intr_establish(void *cookie, int pin, int flags,
+    void (*func)(void *), void *arg)
+{
+       struct bytgpio_softc *sc = cookie;
+       uint32_t reg;
+
+       KASSERT(pin >= 0 && pin < sc->sc_npins);
+
+       sc->sc_pin_ih[pin].ih_func = func;
+       sc->sc_pin_ih[pin].ih_arg = arg;
+
+       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16);
+       reg &= ~BYTGPIO_CONF_GD_MASK;
+       if ((flags & LR_GPIO_MODE) == 0)
+               reg |= BYTGPIO_CONF_GD_LEVEL;
+       if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTLO)
+               reg |= BYTGPIO_CONF_GD_TNE;
+       if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTHI)
+               reg |= BYTGPIO_CONF_GD_TPE;
+       if ((flags & LR_GPIO_POLARITY) == LR_GPIO_ACTBOTH)
+               reg |= BYTGPIO_CONF_GD_TNE | BYTGPIO_CONF_GD_TPE;
+       bus_space_write_4(sc->sc_memt, sc->sc_memh, sc->sc_pins[pin] * 16, reg);
+}
 
 int
 bytgpio_intr(void *arg)
 {
        struct bytgpio_softc *sc = arg;
        uint32_t reg;
+       int rc = 0;
        int pin;
 
        for (pin = 0; pin < sc->sc_npins; pin++) {
-               if (pin % 32 == 0)
-                       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh, 0x800 
+ (pin / 8));
+               if (pin % 32 == 0) {
+                       reg = bus_space_read_4(sc->sc_memt, sc->sc_memh,
+                           BYTGPIO_IRQ_TS_0 + (pin / 8));
+                       bus_space_write_4(sc->sc_memt, sc->sc_memh,
+                           BYTGPIO_IRQ_TS_0 + (pin / 8), reg);
+               }
                if (reg & (1 << (pin % 32))) {
-                       
+                       if (sc->sc_pin_ih[pin].ih_func)
+                               
sc->sc_pin_ih[pin].ih_func(sc->sc_pin_ih[pin].ih_arg);
+                       rc = 1;
                }
        }
 
-       printf("%s\n", __func__);
-       return 1;
+       return rc;
 }
-
-#endif
Index: acpi/dsdt.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dsdt.h,v
retrieving revision 1.69
diff -u -p -r1.69 dsdt.h
--- acpi/dsdt.h 28 Mar 2016 17:22:41 -0000      1.69
+++ acpi/dsdt.h 29 Mar 2016 21:04:45 -0000
@@ -236,6 +236,12 @@ union acpi_resource {
 #define LR_GPIO_IO     0x01
                uint16_t        flags;
                uint16_t        tflags;
+#define LR_GPIO_SHR            (3L << 3)
+#define LR_GPIO_POLARITY       (3L << 1)
+#define  LR_GPIO_ACTHI         (0L << 1)
+#define  LR_GPIO_ACTLO         (1L << 1)
+#define  LR_GPIO_ACTBOTH       (2L << 1)
+#define LR_GPIO_MODE           (1L << 0)
                uint8_t         _ppi;
                uint16_t        _drs;
                uint16_t        _dbt;
Index: acpi/sdhc_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/sdhc_acpi.c,v
retrieving revision 1.4
diff -u -p -r1.4 sdhc_acpi.c
--- acpi/sdhc_acpi.c    29 Mar 2016 18:04:09 -0000      1.4
+++ acpi/sdhc_acpi.c    29 Mar 2016 21:04:45 -0000
@@ -46,6 +46,7 @@ struct sdhc_acpi_softc {
        struct aml_node *sc_gpio_int_node;
        struct aml_node *sc_gpio_io_node;
        uint16_t sc_gpio_int_pin;
+       uint16_t sc_gpio_int_flags;
        uint16_t sc_gpio_io_pin;
 
        struct sdhc_host *sc_host;
@@ -68,6 +69,7 @@ const char *sdhc_hids[] = {
 
 int    sdhc_acpi_parse_resources(union acpi_resource *, void *);
 int    sdhc_acpi_card_detect(struct sdhc_softc *);
+void   sdhc_acpi_card_detect_intr(void *);
 
 int
 sdhc_acpi_match(struct device *parent, void *match, void *aux)
@@ -120,6 +122,13 @@ sdhc_acpi_attach(struct device *parent, 
        if (sc->sc_gpio_io_node && sc->sc_gpio_io_node->gpio)
                sc->sc.sc_card_detect = sdhc_acpi_card_detect;
 
+       if (sc->sc_gpio_int_node && sc->sc_gpio_int_node->gpio) {
+               struct acpi_gpio *gpio = sc->sc_gpio_int_node->gpio;
+
+               gpio->intr_establish(gpio->cookie, sc->sc_gpio_int_pin,
+                   sc->sc_gpio_int_flags, sdhc_acpi_card_detect_intr, sc);
+       }
+
        printf("\n");
 
        sc->sc.sc_host = &sc->sc_host;
@@ -150,6 +159,7 @@ sdhc_acpi_parse_resources(union acpi_res
                if (crs->lr_gpio.type == LR_GPIO_INT) {
                        sc->sc_gpio_int_node = node;
                        sc->sc_gpio_int_pin = pin;
+                       sc->sc_gpio_int_flags = crs->lr_gpio.tflags;
                } else if (crs->lr_gpio.type == LR_GPIO_IO) {
                        sc->sc_gpio_io_node = node;
                        sc->sc_gpio_io_pin = pin;
@@ -176,4 +186,12 @@ sdhc_acpi_card_detect(struct sdhc_softc 
 
        /* Card detect GPIO signal is active-low. */
        return !gpio->read_pin(gpio->cookie, pin);
+}
+
+void
+sdhc_acpi_card_detect_intr(void *arg)
+{
+       struct sdhc_acpi_softc *sc = arg;
+
+       sdhc_needs_discover(&sc->sc);
 }
Index: sdmmc/sdhc.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhc.c,v
retrieving revision 1.42
diff -u -p -r1.42 sdhc.c
--- sdmmc/sdhc.c        27 Mar 2016 18:49:41 -0000      1.42
+++ sdmmc/sdhc.c        29 Mar 2016 21:04:45 -0000
@@ -976,6 +976,15 @@ sdhc_intr(void *arg)
        return done;
 }
 
+void
+sdhc_needs_discover(struct sdhc_softc *sc)
+{
+       int host;
+
+       for (host = 0; host < sc->sc_nhosts; host++)
+               sdmmc_needs_discover(sc->sc_host[host]->sdmmc);
+}
+
 #ifdef SDHC_DEBUG
 void
 sdhc_dump_regs(struct sdhc_host *hp)
Index: sdmmc/sdhcvar.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdhcvar.h,v
retrieving revision 1.7
diff -u -p -r1.7 sdhcvar.h
--- sdmmc/sdhcvar.h     27 Mar 2016 18:49:41 -0000      1.7
+++ sdmmc/sdhcvar.h     29 Mar 2016 21:04:45 -0000
@@ -39,6 +39,8 @@ int   sdhc_activate(struct device *, int);
 void   sdhc_shutdown(void *);
 int    sdhc_intr(void *);
 
+void   sdhc_needs_discover(struct sdhc_softc *);
+
 /* flag values */
 #define SDHC_F_NOPWR0          (1 << 0)
 

Reply via email to