summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2005-11-13 19:26:31 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2005-11-13 19:26:31 +0000
commit694f33bb1782b9face609672619169e5ac26d7bf (patch)
tree7f5b62c3a781ba7e96215a7297f701b83412949f /sys/arch
parent6d208da0ad8e9f074a45d1cf639d1c4aa097af9c (diff)
Add code to turn ki2c(4) into a proper i2c controller.
ok deraadt@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/macppc/dev/ki2c.c63
-rw-r--r--sys/arch/macppc/dev/ki2cvar.h5
2 files changed, 65 insertions, 3 deletions
diff --git a/sys/arch/macppc/dev/ki2c.c b/sys/arch/macppc/dev/ki2c.c
index c4584c27995..2540f0f558a 100644
--- a/sys/arch/macppc/dev/ki2c.c
+++ b/sys/arch/macppc/dev/ki2c.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ki2c.c,v 1.4 2005/11/06 03:10:09 drahn Exp $ */
+/* $OpenBSD: ki2c.c,v 1.5 2005/11/13 19:26:30 kettenis Exp $ */
/* $NetBSD: ki2c.c,v 1.1 2003/12/27 02:19:34 grant Exp $ */
/*-
@@ -36,6 +36,7 @@
#include <machine/autoconf.h>
#include <macppc/dev/ki2cvar.h>
+#include <macppc/dev/maci2cvar.h>
int ki2c_match(struct device *, void *, void *);
void ki2c_attach(struct device *, struct device *, void *);
@@ -51,6 +52,12 @@ int ki2c_start(struct ki2c_softc *, int, int, void *, int);
int ki2c_read(struct ki2c_softc *, int, int, void *, int);
int ki2c_write(struct ki2c_softc *, int, int, const void *, int);
+/* I2C glue */
+int ki2c_i2c_acquire_bus(void *, int);
+void ki2c_i2c_release_bus(void *, int);
+int ki2c_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
+ void *, size_t, int);
+
struct cfattach ki2c_ca = {
sizeof(struct ki2c_softc), ki2c_match, ki2c_attach
};
@@ -84,6 +91,7 @@ ki2c_attach(parent, self, aux)
{
struct ki2c_softc *sc = (struct ki2c_softc *)self;
struct confargs *ca = aux;
+ struct maci2cbus_attach_args iba;
int node = ca->ca_node;
int rate;
@@ -111,6 +119,18 @@ ki2c_attach(parent, self, aux)
ki2c_setmode(sc, I2C_STDSUBMODE);
ki2c_setspeed(sc, I2C_100kHz); /* XXX rate */
+
+ lockinit(&sc->sc_buslock, PZERO, sc->sc_dev.dv_xname, 0, 0);
+ ki2c_writereg(sc, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
+
+ sc->sc_i2c_tag.ic_cookie = sc;
+ sc->sc_i2c_tag.ic_acquire_bus = ki2c_i2c_acquire_bus;
+ sc->sc_i2c_tag.ic_release_bus = ki2c_i2c_release_bus;
+ sc->sc_i2c_tag.ic_exec = ki2c_i2c_exec;
+
+ iba.iba_node = node;
+ iba.iba_tag = &sc->sc_i2c_tag;
+ config_found(&sc->sc_dev, &iba, NULL);
}
u_int
@@ -185,7 +205,6 @@ ki2c_intr(sc)
u_int isr, x;
isr = ki2c_readreg(sc, ISR);
-
if (isr & I2C_INT_ADDR) {
#if 0
if ((ki2c_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
@@ -319,3 +338,43 @@ ki2c_write(sc, addr, subaddr, data, len)
sc->sc_flags = 0;
return ki2c_start(sc, addr, subaddr, (void *)data, len);
}
+
+int
+ki2c_i2c_acquire_bus(void *cookie, int flags)
+{
+ struct ki2c_softc *sc = cookie;
+
+ return (lockmgr(&sc->sc_buslock, LK_EXCLUSIVE, NULL, curproc));
+}
+
+void
+ki2c_i2c_release_bus(void *cookie, int flags)
+{
+ struct ki2c_softc *sc = cookie;
+
+ (void) lockmgr(&sc->sc_buslock, LK_RELEASE, NULL, curproc);
+}
+
+int
+ki2c_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
+ const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
+{
+ struct ki2c_softc *sc = cookie;
+
+ if (!I2C_OP_STOP_P(op))
+ return (EINVAL);
+
+ /* We handle the subaddress stuff ourselves. */
+ ki2c_setmode(sc, I2C_STDMODE);
+
+ if (ki2c_write(sc, (addr << 1), 0, cmdbuf, cmdlen) != 0)
+ return (EIO);
+ if (I2C_OP_READ_P(op)) {
+ if (ki2c_read(sc, (addr << 1), 0, buf, len) != 0)
+ return (EIO);
+ } else {
+ if (ki2c_write(sc, (addr << 1), 0, buf, len) != 0)
+ return (EIO);
+ }
+ return (0);
+}
diff --git a/sys/arch/macppc/dev/ki2cvar.h b/sys/arch/macppc/dev/ki2cvar.h
index ca96f0ceceb..e6174dfe33c 100644
--- a/sys/arch/macppc/dev/ki2cvar.h
+++ b/sys/arch/macppc/dev/ki2cvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ki2cvar.h,v 1.1 2005/11/05 04:33:20 brad Exp $ */
+/* $OpenBSD: ki2cvar.h,v 1.2 2005/11/13 19:26:30 kettenis Exp $ */
/*-
* Copyright (c) 2001 Tsubai Masanari. All rights reserved.
@@ -87,6 +87,9 @@ struct ki2c_softc {
u_char *sc_reg;
int sc_regstep;
+ struct i2c_controller sc_i2c_tag;
+ struct lock sc_buslock;
+
int sc_flags;
u_char *sc_data;
int sc_resid;