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 <[email protected]>
> ---
>  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 <[email protected]>

Cheers,
Peter

Reply via email to