summaryrefslogtreecommitdiff
path: root/sys/dev/acpi
diff options
context:
space:
mode:
authorJonathan Gray <jsg@cvs.openbsd.org>2016-04-02 00:56:40 +0000
committerJonathan Gray <jsg@cvs.openbsd.org>2016-04-02 00:56:40 +0000
commit1205b031a9ad9ffbd73b76f455e3bcf03051352d (patch)
tree50a48389d84c32e30aa2524c5a5848a62088d3c5 /sys/dev/acpi
parentb54c4ee0cba313b9404baa78fdc8883273e79883 (diff)
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/dev/acpi')
-rw-r--r--sys/dev/acpi/dwiic.c39
1 files changed, 33 insertions, 6 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;