Re: [Patch v2 1/2] 5200/mpc: improve i2c bus error recovery
From: Joakim Tjernlund <hidden>
Date: 2010-02-18 17:14:51
Also in:
linux-devicetree
"Albrecht Dre=DF" [off-list ref] wrote on 2010/02/18 16:04:1= 6:
Hi Joakim: [snip]quoted
quoted
static void mpc_i2c_fixup(struct mpc_i2c *i2c) { - writeccr(i2c, 0); - udelay(30); - writeccr(i2c, CCR_MEN); - udelay(30); - writeccr(i2c, CCR_MSTA | CCR_MTX); - udelay(30); - writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); - udelay(30); - writeccr(i2c, CCR_MEN); - udelay(30); + int k; + u32 delay_val =3D 1000000 / i2c->real_clk + 1; + + if (delay_val < 2) + delay_val =3D 2; + + for (k =3D 9; k; k--) { + writeccr(i2c, 0); + writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); + udelay(delay_val); + writeccr(i2c, CCR_MEN); + udelay(delay_val << 1); + } }I am curious, didn't old method work with by just wrapping a for(k=3D9; k; k--) around it? How did the wave form look?Sure does that work! The waveform was somewhat "streched", mainly du=
e to the
delays between some of the writeccr() calls which don't change the sd=
a/scl
lines. Unfortunately I didn't take shots from the scope.
Yeah, the long delays has to go. So the wave form was the same but more= stretched in time? I ask because I don't understand the writeccr(i2c, CCR_MSTA | = CCR_MTX); is supposed to do.
However, for *one* cycle, the old code needed (only counting the udel=
ay's) 150
us. For 9 cycles, it's 1.35 ms, which isn't really nice ;-). At 375=
kHz real
clock rate, delay_val is 3, i.e. each cycle consumes 9 us, or 81 us f=
or the
whole fixup procedure. If the clock is slower, the gain is of course=
a lot
smaller, and at 20.5 kHz each cycle again needs 150 us... My feeling is that the delays used in the old code are just "some" va=
lues
which work for sure, to if you like, my change is basically optimisat=
ion... The old code only works when the device is stuck at the last bit. To co= pe with any bit (worst case is the first bit) you need 9 cycles, 8 bits + = ack =3D 9 Just toggling the clock 9 cycles should unlock any slave stuck in a rea= d operation. To unlock slaves stuck in a write operation you also need to generate a= START in every cycle too. As far as I can tell your patch does all of the above so Signed-off-by: Joakim Tjernlund <redacted>
BTW, related to your earlier question, I checked the timings recorded=
with the
scope at 100 and at 20 kHz against the nxp's "I2C bus specification a=
nd user
manual", rev. 03 - everything seems to be fine.
Good, thanks. Jocke=