summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-designware-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-core.c')
-rw-r--r--drivers/i2c/busses/i2c-designware-core.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index f5258c205de5..94fd81875409 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -413,11 +413,23 @@ i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR);
while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) {
+ u32 cmd = 0;
+
+ /*
+ * If IC_EMPTYFIFO_HOLD_MASTER_EN is set we must
+ * manually set the stop bit. However, it cannot be
+ * detected from the registers so we set it always
+ * when writing/reading the last byte.
+ */
+ if (dev->msg_write_idx == dev->msgs_num - 1 &&
+ buf_len == 1)
+ cmd |= BIT(9);
+
if (msgs[dev->msg_write_idx].flags & I2C_M_RD) {
- dw_writel(dev, 0x100, DW_IC_DATA_CMD);
+ dw_writel(dev, cmd | 0x100, DW_IC_DATA_CMD);
rx_limit--;
} else
- dw_writel(dev, *buf++, DW_IC_DATA_CMD);
+ dw_writel(dev, cmd | *buf++, DW_IC_DATA_CMD);
tx_limit--; buf_len--;
}