From 15328e98b456f91db94add864bb3b4f8b389eefd Mon Sep 17 00:00:00 2001 From: kettenis Date: Mon, 12 Sep 2022 17:42:31 +0000 Subject: [PATCH] Add support for level-triggered GPIO events. ok mlarkin@ --- sys/dev/acpi/acpi.c | 39 ++++++++++++++++++++++++++++++++------- sys/dev/acpi/amltypes.h | 4 +++- sys/dev/acpi/qcgpio.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 9 deletions(-) diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index ebb5249e822..bef27d893c9 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -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 * Copyright (c) 2005 Jordan Hargrave @@ -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); diff --git a/sys/dev/acpi/amltypes.h b/sys/dev/acpi/amltypes.h index 5d6ed43a52b..974a252f7c9 100644 --- a/sys/dev/acpi/amltypes.h +++ b/sys/dev/acpi/amltypes.h @@ -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 * @@ -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; diff --git a/sys/dev/acpi/qcgpio.c b/sys/dev/acpi/qcgpio.c index 36cdea85627..0d5ff38a11a 100644 --- a/sys/dev/acpi/qcgpio.c +++ b/sys/dev/acpi/qcgpio.c @@ -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 * @@ -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) { -- 2.20.1