diff options
Diffstat (limited to 'arch/powerpc/boot/4xx.c')
-rw-r--r-- | arch/powerpc/boot/4xx.c | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c index 3d0e4f921f1..852992b146e 100644 --- a/arch/powerpc/boot/4xx.c +++ b/arch/powerpc/boot/4xx.c @@ -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); +} + |