Skip to content

Commit 285df99

Browse files
akemnadeAndi Shyti
authored andcommitted
i2c: omap: fix IRQ storms
On the GTA04A5 writing a reset command to the gyroscope causes IRQ storms because NACK IRQs are enabled and therefore triggered but not acked. Sending a reset command to the gyroscope by i2cset 1 0x69 0x14 0xb6 with an additional debug print in the ISR (not the thread) itself causes [ 363.353515] i2c i2c-1: ioctl, cmd=0x720, arg=0xbe801b00 [ 363.359039] omap_i2c 48072000.i2c: addr: 0x0069, len: 2, flags: 0x0, stop: 1 [ 363.366180] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x1110) [ 363.371673] omap_i2c 48072000.i2c: IRQ (ISR = 0x0010) [ 363.376892] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) [ 363.382263] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) [ 363.387664] omap_i2c 48072000.i2c: IRQ LL (ISR = 0x0102) repeating till infinity [...] (0x2 = NACK, 0x100 = Bus free, which is not enabled) Apparently no other IRQ bit gets set, so this stalls. Do not ignore enabled interrupts and make sure they are acked. If the NACK IRQ is not needed, it should simply not enabled, but according to the above log, caring about it is necessary unless the Bus free IRQ is enabled and handled. The assumption that is will always come with a ARDY IRQ, which was the idea behind ignoring it, proves wrong. It is true for simple reads from an unused address. To still avoid the i2cdetect trouble which is the reason for commit c770657 ("i2c: omap: Fix standard mode false ACK readings"), avoid doing much about NACK in omap_i2c_xfer_data() which is used by both IRQ mode and polling mode, so also the false detection fix is extended to polling usage and IRQ storms are avoided. By changing this, the hardirq handler is not needed anymore to filter stuff. The mentioned gyro reset now just causes a -ETIMEDOUT instead of hanging the system. Fixes: c770657 ("i2c: omap: Fix standard mode false ACK readings"). CC: stable@kernel.org Signed-off-by: Andreas Kemnade <andreas@kemnade.info> Tested-by: Nishanth Menon <nm@ti.com> Reviewed-by: Aniket Limaye <a-limaye@ti.com> Signed-off-by: Andi Shyti <andi.shyti@kernel.org> Link: https://lore.kernel.org/r/20250228140420.379498-1-andreas@kemnade.info
1 parent 80e54e8 commit 285df99

File tree

1 file changed

+7
-19
lines changed

1 file changed

+7
-19
lines changed

drivers/i2c/busses/i2c-omap.c

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,23 +1048,6 @@ static int omap_i2c_transmit_data(struct omap_i2c_dev *omap, u8 num_bytes,
10481048
return 0;
10491049
}
10501050

1051-
static irqreturn_t
1052-
omap_i2c_isr(int irq, void *dev_id)
1053-
{
1054-
struct omap_i2c_dev *omap = dev_id;
1055-
irqreturn_t ret = IRQ_HANDLED;
1056-
u16 mask;
1057-
u16 stat;
1058-
1059-
stat = omap_i2c_read_reg(omap, OMAP_I2C_STAT_REG);
1060-
mask = omap_i2c_read_reg(omap, OMAP_I2C_IE_REG) & ~OMAP_I2C_STAT_NACK;
1061-
1062-
if (stat & mask)
1063-
ret = IRQ_WAKE_THREAD;
1064-
1065-
return ret;
1066-
}
1067-
10681051
static int omap_i2c_xfer_data(struct omap_i2c_dev *omap)
10691052
{
10701053
u16 bits;
@@ -1095,8 +1078,13 @@ static int omap_i2c_xfer_data(struct omap_i2c_dev *omap)
10951078
}
10961079

10971080
if (stat & OMAP_I2C_STAT_NACK) {
1098-
err |= OMAP_I2C_STAT_NACK;
1081+
omap->cmd_err |= OMAP_I2C_STAT_NACK;
10991082
omap_i2c_ack_stat(omap, OMAP_I2C_STAT_NACK);
1083+
1084+
if (!(stat & ~OMAP_I2C_STAT_NACK)) {
1085+
err = -EAGAIN;
1086+
break;
1087+
}
11001088
}
11011089

11021090
if (stat & OMAP_I2C_STAT_AL) {
@@ -1472,7 +1460,7 @@ omap_i2c_probe(struct platform_device *pdev)
14721460
IRQF_NO_SUSPEND, pdev->name, omap);
14731461
else
14741462
r = devm_request_threaded_irq(&pdev->dev, omap->irq,
1475-
omap_i2c_isr, omap_i2c_isr_thread,
1463+
NULL, omap_i2c_isr_thread,
14761464
IRQF_NO_SUSPEND | IRQF_ONESHOT,
14771465
pdev->name, omap);
14781466

0 commit comments

Comments
 (0)