summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJan Luebbe <jluebbe@debian.org>2015-07-30 16:52:10 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2015-08-20 07:47:15 +0200
commit4f32ba9fcbbdcbfdb6dec75fe70ba8998a82e3ca (patch)
tree937f12684e7516a1614cf588e94fa61c85435c87 /drivers/i2c
parentabcbcfca3abbebb2cab28fdada7daf135cc6b33d (diff)
downloadbarebox-4f32ba9fcbbdcbfdb6dec75fe70ba8998a82e3ca.tar.gz
barebox-4f32ba9fcbbdcbfdb6dec75fe70ba8998a82e3ca.tar.xz
i2c: algo-bit: check if the bus is busy
If we have a timeout while waiting, try to recover. Signed-off-by: Jan Luebbe <jluebbe@debian.org> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 62040cc4e4..2563c0d25a 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -117,6 +117,31 @@ done:
return 0;
}
+static int wait_busy(struct i2c_algo_bit_data *adap)
+{
+ uint64_t start;
+
+ if (sclhi(adap) < 0)
+ return -ETIMEDOUT;
+
+ start = get_time_ns();
+ while (!getsda(adap)) {
+ if (is_timeout(start, adap->timeout_ms * MSECOND)) {
+ if (getsda(adap))
+ break;
+ return -ETIMEDOUT;
+ }
+ }
+#ifdef DEBUG
+ if ((get_time_ns() - start) < 10000)
+ pr_debug("i2c-algo-bit: needed %u usecs for SDA to go "
+ "high\n", (unsigned int)(get_time_ns() - start) /
+ 1000);
+#endif
+
+ udelay(adap->udelay);
+ return 0;
+}
/* --- other auxiliary functions -------------------------------------- */
static void i2c_start(struct i2c_algo_bit_data *adap)
@@ -512,6 +537,13 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
return ret;
}
+ if (wait_busy(adap) < 0) { /* timeout */
+ dev_warn(&i2c_adap->dev, "timeout waiting for bus ready\n");
+ ret = i2c_recover_bus(i2c_adap);
+ if (ret < 0)
+ return ret;
+ }
+
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
i2c_start(adap);
for (i = 0; i < num; i++) {