summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorAlexander Shishkin <virtuoso@slind.org>2010-05-11 20:35:17 +0200
committerBen Dooks <ben-linux@fluff.org>2010-05-20 01:18:59 +0200
commite9f59b9c9bc5730152b6a94c47dd90b730a07e35 (patch)
treeee00d5f5995a47dbb61d119967b4091a79c45580 /drivers/i2c
parentomap: i2c: make errata 1.153 workaround a separate function (diff)
downloadlinux-e9f59b9c9bc5730152b6a94c47dd90b730a07e35.tar.xz
linux-e9f59b9c9bc5730152b6a94c47dd90b730a07e35.zip
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: Alexander Shishkin <virtuoso@slind.org> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-omap.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ef73483efb84..00fd02ec1b65 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -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)
{
- 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)) {
omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY |
OMAP_I2C_STAT_XDR));
*err |= OMAP_I2C_STAT_XUDF;
return -ETIMEDOUT;
}
+
cpu_relax();
*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;
}