Skip to content

Commit

Permalink
i2c-designware: always set the STOP bit after last byte
Browse files Browse the repository at this point in the history
If IC_EMPTYFIFO_HOLD_MASTER_EN is set to one, the DesignWare I2C controller
doesn't generate STOP on the bus when the FIFO is empty. This violates the
rules of Linux I2C stack as it requires that the STOP is issued once the
i2c_transfer() is finished.

However, there is no way to detect this from the hardware registers, so we
must make sure that the STOP bit is always set once the last byte of the
last message is transferred.

This patch is based on the work of Dirk Brandewie.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
  • Loading branch information
Mika Westerberg authored and Wolfram Sang committed Jan 28, 2013
1 parent 5c38dc8 commit 17a76b4
Showing 1 changed file with 14 additions and 2 deletions.
16 changes: 14 additions & 2 deletions drivers/i2c/busses/i2c-designware-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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--;
}

Expand Down

0 comments on commit 17a76b4

Please sign in to comment.