From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> Add support for detecting arbitration loss in the RIIC controller. For certain slave devices, it was observed that after I2C recovery, the transmission triggered an arbitration loss. To handle this, initiate the I2C recovery sequence and retry the transfer. This ensures reliable communication in scenarios where arbitration loss may occur after recovery. Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx> --- drivers/i2c/busses/i2c-riic.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c index 740e53bdb2a9..86404d2df244 100644 --- a/drivers/i2c/busses/i2c-riic.c +++ b/drivers/i2c/busses/i2c-riic.c @@ -79,6 +79,7 @@ #define ICIER_SPIE BIT(3) #define ICSR2_NACKF BIT(4) +#define ICSR2_AL BIT(1) #define ICBR_RESERVED GENMASK(7, 5) /* Should be 1 on writes */ @@ -180,6 +181,7 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) reinit_completion(&riic->msg_done); +retry: riic_writeb(riic, 0, RIIC_ICSR2); for (i = 0, start_bit = ICCR2_ST; i < num; i++) { @@ -193,8 +195,14 @@ static int riic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) riic_writeb(riic, start_bit, RIIC_ICCR2); time_left = wait_for_completion_timeout(&riic->msg_done, riic->adapter.timeout); - if (time_left == 0) + if (time_left == 0) { + if (riic_readb(riic, RIIC_ICSR2) & ICSR2_AL) { + ret = i2c_recover_bus(&riic->adapter); + if (!ret) + goto retry; + } riic->err = -ETIMEDOUT; + } if (riic->err) break; -- 2.49.0