Skip to content

Commit cf8ce8b

Browse files
Russell KingWolfram Sang
authored andcommitted
i2c: fix bus recovery stop mode timing
The I2C specification states that tsu:sto for standard mode timing must be at minimum 4us. Pictographically, this is: SCL: ____/~~~~~~~~~ SDA: _________/~~~~ ->| |<- 4us minimum We are currently waiting 2.5us between asserting SCL and SDA, which is in violation of the standard. Adjust the timings to ensure that we meet what is stipulated as the minimum timings to ensure that all devices correctly interpret the STOP bus transition. This is more important than trying to generate a square wave with even duty cycle. Signed-off-by: Russell King <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 3b722da commit cf8ce8b

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

drivers/i2c/i2c-core-base.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,11 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
186186
* If we can set SDA, we will always create a STOP to ensure additional
187187
* pulses will do no harm. This is achieved by letting SDA follow SCL
188188
* half a cycle later. Check the 'incomplete_write_byte' fault injector
189-
* for details.
189+
* for details. Note that we must honour tsu:sto, 4us, but lets use 5us
190+
* here for simplicity.
190191
*/
191192
bri->set_scl(adap, scl);
192-
ndelay(RECOVERY_NDELAY / 2);
193+
ndelay(RECOVERY_NDELAY);
193194
if (bri->set_sda)
194195
bri->set_sda(adap, scl);
195196
ndelay(RECOVERY_NDELAY / 2);
@@ -211,7 +212,13 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
211212
scl = !scl;
212213
bri->set_scl(adap, scl);
213214
/* Creating STOP again, see above */
214-
ndelay(RECOVERY_NDELAY / 2);
215+
if (scl) {
216+
/* Honour minimum tsu:sto */
217+
ndelay(RECOVERY_NDELAY);
218+
} else {
219+
/* Honour minimum tf and thd:dat */
220+
ndelay(RECOVERY_NDELAY / 2);
221+
}
215222
if (bri->set_sda)
216223
bri->set_sda(adap, scl);
217224
ndelay(RECOVERY_NDELAY / 2);

0 commit comments

Comments
 (0)