diff options
author | Sowjanya Komatineni <skomatineni@nvidia.com> | 2021-01-12 11:02:41 -0800 |
---|---|---|
committer | Wolfram Sang <wsa@kernel.org> | 2021-01-17 12:24:21 +0100 |
commit | 2f3a0828d46166d4e7df227479ed31766ee67e4a (patch) | |
tree | 241ada0caaf3adbe63a23a9dd81e0d3a3f63da29 /drivers | |
parent | bc1c2048abbe3c3074b4de91d213595c57741a6b (diff) | |
download | linux-stable-2f3a0828d46166d4e7df227479ed31766ee67e4a.tar.gz linux-stable-2f3a0828d46166d4e7df227479ed31766ee67e4a.tar.bz2 linux-stable-2f3a0828d46166d4e7df227479ed31766ee67e4a.zip |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/busses/i2c-tegra.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 0727383f4940..8b113ae32dc7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -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; } |