[PATCH v1 1/1] i2c: npcm: unexpected SLVRSTR IRQ in master mode

From: baneric926

Date: Tue Jun 23 2026 - 01:48:08 EST


From: Ban Feng <kcfeng0@xxxxxxxxxxx>

SLVRSTR IRQ occurs even when BMC acts as master role only.
This case was not handled in the master IRQ handler,
resulting in IRQ storming.
Handle this condition to prevent the spurious interrupt.

Signed-off-by: Ban Feng <kcfeng0@xxxxxxxxxxx>
---
drivers/i2c/busses/i2c-npcm7xx.c | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)

diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
index f667a873b81e..02dd8c3ba44b 100644
--- a/drivers/i2c/busses/i2c-npcm7xx.c
+++ b/drivers/i2c/busses/i2c-npcm7xx.c
@@ -593,6 +593,7 @@ struct npcm_i2c {
u64 nack_cnt;
u64 timeout_cnt;
u64 tx_complete_cnt;
+ u64 ab_slvrstr_cnt;
bool ber_state; /* Indicate the bus error state */
};

@@ -1709,6 +1710,24 @@ static void npcm_i2c_irq_master_handler_read(struct npcm_i2c *bus)
}
}

+static void npcm_i2c_irq_handle_ab_slvrstr(struct npcm_i2c *bus)
+{
+ u8 val;
+
+ if (bus->ab_slvrstr_cnt < ULLONG_MAX)
+ bus->ab_slvrstr_cnt++;
+ npcm_i2c_clear_tx_fifo(bus);
+ npcm_i2c_clear_rx_fifo(bus);
+ iowrite8(0, bus->reg + NPCM_I2CRXF_CTL);
+ iowrite8(0, bus->reg + NPCM_I2CTXF_CTL);
+ val = NPCM_I2CFIF_CTS_CLR_FIFO | NPCM_I2CFIF_CTS_SLVRSTR |
+ NPCM_I2CFIF_CTS_RXF_TXE;
+ iowrite8(val, bus->reg + NPCM_I2CFIF_CTS);
+ bus->stop_ind = I2C_BUS_ERR_IND;
+ npcm_i2c_callback(bus, bus->stop_ind, npcm_i2c_get_index(bus));
+ bus->state = I2C_IDLE;
+}
+
static void npcm_i2c_irq_handle_nmatch(struct npcm_i2c *bus)
{
iowrite8(NPCM_I2CST_NMATCH, bus->reg + NPCM_I2CST);
@@ -1777,6 +1796,8 @@ static void npcm_i2c_irq_handle_ber(struct npcm_i2c *bus)
if (npcm_i2c_is_master(bus)) {
npcm_i2c_master_abort(bus);
} else {
+ /* Clear the FIFO */
+ iowrite8(NPCM_I2CFIF_CTS_CLR_FIFO, bus->reg + NPCM_I2CFIF_CTS);
bus->ber_state = true;
npcm_i2c_clear_master_status(bus);

@@ -2237,6 +2258,10 @@ static irqreturn_t npcm_i2c_bus_irq(int irq, void *dev_id)
}
#endif
/* Clear status bits for spurious interrupts */
+ if (bus->fifo_use && FIELD_GET(NPCM_I2CFIF_CTS_SLVRSTR,
+ ioread8(bus->reg + NPCM_I2CFIF_CTS))) {
+ npcm_i2c_irq_handle_ab_slvrstr(bus);
+ }
npcm_i2c_clear_master_status(bus);

return IRQ_HANDLED;
@@ -2487,6 +2512,7 @@ static void npcm_i2c_init_debugfs(struct platform_device *pdev,
debugfs_create_u64("rec_fail_cnt", 0444, bus->adap.debugfs, &bus->rec_fail_cnt);
debugfs_create_u64("timeout_cnt", 0444, bus->adap.debugfs, &bus->timeout_cnt);
debugfs_create_u64("tx_complete_cnt", 0444, bus->adap.debugfs, &bus->tx_complete_cnt);
+ debugfs_create_u64("ab_slvrstr_cnt", 0444, bus->adap.debugfs, &bus->ab_slvrstr_cnt);
}

static int npcm_i2c_probe_bus(struct platform_device *pdev)
--
2.34.1