Patch by Jon Loeliger, 16 Jul 2004:
[oweals/u-boot.git] / cpu / ppc4xx / speed.c
index f075e3a0473086b7bc8dabf2de9baca23ea4157a..be0de0c32a08433a50379a8bc6eee6b8c7183322 100644 (file)
@@ -206,6 +206,7 @@ ulong get_PCI_freq (void)
 
 
 #elif defined(CONFIG_440)
+#if !defined(CONFIG_440_GX)
 void get_sys_info (sys_info_t * sysInfo)
 {
        unsigned long strp0;
@@ -232,11 +233,64 @@ void get_sys_info (sys_info_t * sysInfo)
        sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;
        sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB;
     if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */
-        sysInfo->freqPLB >>= 1;
+       sysInfo->freqPLB >>= 1;
        sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;
        sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv;
 
 }
+#else
+void get_sys_info (sys_info_t * sysInfo)
+{
+       unsigned long strp0;
+       unsigned long strp1;
+       unsigned long temp;
+       unsigned long temp1;
+       unsigned long lfdiv;
+       unsigned long m;
+       unsigned long prbdv0;
+
+       /* Extract configured divisors */
+       mfsdr( sdr_sdstp0,strp0 );
+       mfsdr( sdr_sdstp1,strp1 );
+
+       temp = ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 8);
+       sysInfo->pllFwdDivA = temp ? temp : 16 ;
+       temp = ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 5);
+       sysInfo->pllFwdDivB = temp ? temp: 8 ;
+       temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 12;
+       sysInfo->pllFbkDiv = temp ? temp : 32;
+       temp = (strp0 & PLLSYS0_OPB_DIV_MASK);
+       sysInfo->pllOpbDiv = temp ? temp : 4;
+       temp = (strp1 & PLLSYS1_PERCLK_DIV_MASK) >> 24;
+       sysInfo->pllExtBusDiv = temp ? temp : 4;
+       prbdv0 = (strp0 >> 2) & 0x7;
+
+       /* Calculate 'M' based on feedback source */
+       temp = (strp0 & PLLSYS0_SEL_MASK) >> 27;
+       temp1 = (strp1 & PLLSYS1_LF_DIV_MASK) >> 26;
+       lfdiv = temp1 ? temp1 : 64;
+       if (temp == 0) { /* PLL output */
+               /* Figure which pll to use */
+               temp = (strp0 & PLLSYS0_SRC_MASK) >> 30;
+               if (!temp)
+                       m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivA;
+               else
+                       m = sysInfo->pllFbkDiv * lfdiv * sysInfo->pllFwdDivB;
+       }
+       else if (temp == 1) /* CPU output */
+               m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA;
+       else /* PerClk */
+               m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;
+
+       /* Now calculate the individual clocks */
+       sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1);
+       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;
+
+}
+#endif
 
 ulong get_OPB_freq (void)
 {
@@ -246,6 +300,10 @@ ulong get_OPB_freq (void)
        return sys_info.freqOPB;
 }
 
+#elif defined(CONFIG_XILINX_ML300)
+extern void get_sys_info (sys_info_t * sysInfo);
+extern ulong get_PCI_freq (void);
+
 #elif defined(CONFIG_405)
 
 void get_sys_info (sys_info_t * sysInfo) {
@@ -257,11 +315,137 @@ void get_sys_info (sys_info_t * sysInfo) {
 
 }
 
+#elif defined(CONFIG_405EP)
+void get_sys_info (PPC405_SYS_INFO * sysInfo)
+{
+       unsigned long pllmr0;
+       unsigned long pllmr1;
+       unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000);
+       unsigned long m;
+       unsigned long pllmr0_ccdv;
+
+       /*
+        * Read PLL Mode registers
+        */
+       pllmr0 = mfdcr (cpc0_pllmr0);
+       pllmr1 = mfdcr (cpc0_pllmr1);
+
+       /*
+        * Determine forward divider A
+        */
+       sysInfo->pllFwdDiv = 8 - ((pllmr1 & PLLMR1_FWDVA_MASK) >> 16);
+
+       /*
+        * Determine forward divider B (should be equal to A)
+        */
+       sysInfo->pllFwdDivB = 8 - ((pllmr1 & PLLMR1_FWDVB_MASK) >> 12);
+
+       /*
+        * Determine FBK_DIV.
+        */
+       sysInfo->pllFbkDiv = ((pllmr1 & PLLMR1_FBMUL_MASK) >> 20);
+       if (sysInfo->pllFbkDiv == 0) {
+               sysInfo->pllFbkDiv = 16;
+       }
+
+       /*
+        * Determine PLB_DIV.
+        */
+       sysInfo->pllPlbDiv = ((pllmr0 & PLLMR0_CPU_TO_PLB_MASK) >> 16) + 1;
+
+       /*
+        * Determine PCI_DIV.
+        */
+       sysInfo->pllPciDiv = (pllmr0 & PLLMR0_PCI_TO_PLB_MASK) + 1;
+
+       /*
+        * Determine EXTBUS_DIV.
+        */
+       sysInfo->pllExtBusDiv = ((pllmr0 & PLLMR0_EXB_TO_PLB_MASK) >> 8) + 2;
+
+       /*
+        * Determine OPB_DIV.
+        */
+       sysInfo->pllOpbDiv = ((pllmr0 & PLLMR0_OPB_TO_PLB_MASK) >> 12) + 1;
+
+       /*
+        * Determine the M factor
+        */
+       m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB;
+
+       /*
+        * Determine VCO clock frequency
+        */
+       sysInfo->freqVCOMhz = (1000000 * m) / sysClkPeriodPs;
+
+       /*
+        * Determine CPU clock frequency
+        */
+       pllmr0_ccdv = ((pllmr0 & PLLMR0_CPU_DIV_MASK) >> 20) + 1;
+       if (pllmr1 & PLLMR1_SSCS_MASK) {
+               /*
+                * This is true if FWDVA == FWDVB:
+                * sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv)
+                *      / pllmr0_ccdv;
+                */
+               sysInfo->freqProcessor = (CONFIG_SYS_CLK_FREQ * sysInfo->pllFbkDiv * sysInfo->pllFwdDivB)
+                       / sysInfo->pllFwdDiv / pllmr0_ccdv;
+       } else {
+               sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ / pllmr0_ccdv;
+       }
+
+       /*
+        * Determine PLB clock frequency
+        */
+       sysInfo->freqPLB = sysInfo->freqProcessor / sysInfo->pllPlbDiv;
+
+       if (!((sysInfo->freqVCOMhz >= VCO_MIN) && (sysInfo->freqVCOMhz <= VCO_MAX))) {
+               printf ("\nInvalid VCO frequency calculated :  %ld MHz \a\n",
+                       sysInfo->freqVCOMhz);
+               printf ("It must be between %d-%d MHz \a\n", VCO_MIN, VCO_MAX);
+               printf ("PLL Mode reg 0           :  %8.8lx\a\n", pllmr0);
+               printf ("PLL Mode reg 1           :  %8.8lx\a\n", pllmr1);
+               hang ();
+       }
+}
+
+
+/********************************************
+ * 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;
+}
+
+
+/********************************************
+ * get_PCI_freq
+ * return PCI bus freq in Hz
+ *********************************************/
+ulong get_PCI_freq (void)
+{
+       ulong val;
+       PPC405_SYS_INFO sys_info;
+
+       get_sys_info (&sys_info);
+       val = sys_info.freqPLB / sys_info.pllPciDiv;
+       return val;
+}
+
 #endif
 
 int get_clocks (void)
 {
-#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405)
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405) || defined(CONFIG_405EP)
        DECLARE_GLOBAL_DATA_PTR;
 
        sys_info_t sys_info;
@@ -290,7 +474,7 @@ ulong get_bus_freq (ulong dummy)
 {
        ulong val;
 
-#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_440)
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_440) || defined(CONFIG_405EP)
        sys_info_t sys_info;
 
        get_sys_info (&sys_info);