diff options
author | 2016-04-10 16:43:17 +0000 | |
---|---|---|
committer | 2016-04-10 16:43:17 +0000 | |
commit | 985c1510ff2c50b7ee8345ee96c91434fbcc4990 (patch) | |
tree | 0605c03deb4463b4c44f0c9ef0a6c0946f2839d2 | |
parent | Simple regression tests for rev(1), including UTF-8. (diff) | |
download | wireguard-openbsd-985c1510ff2c50b7ee8345ee96c91434fbcc4990.tar.xz wireguard-openbsd-985c1510ff2c50b7ee8345ee96c91434fbcc4990.zip |
Fix layer violation in the ihidev(4) code by implementing a generic mechanism
that allows the i2c controller implementation to establish interrupts on
behalf of i2c slave device drivers. Use this mechanism in dwiic(4) to let
it configure the right acpi interrupt (global or gpio). Change the level to
IPL_TTY as this is the appropriate level to use for keyboards and other
input devices.
ok jsg@
-rw-r--r-- | sys/dev/acpi/dwiic.c | 36 | ||||
-rw-r--r-- | sys/dev/i2c/i2cvar.h | 13 | ||||
-rw-r--r-- | sys/dev/i2c/ihidev.c | 27 |
3 files changed, 41 insertions, 35 deletions
diff --git a/sys/dev/acpi/dwiic.c b/sys/dev/acpi/dwiic.c index 1ff01f8ef8f..31571e02cac 100644 --- a/sys/dev/acpi/dwiic.c +++ b/sys/dev/acpi/dwiic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dwiic.c,v 1.13 2016/04/02 00:56:39 jsg Exp $ */ +/* $OpenBSD: dwiic.c,v 1.14 2016/04/10 16:43:17 kettenis Exp $ */ /* * Synopsys DesignWare I2C controller * @@ -173,6 +173,9 @@ int dwiic_init(struct dwiic_softc *); void dwiic_enable(struct dwiic_softc *, int); int dwiic_intr(void *); +void * dwiic_i2c_intr_establish(void *, void *, int, + int (*)(void *), void *, const char *); + int dwiic_acpi_parse_crs(union acpi_resource *, void *); int dwiic_acpi_foundhid(struct aml_node *, void *); void dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *, @@ -307,6 +310,7 @@ dwiic_attach(struct device *parent, struct device *self, void *aux) sc->sc_i2c_tag.ic_acquire_bus = dwiic_i2c_acquire_bus; sc->sc_i2c_tag.ic_release_bus = dwiic_i2c_release_bus; sc->sc_i2c_tag.ic_exec = dwiic_i2c_exec; + sc->sc_i2c_tag.ic_intr_establish = dwiic_i2c_intr_establish; bzero(&sc->sc_iba, sizeof(sc->sc_iba)); sc->sc_iba.iba_name = "iic"; @@ -483,6 +487,23 @@ dwiic_i2c_print(void *aux, const char *pnp) return UNCONF; } +void * +dwiic_i2c_intr_establish(void *cookie, void *ih, int level, + int (*func)(void *), void *arg, const char *name) +{ + struct dwiic_crs *crs = ih; + + if (crs->gpio_int_node && crs->gpio_int_node->gpio) { + struct acpi_gpio *gpio = crs->gpio_int_node->gpio; + gpio->intr_establish(gpio->cookie, crs->gpio_int_pin, + crs->gpio_int_flags, func, arg); + return ih; + } + + return acpi_intr_establish(crs->irq_int, crs->irq_flags, + level, func, arg, name); +} + int dwiic_acpi_foundhid(struct aml_node *node, void *arg) { @@ -575,23 +596,14 @@ dwiic_acpi_foundhid(struct aml_node *node, void *arg) aml_parse_resource(&res, dwiic_acpi_parse_crs, &crs); aml_freevalue(&res); - 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) { + if (crs.irq_int <= 0 && crs.gpio_int_node == NULL) { printf("%s: couldn't find irq for %s\n", sc->sc_dev.dv_xname, aml_nodename(node->parent)); return 0; } + ia.ia_intr = &crs; 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 40b487c379c..7f63349db12 100644 --- a/sys/dev/i2c/i2cvar.h +++ b/sys/dev/i2c/i2cvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i2cvar.h,v 1.14 2016/04/02 00:56:39 jsg Exp $ */ +/* $OpenBSD: i2cvar.h,v 1.15 2016/04/10 16:43:17 kettenis Exp $ */ /* $NetBSD: i2cvar.h,v 1.1 2003/09/30 00:35:31 thorpej Exp $ */ /* @@ -90,6 +90,9 @@ typedef struct i2c_controller { int (*ic_initiate_xfer)(void *, i2c_addr_t, int); int (*ic_read_byte)(void *, uint8_t *, int); int (*ic_write_byte)(void *, uint8_t, int); + + void *(*ic_intr_establish)(void *, void *, int, int (*)(void *), + void *, const char *); } *i2c_tag_t; /* Used to attach the i2c framework to the controller. */ @@ -106,11 +109,9 @@ struct i2c_attach_args { i2c_tag_t ia_tag; /* our controller */ i2c_addr_t ia_addr; /* address of device */ int ia_size; /* size (for EEPROMs) */ - int ia_int; /* IRQ */ - int ia_int_flags; /* IRQ flags */ char *ia_name; /* chip name */ void *ia_cookie; /* pass extra info from bus to dev */ - void *acpi_gpio; + void *ia_intr; /* interrupt info */ }; /* @@ -154,6 +155,10 @@ int iic_smbus_write_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t, int); int iic_smbus_read_byte(i2c_tag_t, i2c_addr_t, uint8_t, uint8_t *, int); int iic_smbus_receive_byte(i2c_tag_t, i2c_addr_t, uint8_t *, int); +#define iic_intr_establish(ic, ih, level, func, arg, name) \ + (*(ic)->ic_intr_establish)((ic)->ic_cookie, (ih), (level), \ + (func), (arg), (name)) + void iic_ignore_addr(u_int8_t addr); #endif /* _DEV_I2C_I2CVAR_H_ */ diff --git a/sys/dev/i2c/ihidev.c b/sys/dev/i2c/ihidev.c index 804771930a1..57724b4003d 100644 --- a/sys/dev/i2c/ihidev.c +++ b/sys/dev/i2c/ihidev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ihidev.c,v 1.10 2016/04/02 00:56:39 jsg Exp $ */ +/* $OpenBSD: ihidev.c,v 1.11 2016/04/10 16:43:17 kettenis Exp $ */ /* * HID-over-i2c driver * @@ -30,12 +30,6 @@ #include <dev/hid/hid.h> -#if defined(__i386__) || defined(__amd64__) -#include "acpi.h" -#include <dev/acpi/acpivar.h> -#include <dev/acpi/amltypes.h> -#endif - /* #define IHIDEV_DEBUG */ #ifdef IHIDEV_DEBUG @@ -114,7 +108,9 @@ ihidev_attach(struct device *parent, struct device *self, void *aux) sc->sc_addr = ia->ia_addr; sc->sc_hid_desc_addr = ia->ia_size; - printf(": int %d", ia->ia_int); + /* XXX print proper interrupt string */ + if (ia->ia_intr) + printf(": interrupt"); if (ihidev_hid_command(sc, I2C_HID_CMD_DESCR, NULL) || ihidev_hid_desc_parse(sc)) { @@ -159,18 +155,11 @@ 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) { - sc->sc_ih = acpi_intr_establish(ia->ia_int, ia->ia_int_flags, - IPL_BIO, ihidev_intr, sc, sc->sc_dev.dv_xname); + if (ia->ia_intr) { + sc->sc_ih = iic_intr_establish(sc->sc_tag, ia->ia_intr, + IPL_TTY, ihidev_intr, sc, sc->sc_dev.dv_xname); if (sc->sc_ih == NULL) { - printf(", failed establishing intr\n"); + printf(", can't establish interrupt\n"); return; } } |