@@ -453,6 +453,18 @@ void __i2c_dw_disable(struct dw_i2c_dev *dev)
abort_needed = raw_intr_stats & DW_IC_INTR_MST_ON_HOLD;
if (abort_needed) {
+ if (!enable) {
+ regmap_write(dev->map, DW_IC_ENABLE, DW_IC_ENABLE_ENABLE);
+ enable |= DW_IC_ENABLE_ENABLE;
+
+ /*
+ * Wait two ic_clk delay when enabling the i2c to ensure ENABLE bit
+ * is already set by the driver (for 400KHz this is 25us)
+ * as described in the DesignWare I2C databook.
+ */
+ fsleep(25);
+ }
+
regmap_write(dev->map, DW_IC_ENABLE, enable | DW_IC_ENABLE_ABORT);
ret = regmap_read_poll_timeout(dev->map, DW_IC_ENABLE, enable,
!(enable & DW_IC_ENABLE_ABORT), 10,
@@ -253,6 +253,26 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
__i2c_dw_write_intr_mask(dev, DW_IC_INTR_MASTER_MASK);
}
+static bool i2c_dw_is_master_idling(struct dw_i2c_dev *dev)
+{
+ u32 status;
+ int ret;
+
+ regmap_read(dev->map, DW_IC_STATUS, &status);
+ if (!(status & DW_IC_STATUS_MASTER_ACTIVITY))
+ return true;
+
+ ret = regmap_read_poll_timeout(dev->map, DW_IC_STATUS, status,
+ !(status & DW_IC_STATUS_MASTER_ACTIVITY),
+ 1100, 20000);
+ if (ret) {
+ dev_err(dev->dev, "i2c master controller not idle %d\n", ret);
+ return false;
+ }
+
+ return true;
+}
+
static int i2c_dw_check_stopbit(struct dw_i2c_dev *dev)
{
u32 val;
@@ -796,7 +816,8 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
* additional interrupts are a hardware bug or this driver doesn't
* handle them correctly yet.
*/
- __i2c_dw_disable_nowait(dev);
+ if (i2c_dw_is_master_idling(dev))
+ __i2c_dw_disable_nowait(dev);
if (dev->msg_err) {
ret = dev->msg_err;