Index: sys/arm64/rockchip/rk_i2c.c =================================================================== --- sys/arm64/rockchip/rk_i2c.c +++ sys/arm64/rockchip/rk_i2c.c @@ -291,6 +291,7 @@ rk_i2c_intr_locked(struct rk_i2c_softc *sc) { uint32_t reg; + int transfer_len; sc->ipd = RK_I2C_READ(sc, RK_I2C_IPD); @@ -324,11 +325,16 @@ RK_I2C_WRITE(sc, RK_I2C_IEN, RK_I2C_IEN_MBRFIEN | RK_I2C_IEN_NAKRCVIEN); - reg = RK_I2C_READ(sc, RK_I2C_CON); - reg |= RK_I2C_CON_LASTACK; - RK_I2C_WRITE(sc, RK_I2C_CON, reg); + if ((sc->msg->len - sc->cnt) > 32) + transfer_len = 32; + else { + transfer_len = (sc->msg->len - sc->cnt); + reg = RK_I2C_READ(sc, RK_I2C_CON); + reg |= RK_I2C_CON_LASTACK; + RK_I2C_WRITE(sc, RK_I2C_CON, reg); + } - RK_I2C_WRITE(sc, RK_I2C_MRXCNT, sc->msg->len); + RK_I2C_WRITE(sc, RK_I2C_MRXCNT, transfer_len); } else { sc->state = STATE_WRITE; RK_I2C_WRITE(sc, RK_I2C_IEN, RK_I2C_IEN_MBTFIEN | @@ -344,6 +350,23 @@ if (sc->cnt == sc->msg->len) rk_i2c_send_stop(sc); + else { + sc->mode = RK_I2C_CON_MODE_RX; + reg = RK_I2C_READ(sc, RK_I2C_CON) & \ + ~RK_I2C_CON_CTRL_MASK; + reg |= sc->mode << RK_I2C_CON_MODE_SHIFT; + reg |= RK_I2C_CON_EN; + + if (sc->msg->len > 32) + transfer_len = 32; + else { + transfer_len = sc->msg->len; + reg |= RK_I2C_CON_LASTACK; + } + + RK_I2C_WRITE(sc, RK_I2C_CON, reg); + RK_I2C_WRITE(sc, RK_I2C_MRXCNT, transfer_len); + } break; case STATE_WRITE: @@ -455,8 +478,8 @@ /* Clean stale interrupts */ RK_I2C_WRITE(sc, RK_I2C_IPD, RK_I2C_IPD_ALL); - err = 0; for (i = 0; i < nmsgs; i++) { + err = 0; /* Validate parameters. */ if (msgs == NULL || msgs[i].buf == NULL || msgs[i].len == 0) { @@ -509,7 +532,7 @@ sc->mode = RK_I2C_CON_MODE_RX; } else { sc->mode = RK_I2C_CON_MODE_RRX; - reg = msgs[i].slave & LSB; + reg = msgs[i].slave & ~LSB; reg |= RK_I2C_MRXADDR_VALID(0); RK_I2C_WRITE(sc, RK_I2C_MRXADDR, reg); RK_I2C_WRITE(sc, RK_I2C_MRXRADDR, 0); @@ -537,6 +560,7 @@ err = msleep(sc, &sc->mtx, PZERO, "rk_i2c", 10 * hz); } + DELAY(100); } }