1 |
From cf8ce8b80f8bf9669f6ec4e71e16668430febdac Mon Sep 17 00:00:00 2001 |
2 |
From: Russell King <rmk+kernel@armlinux.org.uk> |
3 |
Date: Sun, 15 Dec 2019 16:39:05 +0000 |
4 |
Subject: i2c: fix bus recovery stop mode timing |
5 |
|
6 |
From: Russell King <rmk+kernel@armlinux.org.uk> |
7 |
|
8 |
commit cf8ce8b80f8bf9669f6ec4e71e16668430febdac upstream. |
9 |
|
10 |
The I2C specification states that tsu:sto for standard mode timing must |
11 |
be at minimum 4us. Pictographically, this is: |
12 |
|
13 |
SCL: ____/~~~~~~~~~ |
14 |
SDA: _________/~~~~ |
15 |
->| |<- 4us minimum |
16 |
|
17 |
We are currently waiting 2.5us between asserting SCL and SDA, which is |
18 |
in violation of the standard. Adjust the timings to ensure that we meet |
19 |
what is stipulated as the minimum timings to ensure that all devices |
20 |
correctly interpret the STOP bus transition. |
21 |
|
22 |
This is more important than trying to generate a square wave with even |
23 |
duty cycle. |
24 |
|
25 |
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
26 |
Signed-off-by: Wolfram Sang <wsa@the-dreams.de> |
27 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
28 |
|
29 |
--- |
30 |
drivers/i2c/i2c-core-base.c | 13 ++++++++++--- |
31 |
1 file changed, 10 insertions(+), 3 deletions(-) |
32 |
|
33 |
--- a/drivers/i2c/i2c-core-base.c |
34 |
+++ b/drivers/i2c/i2c-core-base.c |
35 |
@@ -186,10 +186,11 @@ int i2c_generic_scl_recovery(struct i2c_ |
36 |
* If we can set SDA, we will always create a STOP to ensure additional |
37 |
* pulses will do no harm. This is achieved by letting SDA follow SCL |
38 |
* half a cycle later. Check the 'incomplete_write_byte' fault injector |
39 |
- * for details. |
40 |
+ * for details. Note that we must honour tsu:sto, 4us, but lets use 5us |
41 |
+ * here for simplicity. |
42 |
*/ |
43 |
bri->set_scl(adap, scl); |
44 |
- ndelay(RECOVERY_NDELAY / 2); |
45 |
+ ndelay(RECOVERY_NDELAY); |
46 |
if (bri->set_sda) |
47 |
bri->set_sda(adap, scl); |
48 |
ndelay(RECOVERY_NDELAY / 2); |
49 |
@@ -211,7 +212,13 @@ int i2c_generic_scl_recovery(struct i2c_ |
50 |
scl = !scl; |
51 |
bri->set_scl(adap, scl); |
52 |
/* Creating STOP again, see above */ |
53 |
- ndelay(RECOVERY_NDELAY / 2); |
54 |
+ if (scl) { |
55 |
+ /* Honour minimum tsu:sto */ |
56 |
+ ndelay(RECOVERY_NDELAY); |
57 |
+ } else { |
58 |
+ /* Honour minimum tf and thd:dat */ |
59 |
+ ndelay(RECOVERY_NDELAY / 2); |
60 |
+ } |
61 |
if (bri->set_sda) |
62 |
bri->set_sda(adap, scl); |
63 |
ndelay(RECOVERY_NDELAY / 2); |