1a9cade51SNathan Whitehorn /*- 2a9cade51SNathan Whitehorn * Copyright (c) 2001 Tsubai Masanari. All rights reserved. 3a9cade51SNathan Whitehorn * 4a9cade51SNathan Whitehorn * Redistribution and use in source and binary forms, with or without 5a9cade51SNathan Whitehorn * modification, are permitted provided that the following conditions 6a9cade51SNathan Whitehorn * are met: 7a9cade51SNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 8a9cade51SNathan Whitehorn * notice, this list of conditions and the following disclaimer. 9a9cade51SNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 10a9cade51SNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 11a9cade51SNathan Whitehorn * documentation and/or other materials provided with the distribution. 12a9cade51SNathan Whitehorn * 3. The name of the author may not be used to endorse or promote products 13a9cade51SNathan Whitehorn * derived from this software without specific prior written permission. 14a9cade51SNathan Whitehorn * 15a9cade51SNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16a9cade51SNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17a9cade51SNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18a9cade51SNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19a9cade51SNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20a9cade51SNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21a9cade51SNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22a9cade51SNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23a9cade51SNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24a9cade51SNathan Whitehorn * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25a9cade51SNathan Whitehorn * 26a9cade51SNathan Whitehorn * $FreeBSD$ 27a9cade51SNathan Whitehorn * NetBSD: ki2c.c,v 1.11 2007/12/06 17:00:33 ad Exp 28a9cade51SNathan Whitehorn * Id: ki2c.c,v 1.7 2002/10/05 09:56:05 tsubai Exp 29a9cade51SNathan Whitehorn */ 30a9cade51SNathan Whitehorn 31a9cade51SNathan Whitehorn /* 32a9cade51SNathan Whitehorn * Support routines for the Keywest I2C controller. 33a9cade51SNathan Whitehorn */ 34a9cade51SNathan Whitehorn 35a9cade51SNathan Whitehorn #include <sys/param.h> 36a9cade51SNathan Whitehorn #include <sys/systm.h> 37a9cade51SNathan Whitehorn #include <sys/kernel.h> 38a9cade51SNathan Whitehorn #include <sys/module.h> 39a9cade51SNathan Whitehorn #include <sys/bus.h> 40a9cade51SNathan Whitehorn #include <sys/lock.h> 41a9cade51SNathan Whitehorn #include <sys/mutex.h> 42a9cade51SNathan Whitehorn #include <machine/resource.h> 43a9cade51SNathan Whitehorn #include <machine/bus.h> 44a9cade51SNathan Whitehorn #include <sys/rman.h> 45a9cade51SNathan Whitehorn 46a9cade51SNathan Whitehorn #include <dev/iicbus/iicbus.h> 47a9cade51SNathan Whitehorn #include <dev/iicbus/iiconf.h> 48a9cade51SNathan Whitehorn #include <dev/ofw/ofw_bus.h> 49a9cade51SNathan Whitehorn #include "iicbus_if.h" 50a9cade51SNathan Whitehorn 51a9cade51SNathan Whitehorn /* Keywest I2C Register offsets */ 52a9cade51SNathan Whitehorn #define MODE 0 53a9cade51SNathan Whitehorn #define CONTROL 1 54a9cade51SNathan Whitehorn #define STATUS 2 55a9cade51SNathan Whitehorn #define ISR 3 56a9cade51SNathan Whitehorn #define IER 4 57a9cade51SNathan Whitehorn #define ADDR 5 58a9cade51SNathan Whitehorn #define SUBADDR 6 59a9cade51SNathan Whitehorn #define DATA 7 60a9cade51SNathan Whitehorn 61a9cade51SNathan Whitehorn /* MODE */ 62a9cade51SNathan Whitehorn #define I2C_SPEED 0x03 /* Speed mask */ 63a9cade51SNathan Whitehorn #define I2C_100kHz 0x00 64a9cade51SNathan Whitehorn #define I2C_50kHz 0x01 65a9cade51SNathan Whitehorn #define I2C_25kHz 0x02 66a9cade51SNathan Whitehorn #define I2C_MODE 0x0c /* Mode mask */ 67a9cade51SNathan Whitehorn #define I2C_DUMBMODE 0x00 /* Dumb mode */ 68a9cade51SNathan Whitehorn #define I2C_STDMODE 0x04 /* Standard mode */ 69a9cade51SNathan Whitehorn #define I2C_STDSUBMODE 0x08 /* Standard mode + sub address */ 70a9cade51SNathan Whitehorn #define I2C_COMBMODE 0x0c /* Combined mode */ 71a9cade51SNathan Whitehorn #define I2C_PORT 0xf0 /* Port mask */ 72a9cade51SNathan Whitehorn 73a9cade51SNathan Whitehorn /* CONTROL */ 74a9cade51SNathan Whitehorn #define I2C_CT_AAK 0x01 /* Send AAK */ 75a9cade51SNathan Whitehorn #define I2C_CT_ADDR 0x02 /* Send address(es) */ 76a9cade51SNathan Whitehorn #define I2C_CT_STOP 0x04 /* Send STOP */ 77a9cade51SNathan Whitehorn #define I2C_CT_START 0x08 /* Send START */ 78a9cade51SNathan Whitehorn 79a9cade51SNathan Whitehorn /* STATUS */ 80a9cade51SNathan Whitehorn #define I2C_ST_BUSY 0x01 /* Busy */ 81a9cade51SNathan Whitehorn #define I2C_ST_LASTAAK 0x02 /* Last AAK */ 82a9cade51SNathan Whitehorn #define I2C_ST_LASTRW 0x04 /* Last R/W */ 83a9cade51SNathan Whitehorn #define I2C_ST_SDA 0x08 /* SDA */ 84a9cade51SNathan Whitehorn #define I2C_ST_SCL 0x10 /* SCL */ 85a9cade51SNathan Whitehorn 86a9cade51SNathan Whitehorn /* ISR/IER */ 87a9cade51SNathan Whitehorn #define I2C_INT_DATA 0x01 /* Data byte sent/received */ 88a9cade51SNathan Whitehorn #define I2C_INT_ADDR 0x02 /* Address sent */ 89a9cade51SNathan Whitehorn #define I2C_INT_STOP 0x04 /* STOP condition sent */ 90a9cade51SNathan Whitehorn #define I2C_INT_START 0x08 /* START condition sent */ 91a9cade51SNathan Whitehorn 92a9cade51SNathan Whitehorn /* I2C flags */ 93a9cade51SNathan Whitehorn #define I2C_BUSY 0x01 94a9cade51SNathan Whitehorn #define I2C_READING 0x02 95a9cade51SNathan Whitehorn #define I2C_ERROR 0x04 96a9cade51SNathan Whitehorn #define I2C_SELECTED 0x08 97a9cade51SNathan Whitehorn 98a9cade51SNathan Whitehorn struct kiic_softc { 99a9cade51SNathan Whitehorn device_t sc_dev; 100a9cade51SNathan Whitehorn phandle_t sc_node; 101a9cade51SNathan Whitehorn struct mtx sc_mutex; 102a9cade51SNathan Whitehorn struct resource *sc_reg; 103a9cade51SNathan Whitehorn int sc_irqrid; 104a9cade51SNathan Whitehorn struct resource *sc_irq; 105a9cade51SNathan Whitehorn void *sc_ih; 106a9cade51SNathan Whitehorn u_int sc_regstep; 107a9cade51SNathan Whitehorn u_int sc_flags; 108a9cade51SNathan Whitehorn u_char *sc_data; 109a9cade51SNathan Whitehorn int sc_resid; 110a9cade51SNathan Whitehorn device_t sc_iicbus; 111a9cade51SNathan Whitehorn }; 112a9cade51SNathan Whitehorn 113a9cade51SNathan Whitehorn static int kiic_probe(device_t dev); 114a9cade51SNathan Whitehorn static int kiic_attach(device_t dev); 115a9cade51SNathan Whitehorn static void kiic_writereg(struct kiic_softc *sc, u_int, u_int); 116a9cade51SNathan Whitehorn static u_int kiic_readreg(struct kiic_softc *, u_int); 117a9cade51SNathan Whitehorn static void kiic_setmode(struct kiic_softc *, u_int); 118a9cade51SNathan Whitehorn static void kiic_setspeed(struct kiic_softc *, u_int); 119a9cade51SNathan Whitehorn static void kiic_intr(void *xsc); 120a9cade51SNathan Whitehorn static int kiic_transfer(device_t dev, struct iic_msg *msgs, 121a9cade51SNathan Whitehorn uint32_t nmsgs); 122a9cade51SNathan Whitehorn static phandle_t kiic_get_node(device_t bus, device_t dev); 123a9cade51SNathan Whitehorn 124a9cade51SNathan Whitehorn static device_method_t kiic_methods[] = { 125a9cade51SNathan Whitehorn /* device interface */ 126a9cade51SNathan Whitehorn DEVMETHOD(device_probe, kiic_probe), 127a9cade51SNathan Whitehorn DEVMETHOD(device_attach, kiic_attach), 128a9cade51SNathan Whitehorn 129a9cade51SNathan Whitehorn /* iicbus interface */ 130a9cade51SNathan Whitehorn DEVMETHOD(iicbus_callback, iicbus_null_callback), 131a9cade51SNathan Whitehorn DEVMETHOD(iicbus_transfer, kiic_transfer), 132a9cade51SNathan Whitehorn 133a9cade51SNathan Whitehorn /* ofw_bus interface */ 134a9cade51SNathan Whitehorn DEVMETHOD(ofw_bus_get_node, kiic_get_node), 135a9cade51SNathan Whitehorn 136a9cade51SNathan Whitehorn { 0, 0 } 137a9cade51SNathan Whitehorn }; 138a9cade51SNathan Whitehorn 139a9cade51SNathan Whitehorn static driver_t kiic_driver = { 140a9cade51SNathan Whitehorn "iichb", 141a9cade51SNathan Whitehorn kiic_methods, 142a9cade51SNathan Whitehorn sizeof(struct kiic_softc) 143a9cade51SNathan Whitehorn }; 144a9cade51SNathan Whitehorn static devclass_t kiic_devclass; 145a9cade51SNathan Whitehorn 146a9cade51SNathan Whitehorn DRIVER_MODULE(kiic, macio, kiic_driver, kiic_devclass, 0, 0); 147a9cade51SNathan Whitehorn 148a9cade51SNathan Whitehorn static int 149a9cade51SNathan Whitehorn kiic_probe(device_t self) 150a9cade51SNathan Whitehorn { 151a9cade51SNathan Whitehorn const char *name; 152a9cade51SNathan Whitehorn 153a9cade51SNathan Whitehorn name = ofw_bus_get_name(self); 154a9cade51SNathan Whitehorn if (name && strcmp(name, "i2c") == 0) { 155a9cade51SNathan Whitehorn device_set_desc(self, "Keywest I2C controller"); 156a9cade51SNathan Whitehorn return (0); 157a9cade51SNathan Whitehorn } 158a9cade51SNathan Whitehorn 159a9cade51SNathan Whitehorn return (ENXIO); 160a9cade51SNathan Whitehorn } 161a9cade51SNathan Whitehorn 162a9cade51SNathan Whitehorn static int 163a9cade51SNathan Whitehorn kiic_attach(device_t self) 164a9cade51SNathan Whitehorn { 165a9cade51SNathan Whitehorn struct kiic_softc *sc = device_get_softc(self); 166a9cade51SNathan Whitehorn int rid, rate; 167a9cade51SNathan Whitehorn phandle_t node; 168a9cade51SNathan Whitehorn char name[64]; 169a9cade51SNathan Whitehorn 170a9cade51SNathan Whitehorn bzero(sc, sizeof(*sc)); 171a9cade51SNathan Whitehorn sc->sc_dev = self; 172a9cade51SNathan Whitehorn 173a9cade51SNathan Whitehorn node = ofw_bus_get_node(self); 174a9cade51SNathan Whitehorn if (node == 0 || node == -1) { 175a9cade51SNathan Whitehorn return (EINVAL); 176a9cade51SNathan Whitehorn } 177a9cade51SNathan Whitehorn 178a9cade51SNathan Whitehorn rid = 0; 179a9cade51SNathan Whitehorn sc->sc_reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, 180a9cade51SNathan Whitehorn &rid, RF_ACTIVE); 181a9cade51SNathan Whitehorn if (sc->sc_reg == NULL) { 182a9cade51SNathan Whitehorn return (ENOMEM); 183a9cade51SNathan Whitehorn } 184a9cade51SNathan Whitehorn 185a9cade51SNathan Whitehorn if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) { 186a9cade51SNathan Whitehorn device_printf(self, "cannot get i2c-rate\n"); 187a9cade51SNathan Whitehorn return (ENXIO); 188a9cade51SNathan Whitehorn } 189a9cade51SNathan Whitehorn if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) { 190a9cade51SNathan Whitehorn device_printf(self, "unable to find i2c address step\n"); 191a9cade51SNathan Whitehorn return (ENXIO); 192a9cade51SNathan Whitehorn } 193a9cade51SNathan Whitehorn 194a9cade51SNathan Whitehorn /* 195a9cade51SNathan Whitehorn * Some Keywest I2C devices have their children attached directly 196a9cade51SNathan Whitehorn * underneath them. Some have a single 'iicbus' child with the 197a9cade51SNathan Whitehorn * devices underneath that. Sort this out, and make sure that the 198a9cade51SNathan Whitehorn * OFW I2C layer has the correct node. 199a9cade51SNathan Whitehorn */ 200a9cade51SNathan Whitehorn 201a9cade51SNathan Whitehorn sc->sc_node = OF_child(node); 202a9cade51SNathan Whitehorn if (OF_getprop(sc->sc_node,"name",name,sizeof(name)) > 0) { 203a9cade51SNathan Whitehorn if (strcmp(name,"i2c-bus") != 0) 204a9cade51SNathan Whitehorn sc->sc_node = node; 205a9cade51SNathan Whitehorn } 206a9cade51SNathan Whitehorn 207a9cade51SNathan Whitehorn mtx_init(&sc->sc_mutex, "kiic", NULL, MTX_DEF); 208a9cade51SNathan Whitehorn 209a9cade51SNathan Whitehorn sc->sc_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &sc->sc_irqrid, 210a9cade51SNathan Whitehorn RF_ACTIVE); 211a9cade51SNathan Whitehorn bus_setup_intr(self, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, NULL, 212a9cade51SNathan Whitehorn kiic_intr, sc, &sc->sc_ih); 213a9cade51SNathan Whitehorn 214a9cade51SNathan Whitehorn kiic_writereg(sc, STATUS, 0); 215a9cade51SNathan Whitehorn kiic_writereg(sc, ISR, 0); 216a9cade51SNathan Whitehorn kiic_writereg(sc, IER, 0); 217a9cade51SNathan Whitehorn 218a9cade51SNathan Whitehorn kiic_setmode(sc, I2C_STDMODE); 219a9cade51SNathan Whitehorn kiic_setspeed(sc, I2C_100kHz); /* XXX rate */ 220a9cade51SNathan Whitehorn 221a9cade51SNathan Whitehorn kiic_writereg(sc, IER, I2C_INT_DATA | I2C_INT_ADDR | I2C_INT_STOP); 222a9cade51SNathan Whitehorn 223a9cade51SNathan Whitehorn /* Add the IIC bus layer */ 224a9cade51SNathan Whitehorn sc->sc_iicbus = device_add_child(self, "iicbus", -1); 225a9cade51SNathan Whitehorn 226a9cade51SNathan Whitehorn return (bus_generic_attach(self)); 227a9cade51SNathan Whitehorn } 228a9cade51SNathan Whitehorn 229a9cade51SNathan Whitehorn static void 230a9cade51SNathan Whitehorn kiic_writereg(struct kiic_softc *sc, u_int reg, u_int val) 231a9cade51SNathan Whitehorn { 232a9cade51SNathan Whitehorn bus_write_1(sc->sc_reg, sc->sc_regstep * reg, val); 233a9cade51SNathan Whitehorn DELAY(10); /* XXX why? */ 234a9cade51SNathan Whitehorn } 235a9cade51SNathan Whitehorn 236a9cade51SNathan Whitehorn static u_int 237a9cade51SNathan Whitehorn kiic_readreg(struct kiic_softc *sc, u_int reg) 238a9cade51SNathan Whitehorn { 239a9cade51SNathan Whitehorn return bus_read_1(sc->sc_reg, sc->sc_regstep * reg); 240a9cade51SNathan Whitehorn } 241a9cade51SNathan Whitehorn 242a9cade51SNathan Whitehorn static void 243a9cade51SNathan Whitehorn kiic_setmode(struct kiic_softc *sc, u_int mode) 244a9cade51SNathan Whitehorn { 245a9cade51SNathan Whitehorn u_int x; 246a9cade51SNathan Whitehorn 247a9cade51SNathan Whitehorn KASSERT((mode & ~I2C_MODE) == 0, ("bad mode")); 248a9cade51SNathan Whitehorn x = kiic_readreg(sc, MODE); 249a9cade51SNathan Whitehorn x &= ~I2C_MODE; 250a9cade51SNathan Whitehorn x |= mode; 251a9cade51SNathan Whitehorn kiic_writereg(sc, MODE, x); 252a9cade51SNathan Whitehorn } 253a9cade51SNathan Whitehorn 254a9cade51SNathan Whitehorn static void 255a9cade51SNathan Whitehorn kiic_setspeed(struct kiic_softc *sc, u_int speed) 256a9cade51SNathan Whitehorn { 257a9cade51SNathan Whitehorn u_int x; 258a9cade51SNathan Whitehorn 259a9cade51SNathan Whitehorn KASSERT((speed & ~I2C_SPEED) == 0, ("bad speed")); 260a9cade51SNathan Whitehorn x = kiic_readreg(sc, MODE); 261a9cade51SNathan Whitehorn x &= ~I2C_SPEED; 262a9cade51SNathan Whitehorn x |= speed; 263a9cade51SNathan Whitehorn kiic_writereg(sc, MODE, x); 264a9cade51SNathan Whitehorn } 265a9cade51SNathan Whitehorn 266a9cade51SNathan Whitehorn static void 267a9cade51SNathan Whitehorn kiic_intr(void *xsc) 268a9cade51SNathan Whitehorn { 269a9cade51SNathan Whitehorn struct kiic_softc *sc = xsc; 270a9cade51SNathan Whitehorn u_int isr; 271a9cade51SNathan Whitehorn uint32_t x; 272a9cade51SNathan Whitehorn 273a9cade51SNathan Whitehorn mtx_lock(&sc->sc_mutex); 274a9cade51SNathan Whitehorn isr = kiic_readreg(sc, ISR); 275a9cade51SNathan Whitehorn 276a9cade51SNathan Whitehorn if (isr & I2C_INT_ADDR) { 277a9cade51SNathan Whitehorn sc->sc_flags |= I2C_SELECTED; 278a9cade51SNathan Whitehorn 279a9cade51SNathan Whitehorn if (sc->sc_flags & I2C_READING) { 280a9cade51SNathan Whitehorn if (sc->sc_resid > 1) { 281a9cade51SNathan Whitehorn x = kiic_readreg(sc, CONTROL); 282a9cade51SNathan Whitehorn x |= I2C_CT_AAK; 283a9cade51SNathan Whitehorn kiic_writereg(sc, CONTROL, x); 284a9cade51SNathan Whitehorn } 285a9cade51SNathan Whitehorn } else { 286a9cade51SNathan Whitehorn kiic_writereg(sc, DATA, *sc->sc_data++); 287a9cade51SNathan Whitehorn sc->sc_resid--; 288a9cade51SNathan Whitehorn } 289a9cade51SNathan Whitehorn } 290a9cade51SNathan Whitehorn 291a9cade51SNathan Whitehorn if (isr & I2C_INT_DATA) { 292a9cade51SNathan Whitehorn if (sc->sc_resid > 0) { 293a9cade51SNathan Whitehorn if (sc->sc_flags & I2C_READING) { 294a9cade51SNathan Whitehorn *sc->sc_data++ = kiic_readreg(sc, DATA); 295a9cade51SNathan Whitehorn sc->sc_resid--; 296a9cade51SNathan Whitehorn } else { 297a9cade51SNathan Whitehorn kiic_writereg(sc, DATA, *sc->sc_data++); 298a9cade51SNathan Whitehorn sc->sc_resid--; 299a9cade51SNathan Whitehorn } 300a9cade51SNathan Whitehorn } 301a9cade51SNathan Whitehorn 302a9cade51SNathan Whitehorn if (sc->sc_resid == 0) 303a9cade51SNathan Whitehorn wakeup(sc->sc_dev); 304a9cade51SNathan Whitehorn } 305a9cade51SNathan Whitehorn 306a9cade51SNathan Whitehorn if (isr & I2C_INT_STOP) { 307a9cade51SNathan Whitehorn kiic_writereg(sc, CONTROL, 0); 308a9cade51SNathan Whitehorn sc->sc_flags &= ~I2C_SELECTED; 309a9cade51SNathan Whitehorn wakeup(sc->sc_dev); 310a9cade51SNathan Whitehorn } 311a9cade51SNathan Whitehorn 312a9cade51SNathan Whitehorn kiic_writereg(sc, ISR, isr); 313a9cade51SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 314a9cade51SNathan Whitehorn } 315a9cade51SNathan Whitehorn 316a9cade51SNathan Whitehorn static int 317a9cade51SNathan Whitehorn kiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) 318a9cade51SNathan Whitehorn { 319a9cade51SNathan Whitehorn struct kiic_softc *sc; 320a9cade51SNathan Whitehorn int i, x, timo; 321a9cade51SNathan Whitehorn uint8_t addr; 322a9cade51SNathan Whitehorn 323a9cade51SNathan Whitehorn sc = device_get_softc(dev); 324a9cade51SNathan Whitehorn timo = 100; 325a9cade51SNathan Whitehorn 326a9cade51SNathan Whitehorn mtx_lock(&sc->sc_mutex); 327a9cade51SNathan Whitehorn 328a9cade51SNathan Whitehorn if (sc->sc_flags & I2C_BUSY) 329a9cade51SNathan Whitehorn mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo); 330a9cade51SNathan Whitehorn 331a9cade51SNathan Whitehorn if (sc->sc_flags & I2C_BUSY) { 332a9cade51SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 333a9cade51SNathan Whitehorn return (ETIMEDOUT); 334a9cade51SNathan Whitehorn } 335a9cade51SNathan Whitehorn 336a9cade51SNathan Whitehorn sc->sc_flags = I2C_BUSY; 337a9cade51SNathan Whitehorn 338a9cade51SNathan Whitehorn for (i = 0; i < nmsgs; i++) { 339a9cade51SNathan Whitehorn sc->sc_data = msgs[i].buf; 340a9cade51SNathan Whitehorn sc->sc_resid = msgs[i].len; 341a9cade51SNathan Whitehorn sc->sc_flags = I2C_BUSY; 342a9cade51SNathan Whitehorn addr = msgs[i].slave; 343a9cade51SNathan Whitehorn timo = 1000 + sc->sc_resid * 200; 344a9cade51SNathan Whitehorn 345a9cade51SNathan Whitehorn if (msgs[i].flags & IIC_M_RD) { 346a9cade51SNathan Whitehorn sc->sc_flags |= I2C_READING; 347a9cade51SNathan Whitehorn addr |= 1; 348a9cade51SNathan Whitehorn } 349a9cade51SNathan Whitehorn 350a9cade51SNathan Whitehorn kiic_writereg(sc, ADDR, addr); 351a9cade51SNathan Whitehorn kiic_writereg(sc, SUBADDR, 0x04); 352a9cade51SNathan Whitehorn 353a9cade51SNathan Whitehorn x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR; 354a9cade51SNathan Whitehorn kiic_writereg(sc, CONTROL, x); 355a9cade51SNathan Whitehorn 356a9cade51SNathan Whitehorn mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo); 357a9cade51SNathan Whitehorn 358a9cade51SNathan Whitehorn if (!(sc->sc_flags & I2C_READING)) { 359a9cade51SNathan Whitehorn x = kiic_readreg(sc, CONTROL) | I2C_CT_STOP; 360a9cade51SNathan Whitehorn kiic_writereg(sc, CONTROL, x); 361a9cade51SNathan Whitehorn } 362a9cade51SNathan Whitehorn 363a9cade51SNathan Whitehorn mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo); 364a9cade51SNathan Whitehorn 365a9cade51SNathan Whitehorn msgs[i].len -= sc->sc_resid; 366a9cade51SNathan Whitehorn 367a9cade51SNathan Whitehorn if (sc->sc_flags & I2C_ERROR) { 368a9cade51SNathan Whitehorn device_printf(sc->sc_dev, "I2C_ERROR\n"); 369a9cade51SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 370a9cade51SNathan Whitehorn return (-1); 371a9cade51SNathan Whitehorn } 372a9cade51SNathan Whitehorn } 373a9cade51SNathan Whitehorn 374a9cade51SNathan Whitehorn sc->sc_flags = 0; 375a9cade51SNathan Whitehorn 376a9cade51SNathan Whitehorn mtx_unlock(&sc->sc_mutex); 377a9cade51SNathan Whitehorn 378a9cade51SNathan Whitehorn return (0); 379a9cade51SNathan Whitehorn } 380a9cade51SNathan Whitehorn 381a9cade51SNathan Whitehorn static phandle_t 382a9cade51SNathan Whitehorn kiic_get_node(device_t bus, device_t dev) 383a9cade51SNathan Whitehorn { 384a9cade51SNathan Whitehorn struct kiic_softc *sc; 385a9cade51SNathan Whitehorn 386a9cade51SNathan Whitehorn sc = device_get_softc(bus); 387a9cade51SNathan Whitehorn /* We only have one child, the I2C bus, which needs our own node. */ 388a9cade51SNathan Whitehorn 389a9cade51SNathan Whitehorn return sc->sc_node; 390a9cade51SNathan Whitehorn } 391a9cade51SNathan Whitehorn 392