i2c: tegra: Create i2c_writesl_vi() to use with VI I2C for filling TX FIFO
VI I2C controller has known hardware bug where immediate multiple writes to TX_FIFO register gets stuck. Recommended software work around is to read I2C register after each write to TX_FIFO register to flush out the data. This patch implements this work around for VI I2C controller. Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com> Reviewed-by: Dmitry Osipenko <digetx@gmail.com> Acked-by: Thierry Reding <treding@nvidia.com> Signed-off-by: Wolfram Sang <wsa@kernel.org>
This commit is contained in:
parent
bc1c2048ab
commit
2f3a0828d4
@ -326,6 +326,8 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
|
||||
/* read back register to make sure that register writes completed */
|
||||
if (reg != I2C_TX_FIFO)
|
||||
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
|
||||
else if (i2c_dev->is_vi)
|
||||
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
|
||||
}
|
||||
|
||||
static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
|
||||
@ -339,6 +341,21 @@ static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
|
||||
writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
|
||||
}
|
||||
|
||||
static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
|
||||
unsigned int reg, unsigned int len)
|
||||
{
|
||||
u32 *data32 = data;
|
||||
|
||||
/*
|
||||
* VI I2C controller has known hardware bug where writes get stuck
|
||||
* when immediate multiple writes happen to TX_FIFO register.
|
||||
* Recommended software work around is to read I2C register after
|
||||
* each write to TX_FIFO register to flush out the data.
|
||||
*/
|
||||
while (len--)
|
||||
i2c_writel(i2c_dev, *data32++, reg);
|
||||
}
|
||||
|
||||
static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
|
||||
unsigned int reg, unsigned int len)
|
||||
{
|
||||
@ -811,7 +828,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
|
||||
i2c_dev->msg_buf_remaining = buf_remaining;
|
||||
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
|
||||
|
||||
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
|
||||
if (i2c_dev->is_vi)
|
||||
i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
|
||||
else
|
||||
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
|
||||
|
||||
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user