summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjsg <jsg@openbsd.org>2016-04-02 00:56:39 +0000
committerjsg <jsg@openbsd.org>2016-04-02 00:56:39 +0000
commit90a2c5412ab0b8af7614deebb11c9ddc6463a2f8 (patch)
tree5903de013c3fca51daa5ebec4c85a2d5304c9288 /sys
parentMake the gpio intr_establish callback return an int so the same function (diff)
downloadwireguard-openbsd-90a2c5412ab0b8af7614deebb11c9ddc6463a2f8.tar.xz
wireguard-openbsd-90a2c5412ab0b8af7614deebb11c9ddc6463a2f8.zip
Add support for I2C HID devices with GPIO signalled interrupts.
Required for the keyboard and touchpad on the ideapad 100s. ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpi/dwiic.c39
-rw-r--r--sys/dev/i2c/i2cvar.h3
-rw-r--r--sys/dev/i2c/ihidev.c15
3 files changed, 47 insertions, 10 deletions
diff --git a/sys/dev/acpi/dwiic.c b/sys/dev/acpi/dwiic.c
index 54eb98d805d..1ff01f8ef8f 100644
--- a/sys/dev/acpi/dwiic.c
+++ b/sys/dev/acpi/dwiic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwiic.c,v 1.12 2016/03/29 22:35:09 kettenis Exp $ */
+/* $OpenBSD: dwiic.c,v 1.13 2016/04/02 00:56:39 jsg Exp $ */
/*
* Synopsys DesignWare I2C controller
*
@@ -123,6 +123,10 @@ struct dwiic_crs {
uint32_t addr_bas;
uint32_t addr_len;
uint16_t i2c_addr;
+ struct aml_node *devnode;
+ struct aml_node *gpio_int_node;
+ uint16_t gpio_int_pin;
+ uint16_t gpio_int_flags;
};
struct dwiic_softc {
@@ -238,6 +242,7 @@ dwiic_attach(struct device *parent, struct device *self, void *aux)
return;
}
memset(&crs, 0, sizeof(crs));
+ crs.devnode = sc->sc_devnode;
aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
aml_freevalue(&res);
@@ -374,6 +379,8 @@ int
dwiic_acpi_parse_crs(union acpi_resource *crs, void *arg)
{
struct dwiic_crs *sc_crs = arg;
+ struct aml_node *node;
+ uint16_t pin;
switch (AML_CRSTYPE(crs)) {
case SR_IRQ:
@@ -386,6 +393,17 @@ dwiic_acpi_parse_crs(union acpi_resource *crs, void *arg)
sc_crs->irq_flags = crs->lr_extirq.flags;
break;
+ case LR_GPIO:
+ node = aml_searchname(sc_crs->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) {
+ sc_crs->gpio_int_node = node;
+ sc_crs->gpio_int_pin = pin;
+ sc_crs->gpio_int_flags = crs->lr_gpio.tflags;
+ }
+ break;
+
case LR_MEM32:
sc_crs->addr_min = letoh32(crs->lr_m32._min);
sc_crs->addr_len = letoh32(crs->lr_m32._len);
@@ -553,19 +571,28 @@ dwiic_acpi_foundhid(struct aml_node *node, void *arg)
return (0);
}
memset(&crs, 0, sizeof(crs));
+ crs.devnode = sc->sc_devnode;
aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs);
aml_freevalue(&res);
- if (crs.irq_int <= 0) {
+ if (crs.gpio_int_node && crs.gpio_int_node->gpio) {
+ struct acpi_gpio *gpio = crs.gpio_int_node->gpio;
+ ia.ia_int = crs.gpio_int_pin;
+ ia.ia_int_flags = crs.gpio_int_flags;
+ ia.acpi_gpio = gpio;
+ } else {
+ ia.ia_int = crs.irq_int;
+ ia.ia_int_flags = crs.irq_flags;
+ ia.acpi_gpio = NULL;
+ }
+ ia.ia_addr = crs.i2c_addr;
+
+ if (ia.ia_int <= 0) {
printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname,
aml_nodename(node->parent));
return 0;
}
- ia.ia_int = crs.irq_int;
- ia.ia_int_flags = crs.irq_flags;
- ia.ia_addr = crs.i2c_addr;
-
if (config_found(sc->sc_iic, &ia, dwiic_i2c_print))
return 0;
diff --git a/sys/dev/i2c/i2cvar.h b/sys/dev/i2c/i2cvar.h
index 5a8e71d67bd..40b487c379c 100644
--- a/sys/dev/i2c/i2cvar.h
+++ b/sys/dev/i2c/i2cvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: i2cvar.h,v 1.13 2016/01/12 17:30:23 deraadt Exp $ */
+/* $OpenBSD: i2cvar.h,v 1.14 2016/04/02 00:56:39 jsg Exp $ */
/* $NetBSD: i2cvar.h,v 1.1 2003/09/30 00:35:31 thorpej Exp $ */
/*
@@ -110,6 +110,7 @@ struct i2c_attach_args {
int ia_int_flags; /* IRQ flags */
char *ia_name; /* chip name */
void *ia_cookie; /* pass extra info from bus to dev */
+ void *acpi_gpio;
};
/*
diff --git a/sys/dev/i2c/ihidev.c b/sys/dev/i2c/ihidev.c
index 8d5c3e9118b..804771930a1 100644
--- a/sys/dev/i2c/ihidev.c
+++ b/sys/dev/i2c/ihidev.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ihidev.c,v 1.9 2016/01/29 17:11:58 jcs Exp $ */
+/* $OpenBSD: ihidev.c,v 1.10 2016/04/02 00:56:39 jsg Exp $ */
/*
* HID-over-i2c driver
*
@@ -30,8 +30,11 @@
#include <dev/hid/hid.h>
-/* XXX */
+#if defined(__i386__) || defined(__amd64__)
+#include "acpi.h"
#include <dev/acpi/acpivar.h>
+#include <dev/acpi/amltypes.h>
+#endif
/* #define IHIDEV_DEBUG */
@@ -156,8 +159,14 @@ ihidev_attach(struct device *parent, struct device *self, void *aux)
sc->sc_ibuf = malloc(sc->sc_isize, M_DEVBUF, M_NOWAIT | M_ZERO);
/* register interrupt with system */
+#if NACPI > 0
+ if (ia->ia_int > 0 && ia->acpi_gpio != NULL) {
+ struct acpi_gpio *gpio = ia->acpi_gpio;
+ gpio->intr_establish(gpio->cookie, ia->ia_int,
+ ia->ia_int_flags, ihidev_intr, sc);
+ } else
+#endif
if (ia->ia_int > 0) {
- /* XXX: don't assume this uses acpi_intr_establish */
sc->sc_ih = acpi_intr_establish(ia->ia_int, ia->ia_int_flags,
IPL_BIO, ihidev_intr, sc, sc->sc_dev.dv_xname);
if (sc->sc_ih == NULL) {