[PATCH v2] i2c: rk3x: add support for SCL OE debounce and slave hold recovery
Anand Moon
linux.amoon at gmail.com
Tue Mar 31 06:18:10 PDT 2026
Hi Andi,
Thanks for your review comments.
On Fri, 27 Mar 2026 at 19:43, Andi Shyti <andi.shyti at kernel.org> wrote:
>
> Hi Anand,
>
> ...
>
> > @@ -1125,6 +1141,17 @@ static int rk3x_i2c_xfer_common(struct i2c_adapter *adap,
> > }
> > }
> >
> > + /*
> > + * If a timeout occurred and the slave is holding SCL,
> > + * re-apply the timings/dividers to attempt recovery.
> > + */
> > + if (ret == -ETIMEDOUT && i2c->soc_data->has_scl_oe_debounce) {
> > + if (ipd & REG_INT_SLV_HDSCL) {
> > + dev_err(i2c->dev, "SCL hold by slave detected, resetting timings.\n");
> > + rk3x_i2c_adapt_div(i2c, clk_get_rate(i2c->clk));
>
> argh! this nests i2c->lock. rk3x_i2c_xfer_common() already holds
> it when calling rk3x_i2c_adapt_div().
I agree; the current implementation can lead to a deadlock.
To resolve this, I'll split the function into locked and unlocked variants.
Note that this deadlock only occurs if REG_INT_SLV_HDSCL is active in the
interrupt enable mask, as shown below:
static void rk3x_i2c_start(struct rk3x_i2c *i2c)
{
u32 val = i2c_readl(i2c, REG_CON) & REG_CON_TUNING_MASK;
+ u32 ien = REG_INT_START;
- i2c_writel(i2c, REG_INT_START, REG_IEN);
+ if(i2c->soc_data->has_scl_oe_debounce)
+ ien != REG_INT_SLV_HDSCL;
+
+ i2c_writel(i2c, ien, REG_IEN);
Thanks
-Anand
More information about the Linux-rockchip
mailing list