[U-Boot] fsl_i2c: increase I2C timeout values and make them configurable

Joakim Tjernlund joakim.tjernlund at transmode.se
Fri Sep 11 10:44:37 CEST 2009


>
> Timur Tabi <timur at freescale.com> wrote on 10/09/2009 18:13:03:
> >
> > Joakim Tjernlund wrote:
> >
> > > This calculation does not seem to match AN2919.
> >
> > When I wrote the code, AN2919 was much smaller than what you have today.
> >
> > > Suppose one used only Table 7(almost what we have if you exclude dfsr!= 1)
> > > Table 7 is valid for 1 <= dfsr <=5 so how about replacing the current dfsr
> > > with:
> > > #ifdef __PPC__
> > >          u8 dfsr;
> > >          dfsr = (5*(i2c_clk/1000))/(100000);
> > >          if (dfsr > 5)
> > >             dfsr = 5;
> > >          if (!dfsr)
> > >             dfsr = 1;
> > >          debug("i2c_clk:%d, dfsr:%d\n", i2c_clk, dfsr);
> > >          writeb(dfsr, &dev->dfsrr);   /* set default filter */
> > > #endif
> >
> > The value of FDR is dependent on the value of DFSR, so if I calculate DFSR, I
> > have to also calculate FDR.  This means the table goes away.  I'm okay with
> > that (since my table is no longer a viable approach, it seems), but it's more
> > work than I'm willing to do at the moment.  Especically since this is going to
> > need a lot of testing before I'm willing to push it.
>
> I could not resist so I did a quick start:
[SNIP]

So I completed the function, here it is:

#include <stdlib.h>
#include <stdio.h>
#define I2C_CLK 133332000

int main(int argc, char *argv[])
{
  unsigned long A,B,C;
  unsigned long Ga,Gb;
  unsigned long divisor, req_div;
  unsigned long est_div, bin_Gb, bin_Ga, est_FDR;
  unsigned long speed;

  if (argc != 2) {
    printf("%s <speed in HZ>\n", argv[0]);
    exit(1);
  }
  speed = atol(argv[1]);
  req_div = I2C_CLK/speed;
  C = (5*(I2C_CLK/1000))/(100000);
  if (!C)
    C = 1;
  est_div = ~0;
  for(Ga=0x4, A=10; A<=30; Ga++, A+=2) {
    for (Gb=0; Gb<8; Gb++) {
      B = 16 << Gb;
      divisor = B * (A + ((3*C)/B)*2);
      if (divisor >= req_div && divisor < est_div) {
	est_div = divisor;
	bin_Gb = Gb << 2;
	bin_Ga = (Ga & 0x3) | ((Ga & 0x4) << 3);
	est_FDR = bin_Gb | bin_Ga;
	//printf("div:%d, A:%d, B:%d b:%x, a:%x\n", divisor, A, B, Gb, Ga);
	//printf("bin_Gb:0x%x, bin_Ga:0x%x\n", bin_Gb, bin_Ga);
	//printf("FDR:0x%.2x, div:%d\n", est_FDR, est_div);
	//printf("speed:%d\n\n", I2C_CLK/est_div);
#if 0
/* Condition 2 not accounted for */
	{
	  unsigned long T = 1000000000/I2C_CLK;

	  printf("%d*%d >= Tr\n", (B-3*C), T);
	  printf("%d >= Tr\n", (B-3*C)* T);
	}
#endif
      }
    }
/* The old table in u-boot miss this */
    if (A == 20)
      A+=2;
    if (A == 24)
      A+=4;
  }

#if 1
  printf("\nreq_div:%d, est_div:%d, DFSR:%d\n", req_div, est_div, C);
  printf("bin_Gb:0x%x, bin_Ga:0x%x\n", bin_Gb, bin_Ga);
  printf("FDR:0x%.2x\n", est_FDR);
  printf("speed:%d\n", I2C_CLK/est_div);
#endif
}

This will generate the same divisor tables as AN2919, tables 6-9.
I do not take condition 2 into consideration as it not clear how to
deal with it and it does not seem to have an significant impact.

What do you think?



More information about the U-Boot mailing list