Index: sys/dev/iicbus/twsi/twsi.c =================================================================== --- sys/dev/iicbus/twsi/twsi.c +++ sys/dev/iicbus/twsi/twsi.c @@ -481,12 +481,17 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { struct twsi_softc *sc; + int i; sc = device_get_softc(dev); if (sc->have_intr == false) return (iicbus_transfer_gen(dev, msgs, nmsgs)); + sc->nmsgs = nmsgs; + sc->msgs = msgs; + sc->msg_idx = 0; + sc->transfer = 1; sc->error = 0; sc->control_val = TWSI_CONTROL_TWSIEN | @@ -494,10 +499,6 @@ TWSI_WRITE(sc, sc->reg_control, sc->control_val); debugf(dev, "transmitting %d messages\n", nmsgs); debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status)); - sc->nmsgs = nmsgs; - sc->msgs = msgs; - sc->msg_idx = 0; - sc->transfer = 1; #ifdef TWSI_DEBUG for (int i = 0; i < nmsgs; i++) @@ -506,12 +507,15 @@ /* Send start and re-enable interrupts */ sc->control_val = TWSI_CONTROL_TWSIEN | TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK; - if (sc->msgs[0].len == 1) - sc->control_val &= ~TWSI_CONTROL_ACK; TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); - while (sc->error == 0 && sc->transfer != 0) { + for (i = 0; i < 100 && sc->error == 0 && sc->transfer != 0; i++) { pause_sbt("twsi", SBT_1MS * 30, SBT_1MS, 0); } + if (sc->error == 0 && sc->transfer != 0) { + device_printf(sc->dev, "transfer timeout\n"); + sc->error = IIC_ETIMEOUT; + sc->transfer = 0; + } debugf(sc->dev, "pause finish\n"); if (sc->error) { @@ -533,6 +537,7 @@ struct twsi_softc *sc; uint32_t status; int transfer_done = 0; + int send_byte = 0; sc = arg; @@ -541,6 +546,9 @@ status = TWSI_READ(sc, sc->reg_status); debugf(sc->dev, "reg control=%x\n", TWSI_READ(sc, sc->reg_control)); + if (sc->transfer == 0) + device_printf(sc->dev, "interrupt without active transfer\n"); + switch (status) { case TWSI_STATUS_START: case TWSI_STATUS_RPTD_START: @@ -572,6 +580,8 @@ debugf(sc->dev, "Ack received after transmitting the address (read)\n"); sc->recv_bytes = 0; + if (sc->msgs[sc->msg_idx].len == 1) + sc->control_val &= ~TWSI_CONTROL_ACK; TWSI_WRITE(sc, sc->reg_control, sc->control_val); break; @@ -579,7 +589,7 @@ case TWSI_STATUS_ADDR_R_NACK: debugf(sc->dev, "No ack received after transmitting the address\n"); sc->transfer = 0; - sc->error = ETIMEDOUT; + sc->error = IIC_ENOACK; sc->control_val = 0; wakeup(sc); break; @@ -588,6 +598,8 @@ debugf(sc->dev, "Ack received after transmitting data\n"); if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) { debugf(sc->dev, "Done sending all the bytes for msg %d\n", sc->msg_idx); + send_byte = 0; + /* Send stop, no interrupts on stop */ if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTOP)) { debugf(sc->dev, "Done TX data, send stop\n"); @@ -595,18 +607,29 @@ sc->control_val | TWSI_CONTROL_STOP); } else { debugf(sc->dev, "Done TX data with NO_STOP\n"); - TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); + //TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); } sc->msg_idx++; if (sc->msg_idx == sc->nmsgs) { debugf(sc->dev, "transfer_done=1\n"); transfer_done = 1; sc->error = 0; - } else { + } else if (!(sc->msgs[sc->msg_idx].flags & IIC_M_NOSTART)) { debugf(sc->dev, "Send repeated start\n"); TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START); + } else { + /* Just keep sending data. */ + KASSERT((sc->msgs[sc->msg_idx].flags & IIC_M_RD) == 0, + ("read with nostart after write with nostop")); + debugf(sc->dev, "write followed by write\n"); + sc->sent_bytes = 0; + send_byte = 1; } } else { + send_byte = 1; + } + + if (send_byte) { debugf(sc->dev, "Sending byte %d (of %d) = %x\n", sc->sent_bytes, sc->msgs[sc->msg_idx].len, @@ -660,7 +683,7 @@ default: debugf(sc->dev, "status=%x hot handled\n", status); sc->transfer = 0; - sc->error = ENXIO; + sc->error = IIC_EBUSERR; sc->control_val = 0; wakeup(sc); break;