i2c-designware: Skip RX_FULL and TX_EMPTY bits on tx abort errors
authorShinya Kuribayashi <shinya.kuribayashi@necel.com>
Fri, 6 Nov 2009 12:51:36 +0000 (21:51 +0900)
committerBen Dooks <ben-linux@fluff.org>
Wed, 9 Dec 2009 00:19:12 +0000 (00:19 +0000)
Suppose TX_ABRT occurs in the middle of processing i2c_msg msgs[], and
a STOP condition has already been generated on the bus.  In this case,
subsequent i2c_dw_xfer_msg() might initiate a new and unnecessary I2C
transaction, which we'd have to avoid.

Furthermore, anytime TX_ABRT is set, the contents of tx/rx buffers are
flushed, so we don't have to process RX_FULL and TX_EMPTY.

Disable interrupts, and skip them.

Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi@necel.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
drivers/i2c/busses/i2c-designware.c

index cb83671ff5fc026e71a598a1da602c5bc7016efe..e6b1e6ece5d7232fc569560ac34c6e3df8a400d5 100644 (file)
@@ -621,6 +621,13 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
        if (stat & DW_IC_INTR_TX_ABRT) {
                dev->cmd_err |= DW_IC_ERR_TX_ABRT;
                dev->status = STATUS_IDLE;
+
+               /*
+                * Anytime TX_ABRT is set, the contents of the tx/rx
+                * buffers are flushed.  Make sure to skip them.
+                */
+               writel(0, dev->base + DW_IC_INTR_MASK);
+               goto tx_aborted;
        }
 
        if (stat & DW_IC_INTR_RX_FULL)
@@ -635,6 +642,7 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
         * the current transmit status.
         */
 
+tx_aborted:
        if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err)
                complete(&dev->cmd_complete);