Thread (4 messages) 4 messages, 3 authors, 2010-02-18

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=
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help