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>
This commit is contained in:
parent
8127dfdaa1
commit
39e4db8376
|
@ -117,6 +117,31 @@ done:
|
||||||
return 0;
|
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 -------------------------------------- */
|
/* --- other auxiliary functions -------------------------------------- */
|
||||||
static void i2c_start(struct i2c_algo_bit_data *adap)
|
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;
|
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");
|
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
|
||||||
i2c_start(adap);
|
i2c_start(adap);
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
|
|
Loading…
Reference in New Issue