@@ -25,7 +25,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
@@ -938,8 +937,9 @@ static int tegra_i2c_issue_bus_clear(struct tegra_i2c_dev *i2c_dev)
i2c_writel(i2c_dev, reg, I2C_BUS_CLEAR_CNFG);
tegra_i2c_unmask_irq(i2c_dev, I2C_INT_BUS_CLR_DONE);
- time_left = wait_for_completion_timeout(&i2c_dev->msg_complete,
- TEGRA_I2C_TIMEOUT);
+ time_left = wait_for_completion_timeout(
+ &i2c_dev->msg_complete,
+ msecs_to_jiffies(50));
if (time_left == 0) {
dev_err(i2c_dev->dev, "timed out for bus clear\n");
return -ETIMEDOUT;
@@ -966,6 +966,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
u32 *buffer = NULL;
int err = 0;
bool dma = false;
+ u16 xfer_time = 100;
tegra_i2c_flush_fifos(i2c_dev);
@@ -984,6 +985,13 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
dma = (xfer_size > I2C_PIO_MODE_MAX_LEN) && i2c_dev->dma_buf;
i2c_dev->is_curr_dma_xfer = dma;
+ /*
+ * 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;
@@ -1091,7 +1099,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");
@@ -1117,8 +1125,9 @@ 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);
+ time_left = wait_for_completion_timeout(
+ &i2c_dev->msg_complete,
+ msecs_to_jiffies(xfer_time));
tegra_i2c_mask_irq(i2c_dev, int_mask);
if (time_left == 0) {
@@ -1375,6 +1384,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;