[PATCH] i2c: rk3x: Disable the controller between transfers

Shawn Lin shawn.lin at rock-chips.com
Mon Oct 19 17:48:49 PDT 2026


Hi

在 2026/10/20 星期二 0:50, Alexey Charkov 写道:
> Hi Shawn,
> 
> On Fri, Oct 16, 2026 at 4:33 AM Shawn Lin <shawn.lin at rock-chips.com> wrote:
>>
>> Cc: + David
>>
>> 在 2026/10/15 星期四 22:00, Alexey Charkov 写道:
>>> The driver leaves the controller enabled once a transfer completes, and
>>> an enabled controller keeps tracking the bus. If the lines collapse under
>>> it while idle, as happens when a target's supply is switched off while
>>> its bus pull-ups stay powered, its state machine wedges driving SDA low.
>>> Every later transfer then times out, since the timeout path only requests
>>> a STOP and never disables the controller, and the stuck state even
>>> survives a kexec.
>>>
>>> Clear the enable bit once each transfer is done, successful or not, so
>>> that the controller does not watch an idle bus and starts every transfer
>>> from a clean state.
>>>
>>
>> I checked the vendor kernel tree and saw another case that you perhaps
>> need to fold something similar below into your patch, along with your
>> disabling controller?
>>
>>       In some case,log like this:
>>
>>       [   12.393926] rk3x-i2c ff150000.i2c: irq in STATE_IDLE, ipd = 0x51
>>       [   12.416592] rk3x-i2c ff150000.i2c: irq in STATE_IDLE, ipd = 0x51
>>
>>       The i2c clock is disabled, so the pending irq clean is not
>>       worked. Disable the interrupt after the i2c jobs were done,
>>       the error log would not happen.
>>
>>
>> /* Disable i2c all irqs */
>> #define IEN_ALL_DISABLE   0
>>
>> i2c_writel(i2c, IEN_ALL_DISABLE, REG_IEN);i2c_writel(i2c,
>> IEN_ALL_DISABLE, REG_IEN);
> 
> Thanks for looking into this! Do you happen to have a reproducer or
> any additional info on how this state gets triggered? I haven't run
> into it in my setups - did I just get lucky? :)
> 

Unfortunately, I don't. That came from what I found when checking
the vendor kernel commit to see how we handled your case.

So I have looped David who made the internal submision for the same case
as yours 8 years ago and hope him could have a comment here.

> I see the same write of 0 to REG_IEN just above my changed lines for
> the case if (time_left == 0), which makes sense because a
> too-long-running transfer might eventually complete and trigger the
> interrupt with the controller disabled, unless the interrupt is
> disabled too. For other cases I'd be interested to know what can raise
> the interrupt.
> 
> Best regards,
> Alexey
> 




More information about the Linux-rockchip mailing list