summaryrefslogtreecommitdiff
path: root/drivers/i2c/rk_i2c.c
diff options
context:
space:
mode:
authorWadim Egorov <w.egorov@phytec.de>2017-08-03 13:48:11 +0200
committerPhilipp Tomsich <philipp.tomsich@theobroma-systems.com>2017-09-05 11:13:36 +0200
commit5deaa530280fda91b8fef632c62c94e7bfd89561 (patch)
tree3d887dca6d16fa559240e23df26461592ad5b2df /drivers/i2c/rk_i2c.c
parent313bbcf0ea91db33bdf6ac394e26acff4215bfcf (diff)
rockchip: i2c: fix >32 byte reads
The hw can read up to 32 bytes at a time. If we need more than one chunk, we have to enter the plain RX mode. Signed-off-by: Wadim Egorov <w.egorov@phytec.de> Acked-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
Diffstat (limited to 'drivers/i2c/rk_i2c.c')
-rw-r--r--drivers/i2c/rk_i2c.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
index 8bc045a1a0..68e66536e4 100644
--- a/drivers/i2c/rk_i2c.c
+++ b/drivers/i2c/rk_i2c.c
@@ -164,6 +164,7 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len,
uint rxdata;
uint i, j;
int err;
+ bool snd_chunk = false;
debug("rk_i2c_read: chip = %d, reg = %d, r_len = %d, b_len = %d\n",
chip, reg, r_len, b_len);
@@ -184,15 +185,26 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len,
while (bytes_remain_len) {
if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
- con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX);
+ con = I2C_CON_EN;
bytes_xferred = 32;
} else {
- con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) |
- I2C_CON_LASTACK;
+ /*
+ * The hw can read up to 32 bytes at a time. If we need
+ * more than one chunk, send an ACK after the last byte.
+ */
+ con = I2C_CON_EN | I2C_CON_LASTACK;
bytes_xferred = bytes_remain_len;
}
words_xferred = DIV_ROUND_UP(bytes_xferred, 4);
+ /*
+ * make sure we are in plain RX mode if we read a second chunk
+ */
+ if (snd_chunk)
+ con |= I2C_CON_MOD(I2C_MODE_RX);
+ else
+ con |= I2C_CON_MOD(I2C_MODE_TRX);
+
writel(con, &regs->con);
writel(bytes_xferred, &regs->mrxcnt);
writel(I2C_MBRFIEN | I2C_NAKRCVIEN, &regs->ien);
@@ -227,6 +239,7 @@ static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len,
}
bytes_remain_len -= bytes_xferred;
+ snd_chunk = true;
debug("I2C Read bytes_remain_len %d\n", bytes_remain_len);
}