
Timur Tabi timur@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?