diff options
author | Kohtaro Hashimoto <hashi@ti.com> | 2012-07-20 13:15:34 +0300 |
---|---|---|
committer | Ziyann <jaraidaniel@gmail.com> | 2014-10-01 12:59:56 +0200 |
commit | f4956ba3d3e711336ac758988230a9799ec9c156 (patch) | |
tree | 5090db20a934f4bf34d904bf2d3ab67e86b8e30a /drivers/i2c/busses | |
parent | 8d3d031afd095564e349620288ef4e9206505e33 (diff) | |
download | kernel_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-x | drivers/i2c/busses/i2c-omap.c | 15 |
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; |