Thread (12 messages) 12 messages, 4 authors, 2021-01-12

Re: [PATCH v1] i2c: tegra: Fix i2c_writesl() to use writel() instead of writesl()

From: Thierry Reding <hidden>
Date: 2021-01-11 08:32:53
Also in: linux-i2c, lkml

On Mon, Oct 19, 2020 at 09:03:54PM -0700, Sowjanya Komatineni wrote:
VI I2C don't have DMA support and uses PIO mode all the time.

Current driver uses writesl() to fill TX FIFO based on available
empty slots and with this seeing strange silent hang during any I2C
register access after filling TX FIFO with 8 words.

Using writel() followed by i2c_readl() in a loop to write all words
to TX FIFO instead of using writesl() helps for large transfers in
PIO mode.

So, this patch updates i2c_writesl() API to use writel() in a loop
instead of writesl().

Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
---
 drivers/i2c/busses/i2c-tegra.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
Hi Wolfram,

after discussing a bit more with Sowjanya, I don't think we're going to
have a better solution than this. It should be fairly harmless to have
this additional flushing read of the interrupt status register because
the reads don't have any side-effects (the register is write-1-to-clear)
and these write loops don't happen very often (or when they do we tend
to use DMA anyway), so:

Acked-by: Thierry Reding <redacted>

I did notice that for some reason Sowjanya hadn't listed you as a
recipient, so perhaps you don't have this anywhere in your inbox. I've
quoted the patch fully for reference below and the patchwork link for
this is:

	https://patchwork.ozlabs.org/project/linux-i2c/patch/1603166634-13639-1-git-send-email-skomatineni@nvidia.com/

If you'd prefer to have this in your inbox for proper review, please
let us know so that Sowjanya can resend this.

Thanks,
Thierry
quoted hunk ↗ jump to hunk
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 6f08c0c..274bf3a 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -333,10 +333,13 @@ static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned int reg)
 	return readl_relaxed(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
 }
 
-static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
+static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, u32 *data,
 			unsigned int reg, unsigned int len)
 {
-	writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+	while (len--) {
+		writel(*data++, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+		i2c_readl(i2c_dev, I2C_INT_STATUS);
+	}
 }
 
 static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
@@ -811,7 +814,7 @@ 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);
+		i2c_writesl(i2c_dev, (u32 *)buf, I2C_TX_FIFO, words_to_transfer);
 
 		buf += words_to_transfer * BYTES_PER_FIFO_WORD;
 	}
-- 
2.7.4

Attachments

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help