From c0be7da69f40c2d3e593227e1be46abdf7f97529 Mon Sep 17 00:00:00 2001 From: Seth Forshee Date: Wed, 12 Mar 2008 12:56:10 -0500 Subject: [PATCH] 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 --- drivers/i2c/busses/i2c-omap.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) 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; -- 2.41.1