[PATCH 1/2] i2c: designware: Only check for spurious STOP without EMPTYFIFO_HOLD_MASTER

From: Sarah Maedel

Date: Tue Nov 10 2026 - 10:55:51 EST


Commit 560072246088 ("i2c: designware: Support of controller with
IC_EMPTYFIFO_HOLD_MASTER disabled") fails a transfer when STOP_DET is
seen while a read or write is still in progress. This is meant to catch
Tx FIFO underruns on controllers without IC_EMPTYFIFO_HOLD_MASTER_EN,
but the check is applied to all controllers.

Controllers with IC_EMPTYFIFO_HOLD_MASTER_EN hold SCL on an empty Tx
FIFO and can't underrun, but on a multi-master bus they also see
STOP_DET for other masters' transactions. The driver then disables the
adapter while the controller is still busy with the transfer. On
DW_apb_i2c 1.20a (Ampere Altra, IPMI SSIF shared with the BMC) this
leaves the master stuck with IC_ENABLE_STATUS set, and all following
transfers fail with "timeout waiting for bus ready".

Limit the check to controllers without IC_EMPTYFIFO_HOLD_MASTER, as
suggested by David LaPorte.

Fixes: 560072246088 ("i2c: designware: Support of controller with IC_EMPTYFIFO_HOLD_MASTER disabled")
Cc: stable@xxxxxxxxxxxxxxx # v7.0+
Suggested-by: David LaPorte <dalaport@xxxxxxxxxx>
Link: https://lore.kernel.org/all/20260505232244.71807-1-dalaport@xxxxxxxxxx/
Signed-off-by: Sarah Maedel <sarah.maedel@xxxxxxxxxxxxxxxx>
---
drivers/i2c/busses/i2c-designware-master.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 7e1d9a2e7733..d7d99c7b6ef2 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -675,8 +675,11 @@ static void i2c_dw_process_transfer(struct dw_i2c_dev *dev, unsigned int stat)
if (stat & DW_IC_INTR_TX_EMPTY)
i2c_dw_xfer_msg(dev);

- /* Abort if we detect a STOP in the middle of a read or a write */
- if ((stat & DW_IC_INTR_STOP_DET) &&
+ /*
+ * Abort if we detect a STOP in the middle of a read or a write on a
+ * controller that doesn't hold SCL on an empty Tx FIFO.
+ */
+ if (!dev->emptyfifo_hold_master && (stat & DW_IC_INTR_STOP_DET) &&
(dev->status & (STATUS_READ_IN_PROGRESS | STATUS_WRITE_IN_PROGRESS))) {
dev_err(dev->dev, "spurious STOP detected\n");
dev->rx_outstanding = 0;
--
2.47.3