#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
/* 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)
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
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);
/* 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);
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;