mirror of
https://github.com/torvalds/linux.git
synced 2026-06-06 21:45:45 +02:00
i2c: tegra: Create i2c_writesl_vi() to use with VI I2C for filling TX FIFO
[ Upstream commit 2f3a0828d4 ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
6826f0b4a1
commit
40545c4dd9
|
|
@ -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