[POWERPC] 4xx: EP405 boards support for arch/powerpc
[pandora-kernel.git] / arch / powerpc / boot / 4xx.c
index 3d0e4f9..852992b 100644 (file)
@@ -179,13 +179,16 @@ void ibm40x_dbcr_reset(void)
 #define EMAC_RESET 0x20000000
 void ibm4xx_quiesce_eth(u32 *emac0, u32 *emac1)
 {
-       /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't do this for us */
+       /* Quiesce the MAL and EMAC(s) since PIBS/OpenBIOS don't
+        * do this for us
+        */
        if (emac0)
                *emac0 = EMAC_RESET;
        if (emac1)
                *emac1 = EMAC_RESET;
 
        mtdcr(DCRN_MAL0_CFG, MAL_RESET);
+       while (mfdcr(DCRN_MAL0_CFG) & MAL_RESET) {};
 }
 
 /* Read 4xx EBC bus bridge registers to get mappings of the peripheral
@@ -298,3 +301,53 @@ void ibm440ep_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
        dt_fixup_clock("/plb/opb/serial@ef600500", uart0);
        dt_fixup_clock("/plb/opb/serial@ef600600", uart0);
 }
+
+void ibm405gp_fixup_clocks(unsigned int sysclk, unsigned int ser_clk)
+{
+       u32 pllmr = mfdcr(DCRN_CPC0_PLLMR);
+       u32 cpc0_cr0 = mfdcr(DCRN_405_CPC0_CR0);
+       u32 cpc0_cr1 = mfdcr(DCRN_405_CPC0_CR1);
+       u32 cpu, plb, opb, ebc, tb, uart0, uart1, m;
+       u32 fwdv, fbdv, cbdv, opdv, epdv, udiv;
+
+       fwdv = (8 - ((pllmr & 0xe0000000) >> 29));
+       fbdv = (pllmr & 0x1e000000) >> 25;
+       cbdv = ((pllmr & 0x00060000) >> 17) + 1;
+       opdv = ((pllmr & 0x00018000) >> 15) + 1;
+       epdv = ((pllmr & 0x00001800) >> 13) + 2;
+       udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1;
+
+       m = fwdv * fbdv * cbdv;
+
+       cpu = sysclk * m / fwdv;
+       plb = cpu / cbdv;
+       opb = plb / opdv;
+       ebc = plb / epdv;
+
+       if (cpc0_cr0 & 0x80) {
+               /* uart0 uses the external clock */
+               uart0 = ser_clk;
+       } else {
+               uart0 = cpu / udiv;
+       }
+
+       if (cpc0_cr0 & 0x40) {
+               /* uart1 uses the external clock */
+               uart1 = ser_clk;
+       } else {
+               uart1 = cpu / udiv;
+       }
+
+       /* setup the timebase clock to tick at the cpu frequency */
+       cpc0_cr1 = cpc0_cr1 & ~0x00800000;
+       mtdcr(DCRN_405_CPC0_CR1, cpc0_cr1);
+       tb = cpu;
+
+       dt_fixup_cpu_clocks(cpu, tb, 0);
+       dt_fixup_clock("/plb", plb);
+       dt_fixup_clock("/plb/opb", opb);
+       dt_fixup_clock("/plb/ebc", ebc);
+       dt_fixup_clock("/plb/opb/serial@ef600300", uart0);
+       dt_fixup_clock("/plb/opb/serial@ef600400", uart1);
+}
+