1. System description:
A custom board with iMX6S SoC is connected via I2C bus to SMBus controller of some x86 board(with Intel 8 Series Chipset). There are several temperature and voltage sensors on the x86 board, which are physically connected/soldered to the SMBus. The iMX6S module periodically reads these sensors to decide if h/w is functional.
And a few words about software: a standard Yocto BSP from http://freescale.github.io/ with 3.10.17 kernel is launched on our iMX6S and some decent Linux distribution(like Fedora 20) is used on the x86 board.
All works well.
As we don't know whether the SMBus controller on x86-board will be used by customers(e.g. to access the same sensors or to communicate with some other device), we've decided to perform some stress tests: we continuously read the same register on the same sensor from both sides simultaneously(from iMX6 and from x86 board). After several minutes(1-30) the bus(I2C/SMBus) locks up: some device holds a SDA line low all the time. And when we manually simulate some clocks on SCL, the SDA becomes high again.
- is reproduced with other sensors/devices on SMBus and with other x86 boards(with different chipsets);
- can't be reproduced with only one I2C/SMBus master is present;
- can't be reproduced with other I2C controllers(when iMX6 is replaced by another board).
3. Our attempts to solve/work around it:
Unfortunately for us, we can't determine a root cause of this problem. But as such problems(I2C lock up) are very common, we've decided to integrate some workaround into i2c-imx driver. And it seems that a workaround that was proposed for iMX53 SoC doesn't work on iMX6:
"The following procedure can be used to force this I2C module to generate SCLn so that the device driving SDAn can finish its transaction:
1.1. Disable the I2C module and set the master bit by setting I2CnCR to 0x20.
1.2. Enable the I2C module by setting I2CnCR to 0xA0.
1.3. Read I2CnDR.
1.4. Return the I2C module to slave mode by setting I2CnCR to 0x80."
In our case, when SDA is low, we can't set the master bit to 1, because the I2C controller instantly reverts it to 0. And at that time we can't observe any activity on SCL line with oscilloscope. (Note: this bit sets to 1 perfectly when SDA is high ).
Probably we are doing something wrong, or maybe another trick should be used on iMX6. But we've tried to write to other registers of this I2C controller when SDA is low - all the same and the SCL pulses are not generated.
It seems that the only possible solution(from software point of view) is to reconfigure SCL as GPIO and use it to generate several clocks. Then to reconfigure it back (but it's too clunky).
If someone had experienced similar problem, could you please share your thoughts on it? Very probably that we've missed something important.