Add support for level-triggered GPIO events.
authorkettenis <kettenis@openbsd.org>
Mon, 12 Sep 2022 17:42:31 +0000 (17:42 +0000)
committerkettenis <kettenis@openbsd.org>
Mon, 12 Sep 2022 17:42:31 +0000 (17:42 +0000)
ok mlarkin@

sys/dev/acpi/acpi.c
sys/dev/acpi/amltypes.h
sys/dev/acpi/qcgpio.c

index ebb5249..bef27d8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.416 2022/09/10 13:18:31 kettenis Exp $ */
+/* $OpenBSD: acpi.c,v 1.417 2022/09/12 17:42:31 kettenis Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -857,35 +857,59 @@ acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr)
 
 struct acpi_gpio_event {
        struct aml_node *node;
+       uint16_t tflags;
        uint16_t pin;
 };
 
 void
 acpi_gpio_event_task(void *arg0, int arg1)
 {
-       struct aml_node *node = arg0;
+       struct acpi_softc *sc = acpi_softc;
+       struct acpi_gpio_event *ev = arg0;
+       struct acpi_gpio *gpio = ev->node->gpio;
        struct aml_value evt;
        uint16_t pin = arg1;
        char name[5];
 
        if (pin < 256) {
-               snprintf(name, sizeof(name), "_E%.2X", pin);
-               if (aml_evalname(acpi_softc, node, name, 0, NULL, NULL) == 0)
-                       return;
+               if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL) {
+                       snprintf(name, sizeof(name), "_L%.2X", pin);
+                       if (aml_evalname(sc, ev->node, name, 0, NULL, NULL)) {
+                               if (gpio->intr_enable)
+                                       gpio->intr_enable(gpio->cookie, pin);
+                               return;
+                       }
+               } else {
+                       snprintf(name, sizeof(name), "_E%.2X", pin);
+                       if (aml_evalname(sc, ev->node, name, 0, NULL, NULL)) {
+                               if (gpio->intr_enable)
+                                       gpio->intr_enable(gpio->cookie, pin);
+                               return;
+                       }
+               }
        }
 
        memset(&evt, 0, sizeof(evt));
        evt.v_integer = pin;
        evt.type = AML_OBJTYPE_INTEGER;
-       aml_evalname(acpi_softc, node, "_EVT", 1, &evt, NULL);
+       aml_evalname(sc, ev->node, "_EVT", 1, &evt, NULL);
+       if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL) {
+               if (gpio->intr_enable)
+                       gpio->intr_enable(gpio->cookie, pin);
+       }
 }
 
 int
 acpi_gpio_event(void *arg)
 {
        struct acpi_gpio_event *ev = arg;
+       struct acpi_gpio *gpio = ev->node->gpio;
 
-       acpi_addtask(acpi_softc, acpi_gpio_event_task, ev->node, ev->pin);
+       if ((ev->tflags & LR_GPIO_MODE) == LR_GPIO_LEVEL) {
+               if(gpio->intr_disable)
+                       gpio->intr_disable(gpio->cookie, ev->pin);
+       }
+       acpi_addtask(acpi_softc, acpi_gpio_event_task, ev, ev->pin);
        acpi_wakeup(acpi_softc);
        return 1;
 }
@@ -909,6 +933,7 @@ acpi_gpio_parse_events(int crsidx, union acpi_resource *crs, void *arg)
 
                        ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK);
                        ev->node = devnode;
+                       ev->tflags = crs->lr_gpio.tflags;
                        ev->pin = pin;
                        gpio->intr_establish(gpio->cookie, pin,
                            crs->lr_gpio.tflags, acpi_gpio_event, ev);
index 5d6ed43..974a252 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: amltypes.h,v 1.48 2019/01/10 18:50:32 kettenis Exp $ */
+/* $OpenBSD: amltypes.h,v 1.49 2022/09/12 17:42:31 kettenis Exp $ */
 /*
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
  *
@@ -369,6 +369,8 @@ struct acpi_gpio {
        int     (*read_pin)(void *, int);
        void    (*write_pin)(void *, int, int);
        void    (*intr_establish)(void *, int, int, int (*)(void *), void *);
+       void    (*intr_enable)(void *, int);
+       void    (*intr_disable)(void *, int);
 };
 
 struct i2c_controller;
index 36cdea8..0d5ff38 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: qcgpio.c,v 1.4 2022/09/10 14:32:53 kettenis Exp $     */
+/*     $OpenBSD: qcgpio.c,v 1.5 2022/09/12 17:42:31 kettenis Exp $     */
 /*
  * Copyright (c) 2022 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -102,6 +102,8 @@ int qcgpio_sc8280xp_pin_map(int, bus_size_t *);
 int    qcgpio_read_pin(void *, int);
 void   qcgpio_write_pin(void *, int, int);
 void   qcgpio_intr_establish(void *, int, int, int (*)(void *), void *);
+void   qcgpio_intr_enable(void *, int);
+void   qcgpio_intr_disable(void *, int);
 int    qcgpio_pin_intr(struct qcgpio_softc *, int);
 int    qcgpio_intr(void *);
 
@@ -161,6 +163,8 @@ qcgpio_attach(struct device *parent, struct device *self, void *aux)
        sc->sc_gpio.read_pin = qcgpio_read_pin;
        sc->sc_gpio.write_pin = qcgpio_write_pin;
        sc->sc_gpio.intr_establish = qcgpio_intr_establish;
+       sc->sc_gpio.intr_enable = qcgpio_intr_enable;
+       sc->sc_gpio.intr_disable = qcgpio_intr_disable;
        sc->sc_node->gpio = &sc->sc_gpio;
 
        printf("\n");
@@ -179,6 +183,9 @@ int
 qcgpio_sc7180_pin_map(int pin, bus_size_t *off)
 {
        switch (pin) {
+       case 30:
+               *off = QCGPIO_SC7180_SOUTH;
+               return 30;
        case 33:
        case 0x180:
                *off = QCGPIO_SC7180_NORTH;
@@ -293,6 +300,34 @@ qcgpio_intr_establish(void *cookie, int pin, int flags,
        HWRITE4(sc, off + TLMM_GPIO_INTR_CFG(pin), reg);
 }
 
+void
+qcgpio_intr_enable(void *cookie, int pin)
+{
+       struct qcgpio_softc *sc = cookie;
+       bus_size_t off = 0;
+
+       pin = sc->sc_pin_map(pin, &off);
+       if (pin < 0 || pin >= sc->sc_npins)
+               return;
+
+       HSET4(sc, off + TLMM_GPIO_INTR_CFG(pin),
+           TLMM_GPIO_INTR_CFG_INTR_ENABLE);
+}
+
+void
+qcgpio_intr_disable(void *cookie, int pin)
+{
+       struct qcgpio_softc *sc = cookie;
+       bus_size_t off = 0;
+
+       pin = sc->sc_pin_map(pin, &off);
+       if (pin < 0 || pin >= sc->sc_npins)
+               return;
+
+       HCLR4(sc, off + TLMM_GPIO_INTR_CFG(pin),
+           TLMM_GPIO_INTR_CFG_INTR_ENABLE);
+}
+
 int
 qcgpio_intr(void *arg)
 {