[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250430194647.332553-3-prabhakar.mahadev-lad.rj@bp.renesas.com>
Date: Wed, 30 Apr 2025 20:46:47 +0100
From: Prabhakar <prabhakar.csengg@...il.com>
To: Chris Brandt <chris.brandt@...esas.com>,
Andi Shyti <andi.shyti@...nel.org>,
Wolfram Sang <wsa+renesas@...g-engineering.com>,
Geert Uytterhoeven <geert+renesas@...der.be>,
Andy Shevchenko <andy@...nel.org>
Cc: linux-renesas-soc@...r.kernel.org,
linux-i2c@...r.kernel.org,
linux-kernel@...r.kernel.org,
Prabhakar <prabhakar.csengg@...il.com>,
Biju Das <biju.das.jz@...renesas.com>,
Fabrizio Castro <fabrizio.castro.jz@...esas.com>,
Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
Subject: [PATCH v9 2/2] i2c: riic: Recover from arbitration loss
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@...renesas.com>
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@...renesas.com>
---
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
Powered by blists - more mailing lists