From 5620636871515ccf68c1a33886aa803de479f2f6 Mon Sep 17 00:00:00 2001 From: Sudarshan Iyengar Date: Sat, 18 Apr 2026 17:33:53 +0530 Subject: [PATCH] drivers: i2c: i2c_dw: unmask START_DET to recover from stuck target state The target ISR gates write_requested() on `dw->state != CMD_SEND` so that back-to-back rx_full interrupts during a single write do not re-enter the callback. However, dw->state is only transitioned back to READY on stop_det. If the STOP interrupt is lost (glitch, bus reset, another master drives STOP while we are servicing the ISR), or if the master issues a repeated START with the same direction (WRITE-Sr-WRITE, which is legal in I2C), the state stays CMD_SEND forever and write_requested() is never called again for the rest of the target's life. i2c_dw_slave_read_clear_intr_bits() already handles start_det by resetting state to READY, but START_DET is not in the enabled interrupt mask in i2c_dw_slave_register(), so that path is dead code. Unmask START_DET so the boundary of every new (re)START on the bus is observed and state is correctly reset before the rx_full handler decides whether to call write_requested(). Signed-off-by: Sudarshan Iyengar --- drivers/i2c/i2c_dw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index e39197d191c61..b524f7abc747a 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -1142,8 +1142,9 @@ static int i2c_dw_slave_register(const struct device *dev, struct i2c_target_con dw->read_in_progress = false; dw->slave_cfg = cfg; ret = i2c_dw_set_slave_mode(dev, cfg->address); - write_intr_mask(DW_INTR_MASK_RX_FULL | DW_INTR_MASK_RD_REQ | DW_INTR_MASK_TX_ABRT | - DW_INTR_MASK_STOP_DET, + write_intr_mask(DW_INTR_MASK_RX_FULL | DW_INTR_MASK_RD_REQ | + DW_INTR_MASK_TX_ABRT | DW_INTR_MASK_STOP_DET | + DW_INTR_MASK_START_DET, reg_base); return ret;