diff options
Diffstat (limited to 'arch/powerpc/cpu/ppc4xx/speed.c')
-rw-r--r-- | arch/powerpc/cpu/ppc4xx/speed.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/arch/powerpc/cpu/ppc4xx/speed.c b/arch/powerpc/cpu/ppc4xx/speed.c index abd4e91..09d6671 100644 --- a/arch/powerpc/cpu/ppc4xx/speed.c +++ b/arch/powerpc/cpu/ppc4xx/speed.c @@ -189,7 +189,7 @@ ulong get_PCI_freq (void) #elif defined(CONFIG_440) #if defined(CONFIG_460EX) || defined(CONFIG_460GT) || \ - defined(CONFIG_460SX) + defined(CONFIG_460SX) || defined(CONFIG_APM821XX) static u8 pll_fwdv_multi_bits[] = { /* values for: 1 - 16 */ 0x00, 0x01, 0x0f, 0x04, 0x09, 0x0a, 0x0d, 0x0e, 0x03, 0x0c, @@ -250,6 +250,78 @@ u32 get_cpr0_fbdv(unsigned long cpr_reg_fbdv) return 0; } +#if defined(CONFIG_APM821XX) + +void get_sys_info(sys_info_t *sysInfo) +{ + unsigned long plld; + unsigned long temp; + unsigned long mul; + unsigned long cpudv; + unsigned long plb2dv; + unsigned long ddr2dv; + + /* Calculate Forward divisor A and Feeback divisor */ + mfcpr(CPR0_PLLD, plld); + + temp = CPR0_PLLD_FWDVA(plld); + sysInfo->pllFwdDivA = get_cpr0_fwdv(temp); + + temp = CPR0_PLLD_FDV(plld); + sysInfo->pllFbkDiv = get_cpr0_fbdv(temp); + + /* Calculate OPB clock divisor */ + mfcpr(CPR0_OPBD, temp); + temp = CPR0_OPBD_OPBDV(temp); + sysInfo->pllOpbDiv = temp ? temp : 4; + + /* Calculate Peripheral clock divisor */ + mfcpr(CPR0_PERD, temp); + temp = CPR0_PERD_PERDV(temp); + sysInfo->pllExtBusDiv = temp ? temp : 4; + + /* Calculate CPU clock divisor */ + mfcpr(CPR0_CPUD, temp); + temp = CPR0_CPUD_CPUDV(temp); + cpudv = temp ? temp : 8; + + /* Calculate PLB2 clock divisor */ + mfcpr(CPR0_PLB2D, temp); + temp = CPR0_PLB2D_PLB2DV(temp); + plb2dv = temp ? temp : 4; + + /* Calculate DDR2 clock divisor */ + mfcpr(CPR0_DDR2D, temp); + temp = CPR0_DDR2D_DDR2DV(temp); + ddr2dv = temp ? temp : 4; + + /* Calculate 'M' based on feedback source */ + mfcpr(CPR0_PLLC, temp); + temp = CPR0_PLLC_SEL(temp); + if (temp == 0) { + /* PLL internal feedback */ + mul = sysInfo->pllFbkDiv; + } else { + /* PLL PerClk feedback */ + mul = sysInfo->pllFwdDivA * sysInfo->pllFbkDiv * cpudv + * plb2dv * 2 * sysInfo->pllOpbDiv * + sysInfo->pllExtBusDiv; + } + + /* Now calculate the individual clocks */ + sysInfo->freqVCOMhz = (mul * CONFIG_SYS_CLK_FREQ) + (mul >> 1); + sysInfo->freqProcessor = sysInfo->freqVCOMhz / + sysInfo->pllFwdDivA / cpudv; + sysInfo->freqPLB = sysInfo->freqVCOMhz / + sysInfo->pllFwdDivA / cpudv / plb2dv / 2; + sysInfo->freqOPB = sysInfo->freqPLB / sysInfo->pllOpbDiv; + sysInfo->freqEBC = sysInfo->freqOPB / sysInfo->pllExtBusDiv; + sysInfo->freqDDR = sysInfo->freqVCOMhz / + sysInfo->pllFwdDivA / cpudv / ddr2dv / 2; + sysInfo->freqUART = sysInfo->freqPLB; +} + +#else /* * AMCC_TODO: verify this routine against latest EAS, cause stuff changed * with latest EAS @@ -307,6 +379,7 @@ void get_sys_info (sys_info_t * sysInfo) return; } +#endif #elif defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ defined(CONFIG_440EPX) || defined(CONFIG_440GRX) |