Commit e9f59b9c authored by Alexander Shishkin's avatar Alexander Shishkin Committed by Ben Dooks

omap: i2c: add a timeout to the busy waiting

The errata 1.153 workaround is busy waiting on XUDF bit in interrupt
context, which may lead to kernel hangs. The problem can be reproduced
by running the bus with wrong (too high) speed.
Signed-off-by: default avatarAlexander Shishkin <virtuoso@slind.org>
Signed-off-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarBen Dooks <ben-linux@fluff.org>
parent 2dd151ab
...@@ -763,17 +763,25 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id) ...@@ -763,17 +763,25 @@ omap_i2c_rev1_isr(int this_irq, void *dev_id)
*/ */
static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err)
{ {
while (!(*stat & OMAP_I2C_STAT_XUDF)) { unsigned long timeout = 10000;
while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) {
if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) {
omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY | omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
OMAP_I2C_STAT_XDR)); OMAP_I2C_STAT_XDR));
*err |= OMAP_I2C_STAT_XUDF; *err |= OMAP_I2C_STAT_XUDF;
return -ETIMEDOUT; return -ETIMEDOUT;
} }
cpu_relax(); cpu_relax();
*stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); *stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG);
} }
if (!timeout) {
dev_err(dev->dev, "timeout waiting on XUDF bit\n");
return 0;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment