
On PPC440EPx without a bootstrap I2C EEPROM, the PLL can be reconfigured after startup in order to change the speed of the clocks. This patch adds the option CONFIG_667MHZ. If set, it will set the clocks to run at full speed on a 667MHz PPC440EPx without the need for an external EEPROM.
Signed-off-by: Mike Nuss mike@terascala.com Cc: Stefan Roese sr@denx.de
diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index 2e0dd6f..14682c6 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -99,10 +99,21 @@ DECLARE_GLOBAL_DATA_PTR; # endif #endif /* CFG_INIT_DCACHE_CS */
+#if defined(CONFIG_440EPX) && defined(CONFIG_667MHZ) +#define PRBDV0 2 +#define FWDVA 2 +#define FWDVB 4 +#define FBDV 20 +#define LFBDV 1 +#define PERDV0 4 +#define SPCID0 4 +#endif + /* * Breath some life into the CPU... * - * Set up the memory map, + * Reconfigure PLL if necessary, + * set up the memory map, * initialize a bunch of registers */ void @@ -111,6 +122,78 @@ cpu_init_f (void) #if defined(CONFIG_WATCHDOG) unsigned long val; #endif +#if defined(CONFIG_440EPX) && defined(CONFIG_667MHZ) + int reset_needed = 0; + unsigned long reg, temp; + unsigned long prbdv0, fwdva, fwdvb, fbdv, lfbdv, perdv0, spcid0; + + /* Configure clocks and reset if necessary */ + + mfcpr(clk_primbd, reg); + temp = (reg & PRBDV_MASK) >> 24; + prbdv0 = temp ? temp : 8; + if (prbdv0 != PRBDV0) { + reg &= ~PRBDV_MASK; + reg |= ((PRBDV0 == 8 ? 0 : PRBDV0) << 24); + mtcpr(clk_primbd, reg); + reset_needed = 1; + } + + mfcpr(clk_plld, reg); + + temp = (reg & PLLD_FWDVA_MASK) >> 16; + fwdva = temp ? temp : 16; + + temp = (reg & PLLD_FWDVB_MASK) >> 8; + fwdvb = temp ? temp : 8; + + temp = (reg & PLLD_FBDV_MASK) >> 24; + fbdv = temp ? temp : 32; + + temp = (reg & PLLD_LFBDV_MASK); + lfbdv = temp ? temp : 64; + + if (fwdva != FWDVA || fbdv != FBDV || lfbdv != LFBDV) { + reg &= ~(PLLD_FWDVA_MASK | PLLD_FWDVB_MASK | + PLLD_FBDV_MASK | PLLD_LFBDV_MASK); + reg |= ((FWDVA == 16 ? 0 : FWDVA) << 16) | + ((FWDVB == 8 ? 0 : FWDVB) << 8) | + ((FBDV == 32 ? 0 : FBDV) << 24) | + (LFBDV == 64 ? 0 : LFBDV); + mtcpr(clk_plld, reg); + reset_needed = 1; + } + + mfcpr(clk_perd, reg); + perdv0 = (reg & CPR0_PERD_PERDV0_MASK) >> 24; + if (perdv0 != PERDV0) { + reg &= ~CPR0_PERD_PERDV0_MASK; + reg |= (PERDV0 << 24); + mtcpr(clk_perd, reg); + reset_needed = 1; + } + + mfcpr(clk_spcid, reg); + temp = (reg & CPR0_SPCID_SPCIDV0_MASK) >> 24; + spcid0 = temp ? temp : 4; + if (spcid0 != SPCID0) { + reg &= ~CPR0_SPCID_SPCIDV0_MASK; + reg |= ((SPCID0 == 4 ? 0 : SPCID0) << 24); + mtcpr(clk_spcid, reg); + reset_needed = 1; + } + + mfcpr(clk_icfg, reg); + reg &= ~CPR0_ICFG_RLI_MASK; + reg |= 1 << 31; + mtcpr(clk_icfg, reg); + + if (reset_needed) { + __asm__ __volatile__ ("sync; isync"); + mtspr(dbcr0, 0x20000000); /* Reset processor */ + } +#endif /* CONFIG_440EPX && CONFIG_667MHZ */ +
#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CFG_4xx_GPIO_TABLE) /*