[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <1eb320b6b7d3a12e62785893ea68c4d16aa2560d.1759838476.git.matthias.schiffer@ew.tq-group.com>
Date: Tue, 7 Oct 2025 14:09:24 +0200
From: Matthias Schiffer <matthias.schiffer@...tq-group.com>
To: Peter Korsgaard <peter@...sgaard.com>,
Andrew Lunn <andrew@...n.ch>,
Andi Shyti <andi.shyti@...nel.org>
Cc: linux-i2c@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux@...tq-group.com,
Matthias Schiffer <matthias.schiffer@...tq-group.com>
Subject: [PATCH 1/2] i2c: ocores: replace 1ms poll iteration timeout with total transfer timeout
When a target makes use of clock stretching, a timeout of 1ms may not be
enough. One extreme example is the NXP PTN3460 eDP to LVDS bridge, which
takes ~320ms to send its ACK after a flash command has been
submitted.
Replace the per-iteration timeout of 1ms with limiting the total
transfer time to the timeout set in struct i2c_adapter (defaulting to
1s, configurable through the I2C_TIMEOUT ioctl). While we're at it, also
add a cpu_relax() to the busy poll loop.
Signed-off-by: Matthias Schiffer <matthias.schiffer@...tq-group.com>
---
drivers/i2c/busses/i2c-ocores.c | 27 ++++++++++++---------------
1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 0f67e57cdeff6..1746c8821a149 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -258,7 +258,7 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
* @reg: register to query
* @mask: bitmask to apply on register value
* @val: expected result
- * @timeout: timeout in jiffies
+ * @timeout: absolute timeout in jiffies
*
* Timeout is necessary to avoid to stay here forever when the chip
* does not answer correctly.
@@ -269,17 +269,16 @@ static int ocores_wait(struct ocores_i2c *i2c,
int reg, u8 mask, u8 val,
const unsigned long timeout)
{
- unsigned long j;
-
- j = jiffies + timeout;
while (1) {
u8 status = oc_getreg(i2c, reg);
if ((status & mask) == val)
break;
- if (time_after(jiffies, j))
+ if (time_after(jiffies, timeout))
return -ETIMEDOUT;
+
+ cpu_relax();
}
return 0;
}
@@ -287,12 +286,13 @@ static int ocores_wait(struct ocores_i2c *i2c,
/**
* ocores_poll_wait() - Wait until is possible to process some data
* @i2c: ocores I2C device instance
+ * @timeout: absolute timeout in jiffies
*
* Used when the device is in polling mode (interrupts disabled).
*
* Return: 0 on success, -ETIMEDOUT on timeout
*/
-static int ocores_poll_wait(struct ocores_i2c *i2c)
+static int ocores_poll_wait(struct ocores_i2c *i2c, unsigned long timeout)
{
u8 mask;
int err;
@@ -310,15 +310,11 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
udelay((8 * 1000) / i2c->bus_clock_khz);
}
- /*
- * once we are here we expect to get the expected result immediately
- * so if after 1ms we timeout then something is broken.
- */
- err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, msecs_to_jiffies(1));
+ err = ocores_wait(i2c, OCI2C_STATUS, mask, 0, timeout);
if (err)
- dev_warn(i2c->adap.dev.parent,
- "%s: STATUS timeout, bit 0x%x did not clear in 1ms\n",
- __func__, mask);
+ dev_dbg(i2c->adap.dev.parent,
+ "%s: STATUS timeout, bit 0x%x did not clear\n",
+ __func__, mask);
return err;
}
@@ -336,11 +332,12 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
*/
static int ocores_process_polling(struct ocores_i2c *i2c)
{
+ unsigned long timeout = jiffies + i2c->adap.timeout;
irqreturn_t ret;
int err = 0;
while (1) {
- err = ocores_poll_wait(i2c);
+ err = ocores_poll_wait(i2c, timeout);
if (err)
break; /* timeout */
--
TQ-Systems GmbH | Mühlstraße 2, Gut Delling | 82229 Seefeld, Germany
Amtsgericht München, HRB 105018
Geschäftsführer: Detlef Schneider, Rüdiger Stahl, Stefan Schneider
https://www.tq-group.com/
Powered by blists - more mailing lists