* [PATCH v2] i2c: iproc: reset bus after timeout if START_BUSY is stuck
@ 2026-07-17 8:55 Jonas Gorski
2026-07-17 9:40 ` Mukesh Savaliya
0 siblings, 1 reply; 3+ messages in thread
From: Jonas Gorski @ 2026-07-17 8:55 UTC (permalink / raw)
To: Andi Shyti, Ray Jui, Scott Branden, Kevin Cernekee, Wolfram Sang
Cc: linux-i2c, linux-arm-kernel, linux-kernel
If a transaction times out, the START_BUSY signal can stay up, and
subsequent transactaction attempts will fail as the bus is still
considered busy.
I can easily trigger this by attempting to read from an address with no
device, e.g. when running i2cdetect. After the first read times out, all
subsequent read attempts return busy.
To get to a working state again, the controller needs to be reset to
clear the START_BUSY signal. So check for START_BUSY still asserted on a
timeout, and do reset in case it is,
This is also done by the original non-upstream iproc-smbus driver
implementation [1].
Works around situations like:
bcm-iproc-2c 1803b000.i2c: transaction timed out
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
...
where the bus never recovers after a timeout.
[1] https://github.com/opencomputeproject/onie/blob/master/patches/kernel/3.2.69/driver-iproc-smbus.patch
Fixes: e6e5dd3566e0 ("i2c: iproc: Add Broadcom iProc I2C Driver")
Signed-off-by: Jonas Gorski <jonas.gorski@bisdn.de>
---
v1 -> v2:
* rebased on current master
* reworded the comment and the commit message, as I found I could
trigger this intentionally
v1: https://lore.kernel.org/all/20230904090005.52622-1-jonas.gorski@bisdn.de/
drivers/i2c/busses/i2c-bcm-iproc.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index b5629cffe99b..86ca4c2221c4 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -803,6 +803,17 @@ static int bcm_iproc_i2c_xfer_wait(struct bcm_iproc_i2c_dev *iproc_i2c,
}
if (!time_left && !iproc_i2c->xfer_is_done) {
+ /*
+ * The controller may fail to clear START_BUSY after a timeout,
+ * reset the controller to recover in that case.
+ */
+ if (!!(iproc_i2c_rd_reg(iproc_i2c, M_CMD_OFFSET) &
+ BIT(M_CMD_START_BUSY_SHIFT))) {
+ bcm_iproc_i2c_enable_disable(iproc_i2c, false);
+ bcm_iproc_i2c_init(iproc_i2c);
+ bcm_iproc_i2c_enable_disable(iproc_i2c, true);
+ }
+
/* flush both TX/RX FIFOs */
val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val);
--
2.55.0
--
BISDN GmbH
Körnerstraße 7-10
10785 Berlin
Germany
Phone: +49 30 610 816 100
Managing Directors: Dr.-Ing. Hagen Woesner, Andreas Köpsel
Commercial
register:
Amtsgericht Berlin-Charlottenburg HRB 141569 B
VAT ID No:
DE283257294 <http://goog_1008408251>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] i2c: iproc: reset bus after timeout if START_BUSY is stuck
2026-07-17 8:55 [PATCH v2] i2c: iproc: reset bus after timeout if START_BUSY is stuck Jonas Gorski
@ 2026-07-17 9:40 ` Mukesh Savaliya
2026-07-17 11:08 ` Jonas Gorski
0 siblings, 1 reply; 3+ messages in thread
From: Mukesh Savaliya @ 2026-07-17 9:40 UTC (permalink / raw)
To: Jonas Gorski, Andi Shyti, Ray Jui, Scott Branden, Kevin Cernekee,
Wolfram Sang
Cc: linux-i2c, linux-arm-kernel, linux-kernel
On 7/17/2026 2:25 PM, Jonas Gorski wrote:
> If a transaction times out, the START_BUSY signal can stay up, and
What's exactly START_BUSY signal
> subsequent transactaction attempts will fail as the bus is still
transactaction => transaction
> considered busy.
>
> I can easily trigger this by attempting to read from an address with no
> device, e.g. when running i2cdetect. After the first read times out, all
> subsequent read attempts return busy.
>
> To get to a working state again, the controller needs to be reset to
> clear the START_BUSY signal. So check for START_BUSY still asserted on a
> timeout, and do reset in case it is,
>
what's here after it is, ? wanted to end the statement ?
> This is also done by the original non-upstream iproc-smbus driver
> implementation [1].
>
> Works around situations like:
>
> bcm-iproc-2c 1803b000.i2c: transaction timed out
> bcm-iproc-2c 1803b000.i2c: bus is busy
> bcm-iproc-2c 1803b000.i2c: bus is busy
> bcm-iproc-2c 1803b000.i2c: bus is busy
> bcm-iproc-2c 1803b000.i2c: bus is busy
> bcm-iproc-2c 1803b000.i2c: bus is busy
> ...
>
> where the bus never recovers after a timeout.
isn't there a max retry count ?
>
[...]
> if (!time_left && !iproc_i2c->xfer_is_done) {
> + /*
> + * The controller may fail to clear START_BUSY after a timeout,
> + * reset the controller to recover in that case.
> + */
Make it simple ?
Recover controller if START_BUSY signal is high after timeout
> + if (!!(iproc_i2c_rd_reg(iproc_i2c, M_CMD_OFFSET) &
> + BIT(M_CMD_START_BUSY_SHIFT))) {
> + bcm_iproc_i2c_enable_disable(iproc_i2c, false);
> + bcm_iproc_i2c_init(iproc_i2c);
> + bcm_iproc_i2c_enable_disable(iproc_i2c, true);
> + }
> +
> /* flush both TX/RX FIFOs */
> val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT);
> iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] i2c: iproc: reset bus after timeout if START_BUSY is stuck
2026-07-17 9:40 ` Mukesh Savaliya
@ 2026-07-17 11:08 ` Jonas Gorski
0 siblings, 0 replies; 3+ messages in thread
From: Jonas Gorski @ 2026-07-17 11:08 UTC (permalink / raw)
To: Mukesh Savaliya
Cc: Andi Shyti, Ray Jui, Scott Branden, Kevin Cernekee, Wolfram Sang,
linux-i2c, linux-arm-kernel, linux-kernel
Hi,
On Fri, 17 Jul 2026 at 11:40, Mukesh Savaliya
<mukesh.savaliya@oss.qualcomm.com> wrote:
>
>
>
> On 7/17/2026 2:25 PM, Jonas Gorski wrote:
> > If a transaction times out, the START_BUSY signal can stay up, and
> What's exactly START_BUSY signal
> > subsequent transactaction attempts will fail as the bus is still
> transactaction => transaction
> > considered busy.
aah, I was so concentrated on getting the recipients right I forgot to
spell check @_@
> >
> > I can easily trigger this by attempting to read from an address with no
> > device, e.g. when running i2cdetect. After the first read times out, all
> > subsequent read attempts return busy.
> >
> > To get to a working state again, the controller needs to be reset to
> > clear the START_BUSY signal. So check for START_BUSY still asserted on a
> > timeout, and do reset in case it is,
> >
> what's here after it is, ? wanted to end the statement ?
I think I forgot an "it" there, "and do reset it in case it is."
> > This is also done by the original non-upstream iproc-smbus driver
> > implementation [1].
> >
> > Works around situations like:
> >
> > bcm-iproc-2c 1803b000.i2c: transaction timed out
> > bcm-iproc-2c 1803b000.i2c: bus is busy
> > bcm-iproc-2c 1803b000.i2c: bus is busy
> > bcm-iproc-2c 1803b000.i2c: bus is busy
> > bcm-iproc-2c 1803b000.i2c: bus is busy
> > bcm-iproc-2c 1803b000.i2c: bus is busy
> > ...
> >
> > where the bus never recovers after a timeout.
> isn't there a max retry count ?
In this case it is an already bound driver(s) trying to do (new)
things. Each busy (likely) comes from a new request. In our case there
is an RTC and several SFPs behind an i2c-mux.
So there are two scenarios where I encountered it:
- during runtime after a few hours of uptime, a timeout occurs
accessing an existing device with a bound driver
- and recently while working on a different device I noticed that
reading from an unoccupied address triggers this also
> >
> [...]
> > if (!time_left && !iproc_i2c->xfer_is_done) {
> > + /*
> > + * The controller may fail to clear START_BUSY after a timeout,
> > + * reset the controller to recover in that case.
> > + */
> Make it simple ?
> Recover controller if START_BUSY signal is high after timeout
That's more or less what I had in the first version, but was asked to
expand it (split about two short comments)
> > + if (!!(iproc_i2c_rd_reg(iproc_i2c, M_CMD_OFFSET) &
> > + BIT(M_CMD_START_BUSY_SHIFT))) {
> > + bcm_iproc_i2c_enable_disable(iproc_i2c, false);
> > + bcm_iproc_i2c_init(iproc_i2c);
> > + bcm_iproc_i2c_enable_disable(iproc_i2c, true);
> > + }
> > +
> > /* flush both TX/RX FIFOs */
> > val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT);
> > iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val);
>
Best regards,
Jonas
--
BISDN GmbH
Körnerstraße 7-10
10785 Berlin
Germany
Phone: +49 30 610 816 100
Managing Directors: Dr.-Ing. Hagen Woesner, Andreas Köpsel
Commercial
register:
Amtsgericht Berlin-Charlottenburg HRB 141569 B
VAT ID No:
DE283257294 <http://goog_1008408251>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-17 11:09 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-17 8:55 [PATCH v2] i2c: iproc: reset bus after timeout if START_BUSY is stuck Jonas Gorski
2026-07-17 9:40 ` Mukesh Savaliya
2026-07-17 11:08 ` Jonas Gorski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox