diff options
| author | Shinya Kuribayashi <shinya.kuribayashi@necel.com> | 2009-11-06 07:51:36 -0500 |
|---|---|---|
| committer | Ben Dooks <ben-linux@fluff.org> | 2009-12-08 19:19:12 -0500 |
| commit | 597fe310f16d8246eec856326aa497bfa1b5bfa3 (patch) | |
| tree | c8093cf8803bfe3793c46edcea965f9583e35e93 | |
| parent | 8f588e40c788e63756ca1028c253f9f663d7d1c5 (diff) | |
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>
| -rw-r--r-- | drivers/i2c/busses/i2c-designware.c | 8 |
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) | |||
| 621 | if (stat & DW_IC_INTR_TX_ABRT) { | 621 | if (stat & DW_IC_INTR_TX_ABRT) { |
| 622 | dev->cmd_err |= DW_IC_ERR_TX_ABRT; | 622 | dev->cmd_err |= DW_IC_ERR_TX_ABRT; |
| 623 | dev->status = STATUS_IDLE; | 623 | dev->status = STATUS_IDLE; |
| 624 | |||
| 625 | /* | ||
| 626 | * Anytime TX_ABRT is set, the contents of the tx/rx | ||
| 627 | * buffers are flushed. Make sure to skip them. | ||
| 628 | */ | ||
| 629 | writel(0, dev->base + DW_IC_INTR_MASK); | ||
| 630 | goto tx_aborted; | ||
| 624 | } | 631 | } |
| 625 | 632 | ||
| 626 | if (stat & DW_IC_INTR_RX_FULL) | 633 | if (stat & DW_IC_INTR_RX_FULL) |
| @@ -635,6 +642,7 @@ static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) | |||
| 635 | * the current transmit status. | 642 | * the current transmit status. |
| 636 | */ | 643 | */ |
| 637 | 644 | ||
| 645 | tx_aborted: | ||
| 638 | if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) | 646 | if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) |
| 639 | complete(&dev->cmd_complete); | 647 | complete(&dev->cmd_complete); |
| 640 | 648 | ||
