|
@@ -87,10 +87,10 @@
|
|
|
#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_INTR_MASTER_MASK (DW_IC_INTR_DEFAULT_MASK | \
|
|
|
+ DW_IC_INTR_TX_EMPTY)
|
|
|
#define DW_IC_STATUS_ACTIVITY 0x1
|
|
|
|
|
|
#define DW_IC_SDA_HOLD_RX_SHIFT 16
|
|
@@ -202,6 +202,16 @@ static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void i2c_dw_configure_fifo_master(struct dw_i2c_dev *dev)
|
|
|
+{
|
|
|
+ /* Configure Tx/Rx FIFO threshold levels */
|
|
|
+ dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL);
|
|
|
+ dw_writel(dev, 0, DW_IC_RX_TL);
|
|
|
+
|
|
|
+ /* Configure the I2C master */
|
|
|
+ dw_writel(dev, dev->master_cfg, DW_IC_CON);
|
|
|
+}
|
|
|
+
|
|
|
static u32
|
|
|
i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset)
|
|
|
{
|
|
@@ -440,13 +450,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
|
|
|
"Hardware too old to adjust SDA hold time.\n");
|
|
|
}
|
|
|
|
|
|
- /* Configure Tx/Rx FIFO threshold levels */
|
|
|
- dw_writel(dev, dev->tx_fifo_depth / 2, DW_IC_TX_TL);
|
|
|
- dw_writel(dev, 0, DW_IC_RX_TL);
|
|
|
-
|
|
|
- /* Configure the I2C master */
|
|
|
- dw_writel(dev, dev->master_cfg , DW_IC_CON);
|
|
|
-
|
|
|
+ i2c_dw_configure_fifo_master(dev);
|
|
|
i2c_dw_release_lock(dev);
|
|
|
|
|
|
return 0;
|
|
@@ -511,7 +515,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
|
|
|
|
|
|
/* Clear and enable interrupts */
|
|
|
dw_readl(dev, DW_IC_CLR_INTR);
|
|
|
- dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
|
|
|
+ dw_writel(dev, DW_IC_INTR_MASTER_MASK, DW_IC_INTR_MASK);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -531,7 +535,7 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
|
|
|
u8 *buf = dev->tx_buf;
|
|
|
bool need_restart = false;
|
|
|
|
|
|
- intr_mask = DW_IC_INTR_DEFAULT_MASK;
|
|
|
+ intr_mask = DW_IC_INTR_MASTER_MASK;
|
|
|
|
|
|
for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) {
|
|
|
u32 flags = msgs[dev->msg_write_idx].flags;
|
|
@@ -881,22 +885,14 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Interrupt service routine. This gets called whenever an I2C interrupt
|
|
|
+ * Interrupt service routine. This gets called whenever an I2C master interrupt
|
|
|
* occurs.
|
|
|
*/
|
|
|
-static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
|
|
|
+static int i2c_dw_irq_handler_master(struct dw_i2c_dev *dev)
|
|
|
{
|
|
|
- struct dw_i2c_dev *dev = dev_id;
|
|
|
- u32 stat, enabled;
|
|
|
-
|
|
|
- enabled = dw_readl(dev, DW_IC_ENABLE);
|
|
|
- stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
|
|
|
- dev_dbg(dev->dev, "%s: enabled=%#x stat=%#x\n", __func__, enabled, stat);
|
|
|
- if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
|
|
|
- return IRQ_NONE;
|
|
|
+ u32 stat;
|
|
|
|
|
|
stat = i2c_dw_read_clear_intrbits(dev);
|
|
|
-
|
|
|
if (stat & DW_IC_INTR_TX_ABRT) {
|
|
|
dev->cmd_err |= DW_IC_ERR_TX_ABRT;
|
|
|
dev->status = STATUS_IDLE;
|
|
@@ -931,6 +927,22 @@ tx_aborted:
|
|
|
dw_writel(dev, stat, DW_IC_INTR_MASK);
|
|
|
}
|
|
|
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
|
|
|
+{
|
|
|
+ struct dw_i2c_dev *dev = dev_id;
|
|
|
+ u32 stat, enabled;
|
|
|
+
|
|
|
+ enabled = dw_readl(dev, DW_IC_ENABLE);
|
|
|
+ stat = dw_readl(dev, DW_IC_RAW_INTR_STAT);
|
|
|
+ dev_dbg(dev->dev, "enabled=%#x stat=%#x\n", enabled, stat);
|
|
|
+ if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY))
|
|
|
+ return IRQ_NONE;
|
|
|
+
|
|
|
+ i2c_dw_irq_handler_master(dev);
|
|
|
+
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
|
|