[Patch v2 1/2] 5200/mpc: improve i2c bus error recovery
Joakim Tjernlund
joakim.tjernlund at transmode.se
Thu Feb 18 19:09:17 EST 2010
>
> This patch improves the recovery of the MPC's I2C bus from errors like bus
> hangs resulting in timeouts:
> 1. make the bus timeout configurable, as it depends on the bus clock and
> the attached slave chip(s); default is still 1 second;
> 2. detect any of the cases indicated by the CF, BB and RXAK MSR flags if a
> timeout occurs, and add a missing (required) MAL reset;
> 3. use a more reliable method to fixup the bus if a hang has been detected.
> The sequence is sent 9 times which seems to be necessary if a slave
> "misses" more than one clock cycle. For 400 kHz bus speed, the fixup is
> also ~70us (81us vs. 150us) faster.
>
> Tested on a custom Lite5200b derived board, with a Dallas RTC, AD sensors
> and NXP IO expander chips attached to the i2c.
>
> Changes vs. v1:
> - use improved bus fixup sequence for all chips (not only the 5200)
> - calculate real clock from defaults if no clock is given in the device tree
> - better description (I hope) of the changes.
>
> I didn't split the changes in this file into three parts as recommended by
> Grant, as they actually belong together (i.e. they address one single
> problem, just in three places of one single source file).
>
> Signed-off-by: Albrecht Dreß <albrecht.dress at arcor.de>
>
> ---
>
> Note about the reset sequence: I verified the waveforms for 18.4kHz, 85.9kHz
> and 375kHz (drop me a note if you want to see scope screen shots). Not
> verified on other mpc chips yet.
> @Ira: thanks in advance for giving it a try on your box!
Does this reset sequence also send a START condition for every clock?
The ideal I2C reset sequence should look like this:
for(j = 0; j < 9; j++) {
if(I2C_READ)
send_start();
I2C_SCL(0);
I2C_DELAY;
I2C_TRISTATE;
I2C_SDA(1);
I2C_DELAY;
I2C_SCL(1);
I2C_DELAY;
I2C_DELAY;
}
send_stop();
static void send_start(void)
{
I2C_DELAY;
I2C_TRISTATE;
I2C_SDA(1);
I2C_DELAY;
I2C_SCL(1);
I2C_DELAY;
I2C_SDA(0);
I2C_ACTIVE;
I2C_DELAY;
}
static void send_stop(void)
{
I2C_SCL(0);
I2C_DELAY;
I2C_SDA(0);
I2C_ACTIVE;
I2C_DELAY;
I2C_SCL(1);
I2C_DELAY;
I2C_TRISTATE;
I2C_SDA(1);
I2C_DELAY;
}
Jocke
More information about the Linuxppc-dev
mailing list