Diff below adds support for ACPI GPIO-signaled events to the
chvgpio(4) driver. This makes the laptop I have here realize the lid
is closed or opened.
ok?
Index: dev/acpi/acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
retrieving revision 1.334
diff -u -p -r1.334 acpi.c
--- dev/acpi/acpi.c 16 Nov 2017 18:12:27 -0000 1.334
+++ dev/acpi/acpi.c 29 Nov 2017 22:16:52 -0000
@@ -834,6 +834,87 @@ acpi_pciroots_attach(struct device *dev,
}
}
+/* GPIO support */
+
+struct acpi_gpio_event {
+ struct aml_node *node;
+ int pin;
+};
+
+void
+acpi_gpio_event_task(void *arg0, int arg1)
+{
+ struct aml_node *node = arg0;
+ int 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) {
+ 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: dev/acpi/acpivar.h
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v
retrieving revision 1.88
diff -u -p -r1.88 acpivar.h
--- dev/acpi/acpivar.h 17 Aug 2017 05:16:27 -0000 1.88
+++ dev/acpi/acpivar.h 29 Nov 2017 22:15:32 -0000
@@ -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: dev/acpi/chvgpio.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/chvgpio.c,v
retrieving revision 1.7
diff -u -p -r1.7 chvgpio.c
--- dev/acpi/chvgpio.c 29 Nov 2017 15:22:22 -0000 1.7
+++ dev/acpi/chvgpio.c 29 Nov 2017 22:15:13 -0000
@@ -169,8 +169,6 @@ chvgpio_attach(struct device *parent, st
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, st
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: