aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorKohtaro Hashimoto <hashi@ti.com>2012-07-20 13:15:34 +0300
committerDmytro Kedrovskyi <x0169235@ti.com>2012-07-23 19:38:11 +0300
commit6e786c6b962f498457988246f7b8c13dad72da0e (patch)
tree0171a9e495057ab70c11d79d38d843cc161a1637 /drivers/i2c
parentf4ed88e63d0508b8b49e21123dc184097d8df1f2 (diff)
downloadkernel_samsung_espresso10-6e786c6b962f498457988246f7b8c13dad72da0e.zip
kernel_samsung_espresso10-6e786c6b962f498457988246f7b8c13dad72da0e.tar.gz
kernel_samsung_espresso10-6e786c6b962f498457988246f7b8c13dad72da0e.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')
-rw-r--r--drivers/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 c6ae218..496946d 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -163,6 +163,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)
@@ -303,6 +306,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);
@@ -310,6 +315,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;