[PATCH v2 1/2] i2c: imx: Don't recover bus when arbitration lost
Carlos Song (OSS)
carlos.song at oss.nxp.com
Tue May 19 03:29:23 PDT 2026
> -----Original Message-----
> From: Dan Scally <dan.scally at ideasonboard.com>
> Sent: Tuesday, May 19, 2026 4:42 PM
> To: Oleksij Rempel <o.rempel at pengutronix.de>; Pengutronix Kernel Team
> <kernel at pengutronix.de>
> Cc: linux-i2c at vger.kernel.org; imx at lists.linux.dev;
> linux-arm-kernel at lists.infradead.org; Andi Shyti <andi.shyti at kernel.org>; Frank
> Li <frank.li at nxp.com>; Sascha Hauer <s.hauer at pengutronix.de>; Fabio
> Estevam <festevam at gmail.com>; Gao Pan <b54642 at freescale.com>; Fugang
> Duan <B38611 at freescale.com>; Wolfram Sang <wsa at kernel.org>
> Subject: Re: [PATCH v2 1/2] i2c: imx: Don't recover bus when arbitration lost
>
> [You don't often get email from dan.scally at ideasonboard.com. Learn why this is
> important at https://aka.ms/LearnAboutSenderIdentification ]
>
> Hello Oleksij / all
>
> On 24/04/2026 13:36, Daniel Scally wrote:
> > In i2c_imx_xfer_common(), the driver attempts bus recovery whenever
> > i2c_imx_start() fails. One of the failure modes for i2c_imx_start() is
> > an arbitration-lost signal which results when a second I2C master on
> > the bus tries to control the bus simultaneously, which is a normal and
> > expected behaviour.
> >
> > Bus recovery is not the right response for this case. Add a check for
> > the -EAGAIN return code to avoid running the bus recovery.
> >
> > Fixes: 1c4b6c3bcf30d ("i2c: imx: implement bus recovery")
> > Signed-off-by: Daniel Scally <dan.scally at ideasonboard.com>
> > ---
>
> I raised this patch after we had issues with one of the i2c controllers on imx8mp.
> In that case, the bus had multiple masters that were causing the SoC's i2c
> controller to lose arbitration. The result was that the framework attempted to
> run i2c_generic_scl_recovery() and regularly hit the "SCL is stuck low, exit
> recovery" message [1] because the bus was busy rather than stuck.
>
> I'm now experiencing a different issue with the imx8mp in which a different
> controller - which isn't on a multiple-masters bus - starts transacting fine early in
> boot, but then seems to get stuck - any attempt to start a transaction by either
> a driver or i2ctransfer results in the IAL bit in I2C_I2SR being set and so the
> driver reports that it's lost arbitration [2]. In this case, the bus recovery is
> needed to fix the problem, and so this commit hurts things rather than helps
> them. This problem isn't consistent - I get it on maybe 10% of boots.
>
Hi Dan,
This is the RM shows:
Arbitration lost. Set by hardware in the following circumstances (IAL must be cleared by software by
writing a "0" to it at the start of the interrupt service routine):
* I2Cn_SDA input samples low when the master drives high during an address or data-transmit cycle.
* I2Cn_SDA input samples low when the master drives high during the acknowledge bit of a datareceive
cycle.
For the above two cases, the bit is set at the falling edge of the ninth I2Cn_SCL clock during the ACK
cycle.
* A Start cycle is attempted when the bus is busy.
* A Repeated Start cycle is requested in Slave mode.
* A Stop condition is detected when the master did not request it.
NOTE: Software cannot set the bit.
0 No arbitration lost.
1 Arbitration is lost.
>From my understanding:
The IAL (Arbitration Lost) bit is set not only when true arbitration is lost, but also in several other conditions:
- SDA is sampled low when the master drives it high (during address/data or ACK phase)
- A START is attempted while the bus is busy
- A STOP condition is detected unexpectedly
- A repeated START occurs in slave mode
So in practice, IAL can be asserted not only by real arbitration loss, but also when the controller detects abnormal bus conditions.
Since your system is single-master, this is unlikely to be a true arbitration scenario. Instead, it is more likely caused by signal integrity or timing-related issues, such as:
- weak pull-up / slow rising edges
- noise or glitches on SDA
- timing violations from the slave device
- others
As a workaround, you can enable the 'single-master' property to disable arbitration checks in single-master systems, for example:
&i2c1 {
clock-frequency = <400000>;
pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
pinctrl-1 = <&pinctrl_i2c1_gpio>;
scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
single-master;
status = "okay";
};
Hope it will help some.
Carlos
More information about the linux-arm-kernel
mailing list