|
@@ -90,6 +90,11 @@
|
|
|
#define DW_IC_INTR_START_DET 0x400
|
|
|
#define DW_IC_INTR_GEN_CALL 0x800
|
|
|
|
|
|
+#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
|
|
|
+ DW_IC_INTR_TX_EMPTY | \
|
|
|
+ DW_IC_INTR_TX_ABRT | \
|
|
|
+ DW_IC_INTR_STOP_DET)
|
|
|
+
|
|
|
#define DW_IC_STATUS_ACTIVITY 0x1
|
|
|
|
|
|
#define DW_IC_ERR_TX_ABRT 0x1
|
|
@@ -347,13 +352,16 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
|
|
|
|
|
/* Enable the adapter */
|
|
|
writel(1, dev->base + DW_IC_ENABLE);
|
|
|
+
|
|
|
+ /* Enable interrupts */
|
|
|
+ writel(DW_IC_INTR_DEFAULT_MASK, dev->base + DW_IC_INTR_MASK);
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Initiate low level master read/write transaction.
|
|
|
- * This function is called from i2c_dw_xfer when starting a transfer.
|
|
|
- * This function is also called from i2c_dw_isr to continue a transfer
|
|
|
- * that is longer than the size of the TX FIFO.
|
|
|
+ * Initiate (and continue) low level master read/write transaction.
|
|
|
+ * This function is only called from i2c_dw_isr, and pumping i2c_msg
|
|
|
+ * messages into the tx buffer. Even if the size of i2c_msg data is
|
|
|
+ * longer than the size of the tx buffer, it handles everything.
|
|
|
*/
|
|
|
static void
|
|
|
i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
|
@@ -365,7 +373,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
|
|
u32 buf_len = dev->tx_buf_len;
|
|
|
u8 *buf = dev->tx_buf;;
|
|
|
|
|
|
- intr_mask = DW_IC_INTR_STOP_DET | DW_IC_INTR_TX_ABRT | DW_IC_INTR_RX_FULL;
|
|
|
+ intr_mask = DW_IC_INTR_DEFAULT_MASK;
|
|
|
|
|
|
for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
|
|
|
/* if target address has changed, we need to
|
|
@@ -405,11 +413,12 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
|
|
|
|
|
if (buf_len > 0) {
|
|
|
/* more bytes to be written */
|
|
|
- intr_mask |= DW_IC_INTR_TX_EMPTY;
|
|
|
dev->status |= STATUS_WRITE_IN_PROGRESS;
|
|
|
break;
|
|
|
- } else
|
|
|
+ } else {
|
|
|
dev->status &= ~STATUS_WRITE_IN_PROGRESS;
|
|
|
+ intr_mask &= ~DW_IC_INTR_TX_EMPTY;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
writel(intr_mask, dev->base + DW_IC_INTR_MASK);
|
|
@@ -479,7 +488,6 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
|
|
|
|
|
|
/* start the transfers */
|
|
|
i2c_dw_xfer_init(dev);
|
|
|
- i2c_dw_xfer_msg(dev);
|
|
|
|
|
|
/* wait for tx to complete */
|
|
|
ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ);
|
|
@@ -687,7 +695,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
|
|
|
i2c_dw_init(dev);
|
|
|
|
|
|
writel(0, dev->base + DW_IC_INTR_MASK); /* disable IRQ */
|
|
|
- r = request_irq(dev->irq, i2c_dw_isr, 0, pdev->name, dev);
|
|
|
+ r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev);
|
|
|
if (r) {
|
|
|
dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
|
|
|
goto err_iounmap;
|