Module Name: src Committed By: jmcneill Date: Fri Nov 8 00:35:16 UTC 2019
Modified Files: src/sys/arch/arm/rockchip: rk_i2c.c Log Message: Support reads of more than 32 bytes in a single xfer. To generate a diff of this commit: cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/rockchip/rk_i2c.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/rockchip/rk_i2c.c diff -u src/sys/arch/arm/rockchip/rk_i2c.c:1.5 src/sys/arch/arm/rockchip/rk_i2c.c:1.6 --- src/sys/arch/arm/rockchip/rk_i2c.c:1.5 Wed Sep 18 12:49:34 2019 +++ src/sys/arch/arm/rockchip/rk_i2c.c Fri Nov 8 00:35:16 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: rk_i2c.c,v 1.5 2019/09/18 12:49:34 tnn Exp $ */ +/* $NetBSD: rk_i2c.c,v 1.6 2019/11/08 00:35:16 jmcneill Exp $ */ /*- * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca> @@ -28,7 +28,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rk_i2c.c,v 1.5 2019/09/18 12:49:34 tnn Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rk_i2c.c,v 1.6 2019/11/08 00:35:16 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -284,7 +284,7 @@ rk_i2c_write(struct rk_i2c_softc *sc, i2 static int rk_i2c_read(struct rk_i2c_softc *sc, i2c_addr_t addr, const uint8_t *cmd, size_t cmdlen, uint8_t *buf, - size_t buflen, int flags, bool send_start) + size_t buflen, int flags, bool send_start, bool last_ack) { uint32_t rxdata[8]; uint32_t con, mrxaddr, mrxraddr; @@ -296,24 +296,27 @@ rk_i2c_read(struct rk_i2c_softc *sc, i2c if (cmdlen > 3) return EINVAL; - mode = RKI2C_CON_I2C_MODE_RTX; - con = RKI2C_CON_I2C_EN | RKI2C_CON_ACK | __SHIFTIN(mode, RKI2C_CON_I2C_MODE); + mode = send_start ? RKI2C_CON_I2C_MODE_RTX : RKI2C_CON_I2C_MODE_RX; + con = RKI2C_CON_I2C_EN | __SHIFTIN(mode, RKI2C_CON_I2C_MODE); WR4(sc, RKI2C_CON, con); if (send_start && (error = rk_i2c_start(sc)) != 0) return error; - mrxaddr = __SHIFTIN((addr << 1) | 1, RKI2C_MRXADDR_SADDR) | - RKI2C_MRXADDR_ADDLVLD; - WR4(sc, RKI2C_MRXADDR, mrxaddr); - for (n = 0, mrxraddr = 0; n < cmdlen; n++) { - mrxraddr |= cmd[n] << (n * 8); - mrxraddr |= (RKI2C_MRXRADDR_ADDLVLD << n); + if (send_start) { + mrxaddr = __SHIFTIN((addr << 1) | 1, RKI2C_MRXADDR_SADDR) | + RKI2C_MRXADDR_ADDLVLD; + WR4(sc, RKI2C_MRXADDR, mrxaddr); + for (n = 0, mrxraddr = 0; n < cmdlen; n++) { + mrxraddr |= cmd[n] << (n * 8); + mrxraddr |= (RKI2C_MRXRADDR_ADDLVLD << n); + } + WR4(sc, RKI2C_MRXRADDR, mrxraddr); } - WR4(sc, RKI2C_MRXRADDR, mrxraddr); - /* Acknowledge last byte read */ - con |= RKI2C_CON_ACK; + if (last_ack) { + con |= RKI2C_CON_ACK; + } WR4(sc, RKI2C_CON, con); /* Receive data. Slave address goes in the lower 8 bits of MRXADDR */ @@ -321,8 +324,14 @@ rk_i2c_read(struct rk_i2c_softc *sc, i2c if ((error = rk_i2c_wait(sc, RKI2C_IPD_MBRFIPD)) != 0) return error; +#if 0 bus_space_read_region_4(sc->sc_bst, sc->sc_bsh, RKI2C_RXDATA(0), rxdata, howmany(buflen, 4)); +#else + for (n = 0; n < roundup(buflen, 4); n += 4) + rxdata[n/4] = RD4(sc, RKI2C_RXDATA(n/4)); +#endif + memcpy(buf, rxdata, buflen); return 0; @@ -339,7 +348,19 @@ rk_i2c_exec(void *priv, i2c_op_t op, i2c KASSERT(mutex_owned(&sc->sc_lock)); if (I2C_OP_READ_P(op)) { - error = rk_i2c_read(sc, addr, cmdbuf, cmdlen, buf, buflen, flags, send_start); + uint8_t *databuf = buf; + while (buflen > 0) { + const size_t datalen = uimin(buflen, 32); + const bool last_ack = datalen == buflen; + error = rk_i2c_read(sc, addr, cmdbuf, cmdlen, databuf, datalen, flags, send_start, last_ack); + if (error != 0) + break; + databuf += datalen; + buflen -= datalen; + send_start = false; + cmdbuf = NULL; + cmdlen = 0; + } } else { error = rk_i2c_write(sc, addr, cmdbuf, cmdlen, buf, buflen, flags, send_start); }