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)