Sluggish AT91 I2C driver causes SMBus timeouts

From: Peter Rosin
Date: Thu Oct 12 2017 - 07:35:30 EST


Hi!

I have encountered an "interesting" bug. It silently corrupts data
and is generally nasty...

On an I2C bus, driven by the at91 driver and DMA (an Atmel
sama5d31 chip), I have an 256 byte eeprom (NXP SE97BTP). I'm using
Linux v4.13.

The at24 driver for the eeprom detects that the I2C adapter is
capable of I2C transactions and selects that over SMBus. Reads
are done in 128 byte chunks. However, sometimes there is some
kind of event that disturbs the transactions such that the very
last bit och the very last byte (and the following NACK and STOP)
of such chunks are delayed for a long time (the latest incident
shows 85ms on the scope). That is too long for the eeprom which
is expecting SMBus and times out after about 30 ms. When the
eeprom times out, it just releases the data line so that it is
pulled up high. The I2C driver does not notice this, and when it
finally gets going, it reads a one for the last bit instead of
the expected zero. Since it is the last byte of the read, a NACK
is expected and since the eeprom has timed out the NACK is there.
And the STOP condition also looks normal (expected since it is
generated by the driver itself). So, the driver has not noticed
anything funny. But the data is corrupted.

I can work around this by disabling the SMBus timeout in the eeprom
with:

i2cset -f 0 0x18 0x22 0x8100

But that is done on a different I2C address (the eeprom is on
address 0x50), since the chip is a combined temperature sensor and
eeprom, and the SMBus timeout bit is of course in a temperature
sensor register.

HOWEVER, I fail to see how this is limited to my case with this
eeprom. Any SMBus chip with a timeout will suffer the same fate.
The real bug is that this happens without the driver noticing it.
And why is there a 85ms delay in the middle of the last byte?
Sure, I can see why there might be a delay before finishing up
with a STOP condition or between bytes if there needs to be some
DMA setup at some interval, but after the 7th bit of a byte?

For a lot of transactions on the I2C bus there is no delay before
the last bit. And most of the time there is no delay for the
eeprom reads either; the delay only occurs when it feels like it.

This does not feel good at all.

Cheers,
Peter