From: Seth Forshee Date: Wed, 12 Mar 2008 17:56:10 +0000 (-0500) Subject: I2C: Fix OMAP I2C status register handling in IRQ processing X-Git-Tag: v2.6.25-omap1~93 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=c0be7da69f40c2d3e593227e1be46abdf7f97529;p=linux-2.6-omap-h63xx.git I2C: Fix OMAP I2C status register handling in IRQ processing The IRQ handler in omap-i2c.c can sometimes clear status bits without actually processing them. In particular, error status bits will be ignored if any of the ARDY, RRDY, RDR, XRDY, or XDR bits are concurrently set. Signed-off-by: Seth Forshee Signed-off-by: Tony Lindgren --- diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 4777466437e..a16d513d854 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -590,7 +590,7 @@ omap_i2c_isr(int this_irq, void *dev_id) struct omap_i2c_dev *dev = dev_id; u16 bits; u16 stat, w; - int count = 0; + int err, count = 0; if (dev->idle) return IRQ_NONE; @@ -605,10 +605,19 @@ omap_i2c_isr(int this_irq, void *dev_id) omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); - if (stat & OMAP_I2C_STAT_ARDY) { - omap_i2c_complete_cmd(dev, 0); - continue; + err = 0; + if (stat & OMAP_I2C_STAT_NACK) { + err |= OMAP_I2C_STAT_NACK; + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, + OMAP_I2C_CON_STP); } + if (stat & OMAP_I2C_STAT_AL) { + dev_err(dev->dev, "Arbitration lost\n"); + err |= OMAP_I2C_STAT_AL; + } + if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | + OMAP_I2C_STAT_AL)) + omap_i2c_complete_cmd(dev, err); if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { u8 num_bytes = 1; if (dev->fifo_size) { @@ -640,7 +649,6 @@ omap_i2c_isr(int this_irq, void *dev_id) } } omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)); - continue; } if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) { u8 num_bytes = 1; @@ -674,7 +682,6 @@ omap_i2c_isr(int this_irq, void *dev_id) omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); } omap_i2c_ack_stat(dev, stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); - continue; } if (stat & OMAP_I2C_STAT_ROVR) { dev_err(dev->dev, "Receive overrun\n"); @@ -684,15 +691,6 @@ omap_i2c_isr(int this_irq, void *dev_id) dev_err(dev->dev, "Transmit overflow\n"); dev->cmd_err |= OMAP_I2C_STAT_XUDF; } - if (stat & OMAP_I2C_STAT_NACK) { - omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK); - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, - OMAP_I2C_CON_STP); - } - if (stat & OMAP_I2C_STAT_AL) { - dev_err(dev->dev, "Arbitration lost\n"); - omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL); - } } return count ? IRQ_HANDLED : IRQ_NONE;