From 694f33bb1782b9face609672619169e5ac26d7bf Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sun, 13 Nov 2005 19:26:31 +0000 Subject: Add code to turn ki2c(4) into a proper i2c controller. ok deraadt@ --- sys/arch/macppc/dev/ki2c.c | 63 +++++++++++++++++++++++++++++++++++++++++-- sys/arch/macppc/dev/ki2cvar.h | 5 +++- 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 #include +#include 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; -- cgit v1.2.3