summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorShinya Kuribayashi <shinya.kuribayashi@necel.com>2009-11-06 21:51:36 +0900
committerBen Dooks <ben-linux@fluff.org>2009-12-09 00:19:12 +0000
commit597fe310f16d8246eec856326aa497bfa1b5bfa3 (patch)
treec8093cf8803bfe3793c46edcea965f9583e35e93 /drivers/i2c
parent8f588e40c788e63756ca1028c253f9f663d7d1c5 (diff)
downloadlinux-597fe310f16d8246eec856326aa497bfa1b5bfa3.tar.gz
linux-597fe310f16d8246eec856326aa497bfa1b5bfa3.tar.bz2
linux-597fe310f16d8246eec856326aa497bfa1b5bfa3.zip
i2c-designware: Skip RX_FULL and TX_EMPTY bits on tx abort errors
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>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-designware.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c
index cb83671ff5fc..e6b1e6ece5d7 100644
--- a/drivers/i2c/busses/i2c-designware.c
+++ b/drivers/i2c/busses/i2c-designware.c
@@ -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);