From c550afada5fcad426aa6a219a329feb9eedae8b2 Mon Sep 17 00:00:00 2001 From: Rupjyoti Sarmah Date: Wed, 24 Mar 2010 16:52:02 +0530 Subject: ppc4xx fix unstable 440EPx bootstrap options 440EPx fixed bootstrap options A, B, D, and E sets PLL FWDVA to a value = 1. This results in the PLLOUTB being greater than the CPU clock frequency resulting unstable 440EPx operation resulting in various software hang conditions. This patch reprograms the FWDVA satisfying the requirement of setting FWDVB to a value greater than 1 while using one of the four deafult bootstrap options. Signed-off-by: Rupjyoti Sarmah Acked-by : Victor Gallardo Signed-off-by: Stefan Roese --- cpu/ppc4xx/cpu_init.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++---- include/ppc440.h | 6 +++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index ccd9993677..8a6e545c1a 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -111,17 +111,72 @@ void reconfigure_pll(u32 new_cpu_freq) mtcpr(CPR0_SPCID, reg); reset_needed = 1; } + } + + /* Get current value of FWDVA.*/ + mfcpr(CPR0_PLLD, reg); + temp = (reg & PLLD_FWDVA_MASK) >> 16; - /* Set reload inhibit so configuration will persist across - * processor resets */ + /* + * Check to see if FWDVA has been set to value of 1. if it has we must + * modify it. + */ + if (temp == 1) { + mfcpr(CPR0_PLLD, reg); + /* Get current value of fbdv. */ + temp = (reg & PLLD_FBDV_MASK) >> 24; + fbdv = temp ? temp : 32; + /* Get current value of lfbdv. */ + temp = (reg & PLLD_LFBDV_MASK); + lfbdv = temp ? temp : 64; + /* + * Load register that contains current boot strapping option. + */ + mfcpr(CPR0_ICFG, reg); + /* Shift strapping option into low 3 bits.*/ + reg = (reg >> 28); + + if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) || + (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) { + /* + * Get current value of FWDVA. Assign current FWDVA to + * new FWDVB. + */ + mfcpr(CPR0_PLLD, reg); + target_fwdvb = (reg & PLLD_FWDVA_MASK) >> 16; + fwdvb = target_fwdvb ? target_fwdvb : 8; + /* + * Get current value of FWDVB. Assign current FWDVB to + * new FWDVA. + */ + target_fwdva = (reg & PLLD_FWDVB_MASK) >> 8; + fwdva = target_fwdva ? target_fwdva : 16; + /* + * Update CPR0_PLLD with switched FWDVA and FWDVB. + */ + 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(CPR0_PLLD, reg); + /* Acknowledge that a reset is required. */ + reset_needed = 1; + } + } + + if (reset_needed) { + /* + * Set reload inhibit so configuration will persist across + * processor resets + */ mfcpr(CPR0_ICFG, reg); reg &= ~CPR0_ICFG_RLI_MASK; reg |= 1 << 31; mtcpr(CPR0_ICFG, reg); - } - /* Reset processor if configuration changed */ - if (reset_needed) { + /* Reset processor if configuration changed */ __asm__ __volatile__ ("sync; isync"); mtspr(SPRN_DBCR0, 0x20000000); } diff --git a/include/ppc440.h b/include/ppc440.h index e60fa13905..5f87d2c600 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -68,6 +68,12 @@ #define CPR0_SPCID 0x0120 #define CPR0_ICFG 0x0140 +/* 440EPX boot strap options */ +#define BOOT_STRAP_OPTION_A 0x00000000 +#define BOOT_STRAP_OPTION_B 0x00000001 +#define BOOT_STRAP_OPTION_D 0x00000003 +#define BOOT_STRAP_OPTION_E 0x00000004 + /* 440gx sdr register definations */ #define SDR0_SDSTP0 0x0020 /* */ #define SDR0_SDSTP1 0x0021 /* */ -- cgit