[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