diff options
author | Matthias Fuchs <matthias.fuchs@esd-electronics.com> | 2007-12-07 09:23:05 +1100 |
---|---|---|
committer | Josh Boyer <jwboyer@linux.vnet.ibm.com> | 2008-01-08 07:58:09 -0600 |
commit | 2af59f7d5c3e342db4bdd28c59090aee05577aef (patch) | |
tree | 39048f450e9046bff5c76c2c97ce0c8f72c5ddba /arch/powerpc/boot/4xx.c | |
parent | 5834584e4ea0b03c767e315a5879551b240c5652 (diff) |
[POWERPC] 4xx: Add 405GPr and 405EP support in boot wrapper
This patch adds support for 405GPr processors with optional
new mode strapping. ibm405gp_fixup_clocks() can now be used
for 405GP and 405GPr CPUs.
This is in preparation of porting the cpci405 platform support
from arch/ppc to arch/powerpc.
This patch also adds ibm405ep_fixup_clocks() to support
405EP CPUs from the boot wrapper.
Signed-off-by: Matthias Fuchs <matthias.fuchs@esd-electronics.com>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Diffstat (limited to 'arch/powerpc/boot/4xx.c')
-rw-r--r-- | arch/powerpc/boot/4xx.c | 81 |
1 files changed, 74 insertions, 7 deletions
diff --git a/arch/powerpc/boot/4xx.c b/arch/powerpc/boot/4xx.c index 33f25b671340..61a4045324cb 100644 --- a/arch/powerpc/boot/4xx.c +++ b/arch/powerpc/boot/4xx.c @@ -499,20 +499,45 @@ void ibm405gp_fixup_clocks(unsigned int sys_clk, 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 psr = mfdcr(DCRN_405_CPC0_PSR); u32 cpu, plb, opb, ebc, tb, uart0, uart1, m; - u32 fwdv, fbdv, cbdv, opdv, epdv, udiv; + u32 fwdv, fwdvb, fbdv, cbdv, opdv, epdv, ppdv, 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; + if (fbdv == 0) + fbdv = 16; + cbdv = ((pllmr & 0x00060000) >> 17) + 1; /* CPU:PLB */ + opdv = ((pllmr & 0x00018000) >> 15) + 1; /* PLB:OPB */ + ppdv = ((pllmr & 0x00001800) >> 13) + 1; /* PLB:PCI */ + epdv = ((pllmr & 0x00001800) >> 11) + 2; /* PLB:EBC */ udiv = ((cpc0_cr0 & 0x3e) >> 1) + 1; - m = fwdv * fbdv * cbdv; + /* check for 405GPr */ + if ((mfpvr() & 0xfffffff0) == (0x50910951 & 0xfffffff0)) { + fwdvb = 8 - (pllmr & 0x00000007); + if (!(psr & 0x00001000)) /* PCI async mode enable == 0 */ + if (psr & 0x00000020) /* New mode enable */ + m = fwdvb * 2 * ppdv; + else + m = fwdvb * cbdv * ppdv; + else if (psr & 0x00000020) /* New mode enable */ + if (psr & 0x00000800) /* PerClk synch mode */ + m = fwdvb * 2 * epdv; + else + m = fbdv * fwdv; + else if (epdv == fbdv) + m = fbdv * cbdv * epdv; + else + m = fbdv * fwdvb * cbdv; - cpu = sys_clk * m / fwdv; - plb = cpu / cbdv; + cpu = sys_clk * m / fwdv; + plb = sys_clk * m / (fwdvb * cbdv); + } else { + m = fwdv * fbdv * cbdv; + cpu = sys_clk * m / fwdv; + plb = cpu / cbdv; + } opb = plb / opdv; ebc = plb / epdv; @@ -541,3 +566,45 @@ void ibm405gp_fixup_clocks(unsigned int sys_clk, unsigned int ser_clk) dt_fixup_clock("/plb/opb/serial@ef600400", uart1); } + +void ibm405ep_fixup_clocks(unsigned int sys_clk) +{ + u32 pllmr0 = mfdcr(DCRN_CPC0_PLLMR0); + u32 pllmr1 = mfdcr(DCRN_CPC0_PLLMR1); + u32 cpc0_ucr = mfdcr(DCRN_CPC0_UCR); + u32 cpu, plb, opb, ebc, uart0, uart1; + u32 fwdva, fwdvb, fbdv, cbdv, opdv, epdv; + u32 pllmr0_ccdv, tb, m; + + fwdva = 8 - ((pllmr1 & 0x00070000) >> 16); + fwdvb = 8 - ((pllmr1 & 0x00007000) >> 12); + fbdv = (pllmr1 & 0x00f00000) >> 20; + if (fbdv == 0) + fbdv = 16; + + cbdv = ((pllmr0 & 0x00030000) >> 16) + 1; /* CPU:PLB */ + epdv = ((pllmr0 & 0x00000300) >> 8) + 2; /* PLB:EBC */ + opdv = ((pllmr0 & 0x00003000) >> 12) + 1; /* PLB:OPB */ + + m = fbdv * fwdvb; + + pllmr0_ccdv = ((pllmr0 & 0x00300000) >> 20) + 1; + if (pllmr1 & 0x80000000) + cpu = sys_clk * m / (fwdva * pllmr0_ccdv); + else + cpu = sys_clk / pllmr0_ccdv; + + plb = cpu / cbdv; + opb = plb / opdv; + ebc = plb / epdv; + tb = cpu; + uart0 = cpu / (cpc0_ucr & 0x0000007f); + uart1 = cpu / ((cpc0_ucr & 0x00007f00) >> 8); + + 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); +} |