diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2009-12-09 15:21:12 +0100 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2009-12-09 15:24:57 +0100 |
commit | 45245181f9e4c3774be3a34a97553abbd5aa95f2 (patch) | |
tree | d31a2587106571bbd9ed17b28ed46df7aab3ac57 | |
parent | 90e3f0516d19c934d554f94561118fde405da6a1 (diff) | |
download | barebox-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.c | 20 |
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)) { |