diff options
author | Wadim Egorov <w.egorov@phytec.de> | 2017-08-03 13:48:11 +0200 |
---|---|---|
committer | Philipp Tomsich <philipp.tomsich@theobroma-systems.com> | 2017-09-05 11:13:36 +0200 |
commit | 5deaa530280fda91b8fef632c62c94e7bfd89561 (patch) | |
tree | 3d887dca6d16fa559240e23df26461592ad5b2df /drivers/i2c | |
parent | 313bbcf0ea91db33bdf6ac394e26acff4215bfcf (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')
-rw-r--r-- | drivers/i2c/rk_i2c.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c index 8bc045a1a02..68e66536e4e 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, ®s->con); writel(bytes_xferred, ®s->mrxcnt); writel(I2C_MBRFIEN | I2C_NAKRCVIEN, ®s->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); } |