Skip to content

Commit 2f3a082

Browse files
Sowjanya Komatineniwsakernel
authored andcommitted
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>
1 parent bc1c204 commit 2f3a082

1 file changed

Lines changed: 21 additions & 1 deletion

File tree

drivers/i2c/busses/i2c-tegra.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,8 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned int reg)
326326
/* read back register to make sure that register writes completed */
327327
if (reg != I2C_TX_FIFO)
328328
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
329+
else if (i2c_dev->is_vi)
330+
readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, I2C_INT_STATUS));
329331
}
330332

331333
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,
339341
writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
340342
}
341343

344+
static void i2c_writesl_vi(struct tegra_i2c_dev *i2c_dev, void *data,
345+
unsigned int reg, unsigned int len)
346+
{
347+
u32 *data32 = data;
348+
349+
/*
350+
* VI I2C controller has known hardware bug where writes get stuck
351+
* when immediate multiple writes happen to TX_FIFO register.
352+
* Recommended software work around is to read I2C register after
353+
* each write to TX_FIFO register to flush out the data.
354+
*/
355+
while (len--)
356+
i2c_writel(i2c_dev, *data32++, reg);
357+
}
358+
342359
static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
343360
unsigned int reg, unsigned int len)
344361
{
@@ -811,7 +828,10 @@ static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
811828
i2c_dev->msg_buf_remaining = buf_remaining;
812829
i2c_dev->msg_buf = buf + words_to_transfer * BYTES_PER_FIFO_WORD;
813830

814-
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
831+
if (i2c_dev->is_vi)
832+
i2c_writesl_vi(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
833+
else
834+
i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
815835

816836
buf += words_to_transfer * BYTES_PER_FIFO_WORD;
817837
}

0 commit comments

Comments
 (0)