diff options
Diffstat (limited to 'cpu/ppc4xx/speed.c')
-rw-r--r-- | cpu/ppc4xx/speed.c | 180 |
1 files changed, 174 insertions, 6 deletions
diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index da5330a..750b095 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -1,5 +1,5 @@ /* - * (C) Copyright 2000 + * (C) Copyright 2000-2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this @@ -263,7 +263,7 @@ void get_sys_info (sys_info_t *sysInfo) sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqPLB/sysInfo->pllExtBusDiv; + sysInfo->freqEBC = sysInfo->freqPLB/sysInfo->pllExtBusDiv; sysInfo->freqPCI = sysInfo->freqPLB/sysInfo->pllPciDiv; /* Figure which timer source to use */ @@ -317,7 +317,7 @@ void get_sys_info (sys_info_t * sysInfo) if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */ sysInfo->freqPLB >>= 1; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; + sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; } #else @@ -393,7 +393,7 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; - sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; + sysInfo->freqEBC = sysInfo->freqOPB/sysInfo->pllExtBusDiv; #if defined(CONFIG_YUCCA) /* Determine PCI Clock Period */ @@ -733,6 +733,8 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) * Determine PLB clock frequency */ sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv; + + sysInfo->freqEBC = sysInfo->freqPLB / sysInfo->pllExtBusDiv; } @@ -856,6 +858,9 @@ void get_sys_info (PPC405_SYS_INFO * sysInfo) */ sysInfo->freqPLB = (CONFIG_SYS_CLK_FREQ * m) / sysInfo->pllFwdDiv / sysInfo->pllPlbDiv; + + sysInfo->freqEBC = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv) / + sysInfo->pllExtBusDiv; } /******************************************** @@ -874,13 +879,175 @@ ulong get_OPB_freq (void) return val; } +#elif defined(CONFIG_405EX) + +/* + * TODO: We need to get the CPR registers and calculate these values correctly!!!! + * We need the specs!!!! + */ +static unsigned char get_fbdv(unsigned char index) +{ + unsigned char ret = 0; + /* This is table should be 256 bytes. + * Only take first 52 values. + */ + unsigned char fbdv_tb[] = { + 0x00, 0xff, 0x7f, 0xfd, + 0x7a, 0xf5, 0x6a, 0xd5, + 0x2a, 0xd4, 0x29, 0xd3, + 0x26, 0xcc, 0x19, 0xb3, + 0x67, 0xce, 0x1d, 0xbb, + 0x77, 0xee, 0x5d, 0xba, + 0x74, 0xe9, 0x52, 0xa5, + 0x4b, 0x96, 0x2c, 0xd8, + 0x31, 0xe3, 0x46, 0x8d, + 0x1b, 0xb7, 0x6f, 0xde, + 0x3d, 0xfb, 0x76, 0xed, + 0x5a, 0xb5, 0x6b, 0xd6, + 0x2d, 0xdb, 0x36, 0xec, + + }; + + if ((index & 0x7f) == 0) + return 1; + while (ret < sizeof (fbdv_tb)) { + if (fbdv_tb[ret] == index) + break; + ret++; + } + ret++; + + return ret; +} + +#define PLL_FBK_PLL_LOCAL 0 +#define PLL_FBK_CPU 1 +#define PLL_FBK_PERCLK 5 + +void get_sys_info (sys_info_t * sysInfo) +{ + unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); + unsigned long m = 1; + unsigned int tmp; + unsigned char fwdva[16] = { + 1, 2, 14, 9, 4, 11, 16, 13, + 12, 5, 6, 15, 10, 7, 8, 3, + }; + unsigned char sel, cpudv0, plb2xDiv; + + mfcpr(cpr0_plld, tmp); + + /* + * Determine forward divider A + */ + sysInfo->pllFwdDiv = fwdva[((tmp >> 16) & 0x0f)]; /* FWDVA */ + + /* + * Determine FBK_DIV. + */ + sysInfo->pllFbkDiv = get_fbdv(((tmp >> 24) & 0x0ff)); /* FBDV */ + + /* + * Determine PLBDV0 + */ + sysInfo->pllPlbDiv = 2; + + /* + * Determine PERDV0 + */ + mfcpr(cpr0_perd, tmp); + tmp = (tmp >> 24) & 0x03; + sysInfo->pllExtBusDiv = (tmp == 0) ? 4 : tmp; + + /* + * Determine OPBDV0 + */ + mfcpr(cpr0_opbd, tmp); + tmp = (tmp >> 24) & 0x03; + sysInfo->pllOpbDiv = (tmp == 0) ? 4 : tmp; + + /* Determine PLB2XDV0 */ + mfcpr(cpr0_plbd, tmp); + tmp = (tmp >> 16) & 0x07; + plb2xDiv = (tmp == 0) ? 8 : tmp; + + /* Determine CPUDV0 */ + mfcpr(cpr0_cpud, tmp); + tmp = (tmp >> 24) & 0x07; + cpudv0 = (tmp == 0) ? 8 : tmp; + + /* Determine SEL(5:7) in CPR0_PLLC */ + mfcpr(cpr0_pllc, tmp); + sel = (tmp >> 24) & 0x07; + + /* + * Determine the M factor + * PLL local: M = FBDV + * CPU clock: M = FBDV * FWDVA * CPUDV0 + * PerClk : M = FBDV * FWDVA * PLB2XDV0 * PLBDV0(2) * OPBDV0 * PERDV0 + * + */ + switch (sel) { + case PLL_FBK_CPU: + m = sysInfo->pllFwdDiv * cpudv0; + break; + case PLL_FBK_PERCLK: + m = sysInfo->pllFwdDiv * plb2xDiv * 2 + * sysInfo->pllOpbDiv * sysInfo->pllExtBusDiv; + break; + case PLL_FBK_PLL_LOCAL: + break; + default: + printf("%s unknown m\n", __FUNCTION__); + return; + + } + m *= sysInfo->pllFbkDiv; + + /* + * Determine VCO clock frequency + */ + sysInfo->freqVCOHz = (1000000000000LL * (unsigned long long)m) / + (unsigned long long)sysClkPeriodPs; + + /* + * Determine CPU clock frequency + */ + sysInfo->freqProcessor = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * cpudv0); + + /* + * Determine PLB clock frequency, ddr1x should be the same + */ + sysInfo->freqPLB = sysInfo->freqVCOHz / (sysInfo->pllFwdDiv * plb2xDiv * 2); + sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; + sysInfo->freqDDR = sysInfo->freqPLB; + sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; +} + +/******************************************** + * get_OPB_freq + * return OPB bus freq in Hz + *********************************************/ +ulong get_OPB_freq (void) +{ + ulong val = 0; + + PPC405_SYS_INFO sys_info; + + get_sys_info (&sys_info); + val = sys_info.freqPLB / sys_info.pllOpbDiv; + + return val; +} + #endif int get_clocks (void) { #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440) || defined(CONFIG_405) + defined(CONFIG_405EX) || defined(CONFIG_405) || \ + defined(CONFIG_440) sys_info_t sys_info; get_sys_info (&sys_info); @@ -907,7 +1074,8 @@ ulong get_bus_freq (ulong dummy) #if defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ - defined(CONFIG_440) || defined(CONFIG_405) + defined(CONFIG_405EX) || defined(CONFIG_405) || \ + defined(CONFIG_440) sys_info_t sys_info; get_sys_info (&sys_info); |