Skip to content

Commit

Permalink
i2c: tegra: update transfer timeout
Browse files Browse the repository at this point in the history
Tegra194 allows max of 64K bytes and Tegra186 and prior allows
max of 4K bytes of transfer per packet.

one sec timeout is not enough for transfers more than 10K bytes
at STD bus rate.

This patch updates I2C transfer timeout based on the transfer size
and I2C bus rate to allow enough time during max transfer size at
lower bus speed.

Acked-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Dmitry Osipenko <digetx@gmail.com>
Signed-off-by: Sowjanya Komatineni <skomatineni@nvidia.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Sowjanya Komatineni authored and Wolfram Sang committed Feb 14, 2019
1 parent 86c92b9 commit 80d4062
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions drivers/i2c/busses/i2c-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include <linux/pm_runtime.h>
#include <linux/reset.h>

#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000))
#define BYTES_PER_FIFO_WORD 4

#define I2C_CNFG 0x000
Expand Down Expand Up @@ -936,7 +935,7 @@ static int tegra_i2c_issue_bus_clear(struct i2c_adapter *adap)
tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);

time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
TEGRA_I2C_TIMEOUT);
msecs_to_jiffies(50));
if (time_left == 0) {
dev_err(i2c_dev->dev, "timed out for bus clear\n");
return -ETIMEDOUT;
Expand All @@ -963,6 +962,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
u32 *buffer = NULL;
int err = 0;
bool dma;
u16 xfer_time = 100;

tegra_i2c_flush_fifos(i2c_dev);

Expand All @@ -982,6 +982,12 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
i2c_dev->dma_buf;
tegra_i2c_config_fifo_trig(i2c_dev, xfer_size);
dma = i2c_dev->is_curr_dma_xfer;
/*
* Transfer time in mSec = Total bits / transfer rate
* Total bits = 9 bits per byte (including ACK bit) + Start & stop bits
*/
xfer_time += DIV_ROUND_CLOSEST(((xfer_size * 9) + 2) * MSEC_PER_SEC,
i2c_dev->bus_clk_rate);
spin_lock_irqsave(&i2c_dev->xfer_lock, flags);

int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
Expand Down Expand Up @@ -1085,7 +1091,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,

time_left = wait_for_completion_timeout(
&i2c_dev->dma_complete,
TEGRA_I2C_TIMEOUT);
msecs_to_jiffies(xfer_time));
if (time_left == 0) {
dev_err(i2c_dev->dev, "DMA transfer timeout\n");
dmaengine_terminate_sync(i2c_dev->msg_read ?
Expand All @@ -1111,7 +1117,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
}

time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
TEGRA_I2C_TIMEOUT);
msecs_to_jiffies(xfer_time));
tegra_i2c_mask_irq(i2c_dev, int_mask);

if (time_left == 0) {
Expand Down Expand Up @@ -1390,6 +1396,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
i2c_dev->div_clk = div_clk;
i2c_dev->adapter.algo = &tegra_i2c_algo;
i2c_dev->adapter.retries = 1;
i2c_dev->adapter.timeout = 6 * HZ;
i2c_dev->irq = irq;
i2c_dev->cont_id = pdev->id;
i2c_dev->dev = &pdev->dev;
Expand Down

0 comments on commit 80d4062

Please sign in to comment.