Add support for GPIO-signaled events.
authorkettenis <kettenis@openbsd.org>
Wed, 29 Nov 2017 22:51:01 +0000 (22:51 +0000)
committerkettenis <kettenis@openbsd.org>
Wed, 29 Nov 2017 22:51:01 +0000 (22:51 +0000)
ok mlarkin@

sys/dev/acpi/acpi.c
sys/dev/acpi/acpivar.h
sys/dev/acpi/chvgpio.c

index 99ad34e..c037c52 100644 (file)
@@ -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 <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -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)
 {
index 558ec12..e953c5c 100644 (file)
@@ -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 <tholo@sigmasoft.com>
  *
@@ -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);
index a82e6c5..4dddf4e 100644 (file)
@@ -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: