summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2009-12-09 15:21:12 +0100
committerMarc Kleine-Budde <mkl@pengutronix.de>2009-12-09 15:24:57 +0100
commit45245181f9e4c3774be3a34a97553abbd5aa95f2 (patch)
treed31a2587106571bbd9ed17b28ed46df7aab3ac57
parent90e3f0516d19c934d554f94561118fde405da6a1 (diff)
downloadbarebox-45245181f9e4c3774be3a34a97553abbd5aa95f2.tar.gz
barebox-45245181f9e4c3774be3a34a97553abbd5aa95f2.tar.xz
i2c-imx: fix low bitrate problem
loop in i2c_imx_acked() in low bit rates it takes some time until the ACK comes in. Also add a delay before polling for bus not busy in i2c_imx_read. Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
-rw-r--r--drivers/i2c/i2c-imx.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/i2c/i2c-imx.c b/drivers/i2c/i2c-imx.c
index 14d5260443..c2a38ee200 100644
--- a/drivers/i2c/i2c-imx.c
+++ b/drivers/i2c/i2c-imx.c
@@ -205,10 +205,18 @@ static int i2c_imx_wait_iif(struct i2c_adapter *adapter)
static int i2c_imx_acked(struct i2c_adapter *adapter)
{
unsigned long base = adapter->dev->map_base;
+ uint64_t start;
- if (readb(base + IMX_I2C_I2SR) & I2SR_RXAK) {
- dev_notice(adapter->dev, "<%s> No ACK\n", __func__);
- return -EIO;
+ start = get_time_ns();
+ while (1) {
+ unsigned int reg = readb(base + IMX_I2C_I2SR);
+ if (!(reg & I2SR_RXAK))
+ break;
+
+ if (is_timeout(start, MSECOND)) {
+ dev_err(adapter->dev, "<%s> No ACK\n", __func__);
+ return -EIO;
+ }
}
return 0;
@@ -398,6 +406,12 @@ static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs)
temp = readb(base + IMX_I2C_I2CR);
temp &= ~(I2CR_MSTA | I2CR_MTX);
writeb(temp, base + IMX_I2C_I2CR);
+
+ /*
+ * adding this delay helps on low bitrates
+ */
+ udelay(i2c_imx->disable_delay);
+
i2c_imx_bus_busy(adapter, 0);
i2c_imx->stopped = 1;
} else if (i == (msgs->len - 2)) {