From 94e0b117e63c48e22b0c55d74f088335a1355c4e Mon Sep 17 00:00:00 2001 From: kettenis Date: Wed, 29 Nov 2017 22:51:01 +0000 Subject: [PATCH] Add support for GPIO-signaled events. ok mlarkin@ --- sys/dev/acpi/acpi.c | 84 +++++++++++++++++++++++++++++++++++++++++- sys/dev/acpi/acpivar.h | 4 +- sys/dev/acpi/chvgpio.c | 16 ++------ 3 files changed, 89 insertions(+), 15 deletions(-) diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 99ad34ec619..c037c5240c9 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.334 2017/11/16 18:12:27 jcs Exp $ */ +/* $OpenBSD: acpi.c,v 1.335 2017/11/29 22:51:01 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * Copyright (c) 2005 Jordan Hargrave @@ -834,6 +834,88 @@ acpi_pciroots_attach(struct device *dev, void *aux, cfprint_t pr) } } +/* GPIO support */ + +struct acpi_gpio_event { + struct aml_node *node; + uint16_t pin; +}; + +void +acpi_gpio_event_task(void *arg0, int arg1) +{ + struct aml_node *node = arg0; + uint16_t pin = arg1; + char name[5]; + + snprintf(name, sizeof(name), "_E%.2X", pin); + aml_evalname(acpi_softc, node, name, 0, NULL, NULL); +} + +int +acpi_gpio_event(void *arg) +{ + struct acpi_gpio_event *ev = arg; + + acpi_addtask(acpi_softc, acpi_gpio_event_task, ev->node, ev->pin); + return 1; +} + +int +acpi_gpio_parse_events(int crsidx, union acpi_resource *crs, void *arg) +{ + struct aml_node *devnode = arg; + struct aml_node *node; + uint16_t pin; + + switch (AML_CRSTYPE(crs)) { + case LR_GPIO: + node = aml_searchname(devnode, + (char *)&crs->pad[crs->lr_gpio.res_off]); + pin = *(uint16_t *)&crs->pad[crs->lr_gpio.pin_off]; + if (crs->lr_gpio.type == LR_GPIO_INT && + node && node->gpio && pin < 256) { + struct acpi_gpio *gpio = node->gpio; + struct acpi_gpio_event *ev; + + ev = malloc(sizeof(*ev), M_DEVBUF, M_WAITOK); + ev->node = devnode; + ev->pin = pin; + gpio->intr_establish(gpio->cookie, pin, + crs->lr_gpio.tflags, acpi_gpio_event, ev); + } + break; + default: + printf("%s: unknown resource type %d\n", __func__, + AML_CRSTYPE(crs)); + } + + return 0; +} + +void +acpi_register_gpio(struct acpi_softc *sc, struct aml_node *devnode) +{ + struct aml_value arg[2]; + struct aml_node *node; + struct aml_value res; + + /* Register GeneralPurposeIO address space. */ + memset(&arg, 0, sizeof(arg)); + arg[0].type = AML_OBJTYPE_INTEGER; + arg[0].v_integer = ACPI_OPREG_GPIO; + arg[1].type = AML_OBJTYPE_INTEGER; + arg[1].v_integer = 1; + node = aml_searchname(devnode, "_REG"); + if (node && aml_evalnode(sc, node, 2, arg, NULL)) + printf("%s: _REG failed\n", node->name); + + /* Register GPIO signaled ACPI events. */ + if (aml_evalname(sc, devnode, "_AEI", 0, NULL, &res)) + return; + aml_parse_resource(&res, acpi_gpio_parse_events, devnode); +} + void acpi_attach(struct device *parent, struct device *self, void *aux) { diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h index 558ec12cd40..e953c5cecdf 100644 --- a/sys/dev/acpi/acpivar.h +++ b/sys/dev/acpi/acpivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpivar.h,v 1.88 2017/08/17 05:16:27 stsp Exp $ */ +/* $OpenBSD: acpivar.h,v 1.89 2017/11/29 22:51:01 kettenis Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * @@ -332,6 +332,8 @@ void acpi_wakeup(void *); int acpi_gasio(struct acpi_softc *, int, int, uint64_t, int, int, void *); +void acpi_register_gpio(struct acpi_softc *, struct aml_node *); + int acpi_set_gpehandler(struct acpi_softc *, int, int (*)(struct acpi_softc *, int, void *), void *, int); void acpi_enable_gpe(struct acpi_softc *, u_int32_t); diff --git a/sys/dev/acpi/chvgpio.c b/sys/dev/acpi/chvgpio.c index a82e6c53fbb..4dddf4e76ee 100644 --- a/sys/dev/acpi/chvgpio.c +++ b/sys/dev/acpi/chvgpio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: chvgpio.c,v 1.7 2017/11/29 15:22:22 kettenis Exp $ */ +/* $OpenBSD: chvgpio.c,v 1.8 2017/11/29 22:51:01 kettenis Exp $ */ /* * Copyright (c) 2016 Mark Kettenis * @@ -169,8 +169,6 @@ chvgpio_attach(struct device *parent, struct device *self, void *aux) struct acpi_attach_args *aaa = aux; struct chvgpio_softc *sc = (struct chvgpio_softc *)self; struct aml_value res; - struct aml_value arg[2]; - struct aml_node *node; int64_t uid; int i; @@ -251,19 +249,11 @@ chvgpio_attach(struct device *parent, struct device *self, void *aux) printf(", %d pins\n", sc->sc_npins); - /* Register GeneralPurposeIO address space. */ - memset(&arg, 0, sizeof(arg)); - arg[0].type = AML_OBJTYPE_INTEGER; - arg[0].v_integer = ACPI_OPREG_GPIO; - arg[1].type = AML_OBJTYPE_INTEGER; - arg[1].v_integer = 1; - node = aml_searchname(sc->sc_node, "_REG"); - if (node && aml_evalnode(sc->sc_acpi, node, 2, arg, NULL)) - printf("%s: _REG failed\n", sc->sc_dev.dv_xname); - /* Register OEM defined address space. */ aml_register_regionspace(sc->sc_node, CHVGPIO_REGIONSPACE_BASE + uid, sc, chvgpio_opreg_handler); + + acpi_register_gpio(sc->sc_acpi, sc->sc_node); return; unmap: -- 2.20.1