int kiic_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 kiic_bus *bus = cookie; u_int mode = I2C_STDSUBMODE; u_int8_t cmd = 0; if (!I2C_OP_STOP_P(op) || cmdlen > 1) return (EINVAL); if (cmdlen == 0) mode = I2C_STDMODE; else if (I2C_OP_READ_P(op)) mode = I2C_COMBMODE; if (cmdlen > 0) cmd = *(u_int8_t *)cmdbuf; kiic_setmode(bus->sc, mode, bus->reg || addr & 0x80); addr &= 0x7f; if (I2C_OP_READ_P(op)) { if (kiic_read(bus->sc, (addr << 1), cmd, buf, len) != 0) return (EIO); } else { if (kiic_write(bus->sc, (addr << 1), cmd, buf, len) != 0) return (EIO); } return (0); }
void kiic_attach(struct device *parent, struct device *self, void *aux) { struct kiic_softc *sc = (struct kiic_softc *)self; struct confargs *ca = aux; int node = ca->ca_node; int rate, count = 0; char name[32]; ca->ca_reg[0] += ca->ca_baseaddr; if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) { printf(": cannot get i2c-rate\n"); return; } if (OF_getprop(node, "AAPL,address", &sc->sc_paddr, 4) != 4) { printf(": unable to find i2c address\n"); return; } if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) { printf(": unable to find i2c address step\n"); return; } sc->sc_reg = mapiodev(sc->sc_paddr, (DATA+1)*sc->sc_regstep); printf("\n"); kiic_writereg(sc, STATUS, 0); kiic_writereg(sc, ISR, 0); kiic_writereg(sc, IER, 0); kiic_setmode(sc, I2C_STDSUBMODE, 0); kiic_setspeed(sc, I2C_100kHz); /* XXX rate */ rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname); kiic_writereg(sc, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP); for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) { if (OF_getprop(node, "name", &name, sizeof name) > 0) { if (strcmp(name, "i2c-bus") == 0) { kiic_attach_bus(sc, &sc->sc_bus[count], node); if (++count >= KIIC_MAX_BUSSES) break; } } } /* * If we didn't find any i2c-bus nodes, there is only a single * i2c bus. */ if (count == 0) kiic_attach_bus(sc, &sc->sc_bus[0], ca->ca_node); }
static int kiic_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { struct kiic_softc *sc; int i, x, timo, err; uint16_t addr; uint8_t subaddr; sc = device_get_softc(dev); timo = 100; subaddr = 0; mtx_lock(&sc->sc_mutex); if (sc->sc_flags & I2C_BUSY) mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo); if (sc->sc_flags & I2C_BUSY) { mtx_unlock(&sc->sc_mutex); return (ETIMEDOUT); } sc->sc_flags = I2C_BUSY; /* Clear pending interrupts, and reset controller */ kiic_writereg(sc, ISR, kiic_readreg(sc, ISR)); kiic_writereg(sc, STATUS, 0); for (i = 0; i < nmsgs; i++) { if (msgs[i].flags & IIC_M_NOSTOP) { if (msgs[i+1].flags & IIC_M_RD) kiic_setmode(sc, I2C_COMBMODE); else kiic_setmode(sc, I2C_STDSUBMODE); KASSERT(msgs[i].len == 1, ("oversize I2C message")); subaddr = msgs[i].buf[0]; i++; } else { kiic_setmode(sc, I2C_STDMODE); } sc->sc_data = msgs[i].buf; sc->sc_resid = msgs[i].len; sc->sc_flags = I2C_BUSY; addr = msgs[i].slave; timo = 1000 + sc->sc_resid * 200; timo += 100000; if (msgs[i].flags & IIC_M_RD) { sc->sc_flags |= I2C_READING; addr |= 1; } addr |= sc->sc_i2c_base; kiic_setport(sc, (addr & 0x100) >> 8); kiic_writereg(sc, ADDR, addr & 0xff); kiic_writereg(sc, SUBADDR, subaddr); x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR; kiic_writereg(sc, CONTROL, x); err = mtx_sleep(dev, &sc->sc_mutex, 0, "kiic", timo); msgs[i].len -= sc->sc_resid; if ((sc->sc_flags & I2C_ERROR) || err == EWOULDBLOCK) { device_printf(sc->sc_dev, "I2C error\n"); sc->sc_flags = 0; mtx_unlock(&sc->sc_mutex); return (EIO); } } sc->sc_flags = 0; mtx_unlock(&sc->sc_mutex); return (0); }
static int kiic_attach(device_t self) { struct kiic_softc *sc = device_get_softc(self); int rid, rate; phandle_t node; char name[64]; bzero(sc, sizeof(*sc)); sc->sc_dev = self; node = ofw_bus_get_node(self); if (node == 0 || node == -1) { return (EINVAL); } rid = 0; sc->sc_reg = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->sc_reg == NULL) { return (ENOMEM); } if (OF_getencprop(node, "AAPL,i2c-rate", &rate, 4) != 4) { device_printf(self, "cannot get i2c-rate\n"); return (ENXIO); } if (OF_getencprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) { device_printf(self, "unable to find i2c address step\n"); return (ENXIO); } /* * Some Keywest I2C devices have their children attached directly * underneath them. Some have a single 'iicbus' child with the * devices underneath that. Sort this out, and make sure that the * OFW I2C layer has the correct node. * * Note: the I2C children of the Uninorth bridges have two ports. * In general, the port is designated in the 9th bit of the I2C * address. However, for kiic devices with children attached below * an i2c-bus node, the port is indicated in the 'reg' property * of the i2c-bus node. */ sc->sc_node = node; node = OF_child(node); if (OF_getprop(node, "name", name, sizeof(name)) > 0) { if (strcmp(name,"i2c-bus") == 0) { phandle_t reg; if (OF_getprop(node, "reg", ®, sizeof(reg)) > 0) sc->sc_i2c_base = reg << 8; sc->sc_node = node; } } mtx_init(&sc->sc_mutex, "kiic", NULL, MTX_DEF); sc->sc_irq = bus_alloc_resource_any(self, SYS_RES_IRQ, &sc->sc_irqrid, RF_ACTIVE); bus_setup_intr(self, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, NULL, kiic_intr, sc, &sc->sc_ih); kiic_writereg(sc, ISR, kiic_readreg(sc, ISR)); kiic_writereg(sc, STATUS, 0); kiic_writereg(sc, IER, 0); kiic_setmode(sc, I2C_STDMODE); kiic_setspeed(sc, I2C_100kHz); /* XXX rate */ kiic_writereg(sc, IER, I2C_INT_DATA | I2C_INT_ADDR | I2C_INT_STOP); if (bootverbose) device_printf(self, "Revision: %02X\n", kiic_readreg(sc, REV)); /* Add the IIC bus layer */ sc->sc_iicbus = device_add_child(self, "iicbus", -1); return (bus_generic_attach(self)); }