On 2018-07-10 23:42, Wolfram Sang wrote:
> I2C clients may misunderstand recovery pulses if they can't read SDA to
> bail out early. In the worst case, as a write operation. To avoid that
> and if we can write SDA, try to send STOP to avoid the
> misinterpretation.
>
> Signed-off-by: Wolfram Sang
> ---
> drivers/i2c/i2c-core-base.c | 11 ++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
> index 31d16ada6e7d..301285c54603 100644
> --- a/drivers/i2c/i2c-core-base.c
> +++ b/drivers/i2c/i2c-core-base.c
> @@ -198,7 +198,16 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
>
> val = !val;
> bri->set_scl(adap, val);
> - ndelay(RECOVERY_NDELAY);
> +
> + /*
> + * If we can set SDA, we will always create STOP here to ensure
> + * the additional pulses will do no harm. This is achieved by
> + * letting SDA follow SCL half a cycle later.
> + */
> + ndelay(RECOVERY_NDELAY / 2);
> + if (bri->set_sda)
> + bri->set_sda(adap, val);
> + ndelay(RECOVERY_NDELAY / 2);
> }
>
> /* check if recovery actually succeeded */
>
Hmmm, should not the ndelay before the loop also be split up in two like
this, with one ndelay(... / 2) on either side of the (possible) set_sda.
Not that it should matter, since SDA is presumably stuck low. But what if
it isn't?
I would also change the while (...) to
for (i = 0; i < RECOVERY_CLK_CNT * 2; i++)
but both these "issues" are perhaps not related to this patch...
Either way,
Reviewed-by: Peter Rosin
Cheers,
Peter