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);
 	}

Reply via email to