From: Quanyang Wang <>

When using i2c_smbus_read_byte_data to read one byte from a
slave device, because of the commit d358def70688
("i2c: cadence: Fix the hold bit setting"), the transaction becomes:

S Addr Wr [A] Comm [A] P S Addr Rd [A] [Data] NA P
                CR_HOLD bit as 0

This will result that the read operation fails and will read "0xff" from
the slave device. In the SMBus protocol, it stipulates that it must follow
that command with a repeated START condition as below:

S Addr Wr [A] Comm [A] Sr Addr Rd [A] [Data] NA P

So add a check if I2C_M_NOSTART is set in flags. If set, clear the
CR_HOLD bit, or else keep CR_HOLD bit to be 1 to make sure that
the read operation begins with a repeated START.

Signed-off-by: Quanyang Wang <>
Reviewed-by: Shubhrajyoti Datta <>
Signed-off-by: Bruce Ashfield <>
 drivers/i2c/busses/i2c-cadence.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c
index 6b011931e090..22c1590c0e7a 100644
--- a/drivers/i2c/busses/i2c-cadence.c
+++ b/drivers/i2c/busses/i2c-cadence.c
@@ -624,10 +624,12 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
-       if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag)
+       if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag) {
                ctrl_reg |= CDNS_I2C_CR_HOLD;
-       else
-               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+       } else {
+               if (id->p_msg->flags & I2C_M_NOSTART)
+                       ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+       }
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);

Links: You receive all messages sent to this group.

View/Reply Online (#8160):
Mute This Topic:
Group Owner:

Reply via email to