summaryrefslogtreecommitdiff
path: root/sys/dev/acpi/dwiic_acpi.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2023-04-23 00:33:03 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2023-04-23 00:33:03 +0000
commit47d7682bde65221653f17bcd182f74412969e861 (patch)
tree6f6f8ea9cc6cca1e6a0bd5ec097869170fc29baf /sys/dev/acpi/dwiic_acpi.c
parentdab0a5ce68c5fdc2ae6c7a3eac21718d7eb9cf03 (diff)
add support for coordinating i2c bus access with iosf(4)
if the acpi node has a _SEM property, add wrappers around the i2c bus acquire and release handlers to try and call the iosf provided hardware semaphore ops. this means bus accesses can be coordinate with other parts of the platform such as the punit. this stops my Dell Wyse 3040 from locking up. ok kettenis@ patrick@
Diffstat (limited to 'sys/dev/acpi/dwiic_acpi.c')
-rw-r--r--sys/dev/acpi/dwiic_acpi.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/sys/dev/acpi/dwiic_acpi.c b/sys/dev/acpi/dwiic_acpi.c
index ad8b9776116..acfe7b5327c 100644
--- a/sys/dev/acpi/dwiic_acpi.c
+++ b/sys/dev/acpi/dwiic_acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dwiic_acpi.c,v 1.20 2022/08/31 15:14:01 kettenis Exp $ */
+/* $OpenBSD: dwiic_acpi.c,v 1.21 2023/04/23 00:33:02 dlg Exp $ */
/*
* Synopsys DesignWare I2C controller
*
@@ -17,6 +17,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "iosf.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -28,6 +30,7 @@
#include <dev/acpi/dsdt.h>
#include <dev/ic/dwiicvar.h>
+#include <dev/ic/iosfvar.h>
struct dwiic_crs {
int irq_int;
@@ -53,6 +56,11 @@ void dwiic_acpi_power(struct dwiic_softc *, int);
void dwiic_acpi_bus_scan(struct device *,
struct i2cbus_attach_args *, void *);
+#if NIOSF > 0
+int dwiic_acpi_acquire_bus(void *, int);
+void dwiic_acpi_release_bus(void *, int);
+#endif
+
const struct cfattach dwiic_acpi_ca = {
sizeof(struct dwiic_softc),
dwiic_acpi_match,
@@ -103,6 +111,7 @@ dwiic_acpi_attach(struct device *parent, struct device *self, void *aux)
struct acpi_attach_args *aaa = aux;
struct aml_value res;
struct dwiic_crs crs;
+ uint64_t sem;
sc->sc_acpi = (struct acpi_softc *)parent;
sc->sc_devnode = aaa->aaa_node;
@@ -163,6 +172,13 @@ dwiic_acpi_attach(struct device *parent, struct device *self, void *aux)
printf(": can't establish interrupt");
}
+ if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
+ "_SEM", 0, NULL, &sem))
+ sem = 0;
+
+ if (sem)
+ printf(", sem");
+
printf("\n");
rw_init(&sc->sc_i2c_lock, "iiclk");
@@ -176,6 +192,13 @@ dwiic_acpi_attach(struct device *parent, struct device *self, void *aux)
sc->sc_i2c_tag.ic_intr_disestablish = dwiic_i2c_intr_disestablish;
sc->sc_i2c_tag.ic_intr_string = dwiic_i2c_intr_string;
+#if NIOSF > 0
+ if (sem) {
+ sc->sc_i2c_tag.ic_acquire_bus = dwiic_acpi_acquire_bus;
+ sc->sc_i2c_tag.ic_release_bus = dwiic_acpi_release_bus;
+ }
+#endif
+
bzero(&sc->sc_iba, sizeof(sc->sc_iba));
sc->sc_iba.iba_name = "iic";
sc->sc_iba.iba_tag = &sc->sc_i2c_tag;
@@ -547,3 +570,27 @@ dwiic_acpi_power(struct dwiic_softc *sc, int power)
dwiic_write(sc, 0x800, 1);
}
}
+
+#if NIOSF > 0
+extern int iosf_i2c_acquire(int);
+extern void iosf_i2c_release(int);
+
+int
+dwiic_acpi_acquire_bus(void *cookie, int flags)
+{
+ int rv;
+
+ rv = dwiic_i2c_acquire_bus(cookie, flags);
+ if (rv != 0)
+ return (rv);
+
+ return (iosf_i2c_acquire(flags));
+}
+
+void
+dwiic_acpi_release_bus(void *cookie, int flags)
+{
+ iosf_i2c_release(flags);
+ dwiic_i2c_release_bus(cookie, flags);
+}
+#endif /* NIOSF > 0 */