[PATCH] OMAP3 : Fix I2C lockup during timeout/error cases

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Current OMAP3 I2C driver code does not follow the correct sequence for soft
reset. Due to this, lock up issues are reported during timeout/error cases.

This patch fixes above issue by disabling I2C controller as per OMAP3430 TRM
for soft reset. As per TRM, I2C controller needs to be disabled as a first
step during soft reset.

Here is correct soft reset sequence:
1. Ensure that the module is disabled
(clear the I2Ci.I2C_CON[15] I2C_EN bit to 0).
2. Set the I2Ci.I2C_SYSC[1] SRST bit to 1.
3. Enable the module by setting I2Ci.I2C_CON[15] I2C_EN bit to 1.
4. Check the I2Ci.I2C_SYSS[0] RDONE bit until it is set to 1 to
indicate the software reset is complete.

Signed-off-by: Manjunatha GK <manjugk@xxxxxx>
---
 drivers/i2c/busses/i2c-omap.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)
 mode change 100644 => 100755 drivers/i2c/busses/i2c-omap.c

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
old mode 100644
new mode 100755
index 827da08..2f869dc
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -265,6 +265,21 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	unsigned long internal_clk = 0;
 
 	if (dev->rev >= OMAP_I2C_REV_2) {
+		/* Disable I2C controller before soft reset */
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+			omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
+				~(OMAP_I2C_CON_EN));
+		timeout = jiffies + OMAP_I2C_TIMEOUT;
+		while ((omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) &
+			OMAP_I2C_CON_EN)) {
+			if (time_after(jiffies, timeout)) {
+				dev_warn(dev->dev, "timeout waiting "
+					"for controller reset\n");
+				return -ETIMEDOUT;
+			}
+			schedule();
+		}
+
 		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK);
 		/* For some reason we need to set the EN bit before the
 		 * reset done bit gets set. */
@@ -277,7 +292,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 						"for controller reset\n");
 				return -ETIMEDOUT;
 			}
-			msleep(1);
+			schedule();
 		}
 
 		/* SYSC register is cleared by the reset; rewrite it */
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux