aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses
diff options
context:
space:
mode:
authorKohtaro Hashimoto <hashi@ti.com>2012-07-20 13:15:34 +0300
committerZiyann <jaraidaniel@gmail.com>2014-10-01 12:59:56 +0200
commitf4956ba3d3e711336ac758988230a9799ec9c156 (patch)
tree5090db20a934f4bf34d904bf2d3ab67e86b8e30a /drivers/i2c/busses
parent8d3d031afd095564e349620288ef4e9206505e33 (diff)
downloadkernel_samsung_tuna-f4956ba3d3e711336ac758988230a9799ec9c156.zip
kernel_samsung_tuna-f4956ba3d3e711336ac758988230a9799ec9c156.tar.gz
kernel_samsung_tuna-f4956ba3d3e711336ac758988230a9799ec9c156.tar.bz2
OMAP: I2C: Wait till functional part of the I2C controller completely becomes valid
Bus busy status bit is not effective when functional part of the I2C controller is not valid, and bus busy detection in omap_i2c_wait_for_bb() will be skipped sometimes. So we should wait till functional part of the I2C controller completely becomes valid, after setting the I2Ci.I2C_CON[15] I2C_EN bit to 1. For doing that we have to wait till RDONE bit of SYSS register reach "1". For details see TRM, 23.1.4.3 HS I2C Software Reset. Change-Id: I989855d6cb2b1aa0098e11245dacb77583fe6647 Signed-off-by: Semen Protsenko <semen.protsenko@ti.com>
Diffstat (limited to 'drivers/i2c/busses')
-rwxr-xr-xdrivers/i2c/busses/i2c-omap.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index d451f11..a17fed4 100755
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -160,6 +160,9 @@ enum {
#define OMAP_I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense in */
#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */
+/* I2C System Status Register */
+#define OMAP_I2C_SYSS_RDONE BIT(0) /* Reset done */
+
/* Errata definitions */
#define I2C_OMAP_ERRATA_I207 (1 << 0)
#define I2C_OMAP3_1P153 (1 << 1)
@@ -338,6 +341,8 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
pm_runtime_get_sync(&pdev->dev);
if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ unsigned long delay;
+
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
@@ -345,6 +350,16 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate);
omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+ delay = jiffies + OMAP_I2C_TIMEOUT;
+ while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG)
+ & OMAP_I2C_SYSS_RDONE)) {
+ if (time_after(jiffies, delay)) {
+ dev_err(dev->dev, "omap i2c unidle timeout\n");
+ return;
+ }
+ cpu_relax();
+ }
}
dev->idle = 0;