X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Fpowerpc%2Fcpu%2Fppc4xx%2Fcpu_init.c;h=4013a0c24ae2aac5337172a819d80cf388f17250;hb=dc557e9a1fe00ca9d884bd88feef5bebf23fede4;hp=8a6e545c1aba8987fc3c651d7cfd22b8408108e2;hpb=9d62f20d0861ef87460d073dc189c851715b46ae;p=oweals%2Fu-boot.git diff --git a/arch/powerpc/cpu/ppc4xx/cpu_init.c b/arch/powerpc/cpu/ppc4xx/cpu_init.c index 8a6e545c1a..4013a0c24a 100644 --- a/arch/powerpc/cpu/ppc4xx/cpu_init.c +++ b/arch/powerpc/cpu/ppc4xx/cpu_init.c @@ -2,40 +2,42 @@ * (C) Copyright 2000-2007 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA + * SPDX-License-Identifier: GPL-2.0+ */ #include #include -#include +#include #include -#include -#include +#include +#include -#if defined(CONFIG_405GP) || defined(CONFIG_405EP) DECLARE_GLOBAL_DATA_PTR; -#endif #ifndef CONFIG_SYS_PLL_RECONFIG #define CONFIG_SYS_PLL_RECONFIG 0 #endif +#if defined(CONFIG_440EPX) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) +static void reset_with_rli(void) +{ + u32 reg; + + /* + * Set reload inhibit so configuration will persist across + * processor resets + */ + mfcpr(CPR0_ICFG, reg); + reg |= CPR0_ICFG_RLI_MASK; + mtcpr(CPR0_ICFG, reg); + + /* Reset processor if configuration changed */ + __asm__ __volatile__ ("sync; isync"); + mtspr(SPRN_DBCR0, 0x20000000); +} +#endif + void reconfigure_pll(u32 new_cpu_freq) { #if defined(CONFIG_440EPX) @@ -122,22 +124,28 @@ void reconfigure_pll(u32 new_cpu_freq) * 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); + /* + * Strapping option bits (ICS) are already in correct position, + * only masking needed. + */ + reg &= CPR0_ICFG_ICS_MASK; if ((reg == BOOT_STRAP_OPTION_A) || (reg == BOOT_STRAP_OPTION_B) || (reg == BOOT_STRAP_OPTION_D) || (reg == BOOT_STRAP_OPTION_E)) { + 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; + /* * Get current value of FWDVA. Assign current FWDVA to * new FWDVB. @@ -145,12 +153,14 @@ void reconfigure_pll(u32 new_cpu_freq) 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. */ @@ -161,28 +171,98 @@ void reconfigure_pll(u32 new_cpu_freq) ((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) { + /* Now reset the CPU if needed */ + if (reset_needed) + reset_with_rli(); +#endif + +#if defined(CONFIG_460EX) || defined(CONFIG_460GT) + u32 reg; + + /* + * See "9.2.1.1 Booting with Option E" in the 460EX/GT + * users manual + */ + mfcpr(CPR0_PLLC, reg); + if ((reg & (CPR0_PLLC_RST | CPR0_PLLC_ENG)) == CPR0_PLLC_RST) { /* - * Set reload inhibit so configuration will persist across - * processor resets + * Set engage bit */ - mfcpr(CPR0_ICFG, reg); - reg &= ~CPR0_ICFG_RLI_MASK; - reg |= 1 << 31; - mtcpr(CPR0_ICFG, reg); + reg = (reg & ~CPR0_PLLC_RST) | CPR0_PLLC_ENG; + mtcpr(CPR0_PLLC, reg); - /* Reset processor if configuration changed */ - __asm__ __volatile__ ("sync; isync"); - mtspr(SPRN_DBCR0, 0x20000000); + /* Now reset the CPU */ + reset_with_rli(); } #endif } +#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA +void +chip_21_errata(void) +{ + /* + * See rev 1.09 of the 405EX/405EXr errata. CHIP_21 says that + * sometimes reading the PVR and/or SDR0_ECID results in incorrect + * values. Since the rev-D chip uses the SDR0_ECID bits to control + * internal features, that means the second PCIe or ethernet of an EX + * variant could fail to work. Also, security features of both EX and + * EXr might be incorrectly disabled. + * + * The suggested workaround is as follows (covering rev-C and rev-D): + * + * 1.Read the PVR and SDR0_ECID3. + * + * 2.If the PVR matches an expected Revision C PVR value AND if + * SDR0_ECID3[12:15] is different from PVR[28:31], then processor is + * Revision C: continue executing the initialization code (no reset + * required). else go to step 3. + * + * 3.If the PVR matches an expected Revision D PVR value AND if + * SDR0_ECID3[10:11] matches its expected value, then continue + * executing initialization code, no reset required. else write + * DBCR0[RST] = 0b11 to generate a SysReset. + */ + + u32 pvr; + u32 pvr_28_31; + u32 ecid3; + u32 ecid3_10_11; + u32 ecid3_12_15; + + /* Step 1: */ + pvr = get_pvr(); + mfsdr(SDR0_ECID3, ecid3); + + /* Step 2: */ + pvr_28_31 = pvr & 0xf; + ecid3_10_11 = (ecid3 >> 20) & 0x3; + ecid3_12_15 = (ecid3 >> 16) & 0xf; + if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_C) && + (pvr_28_31 != ecid3_12_15)) { + /* No reset required. */ + return; + } + + /* Step 3: */ + if ((pvr == CONFIG_405EX_CHIP21_PVR_REV_D) && + (ecid3_10_11 == CONFIG_405EX_CHIP21_ECID3_REV_D)) { + /* No reset required. */ + return; + } + + /* Reset required. */ + __asm__ __volatile__ ("sync; isync"); + mtspr(SPRN_DBCR0, 0x30000000); +} +#endif + /* * Breath some life into the CPU... * @@ -197,9 +277,14 @@ cpu_init_f (void) u32 val; #endif +#ifdef CONFIG_SYS_4xx_CHIP_21_ERRATA + chip_21_errata(); +#endif + reconfigure_pll(CONFIG_SYS_PLL_RECONFIG); -#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && !defined(CONFIG_SYS_4xx_GPIO_TABLE) +#if (defined(CONFIG_405EP) || defined (CONFIG_405EX)) && \ + !defined(CONFIG_SYS_4xx_GPIO_TABLE) /* * GPIO0 setup (select GPIO or alternate function) */ @@ -228,7 +313,7 @@ cpu_init_f (void) /* * Set EMAC noise filter bits */ - mtdcr(CPC0_EPCTL, CPC0_EPRCSR_E0NFE | CPC0_EPRCSR_E1NFE); + mtdcr(CPC0_EPCTL, CPC0_EPCTL_E0NFE | CPC0_EPCTL_E1NFE); #endif /* CONFIG_405EP */ #if defined(CONFIG_SYS_4xx_GPIO_TABLE) @@ -239,7 +324,7 @@ cpu_init_f (void) * External Bus Controller (EBC) Setup */ #if (defined(CONFIG_SYS_EBC_PB0AP) && defined(CONFIG_SYS_EBC_PB0CR)) -#if (defined(CONFIG_405GP) || defined(CONFIG_405CR) || \ +#if (defined(CONFIG_405GP) || \ defined(CONFIG_405EP) || defined(CONFIG_405EZ) || \ defined(CONFIG_405EX) || defined(CONFIG_405)) /* @@ -303,7 +388,7 @@ cpu_init_f (void) #endif #if defined(CONFIG_WATCHDOG) - val = mfspr(tcr); + val = mfspr(SPRN_TCR); #if defined(CONFIG_440EP) || defined(CONFIG_440GR) val |= 0xb8000000; /* generate system reset after 1.34 seconds */ #elif defined(CONFIG_440EPX) @@ -315,11 +400,11 @@ cpu_init_f (void) val &= ~0x30000000; /* clear WRC bits */ val |= CONFIG_SYS_4xx_RESET_TYPE << 28; /* set board specific WRC type */ #endif - mtspr(tcr, val); + mtspr(SPRN_TCR, val); - val = mfspr(tsr); + val = mfspr(SPRN_TSR); val |= 0x80000000; /* enable watchdog timer */ - mtspr(tsr, val); + mtspr(SPRN_TSR, val); reset_4xx_watchdog(); #endif /* CONFIG_WATCHDOG */ @@ -359,10 +444,10 @@ cpu_init_f (void) /* * Set PLB4 arbiter (Segment 0 and 1) to 4 deep pipeline read */ - mtdcr(PLB0_ACR, (mfdcr(PLB0_ACR) & ~PLB0_ACR_RDP_MASK) | - PLB0_ACR_RDP_4DEEP); - mtdcr(PLB1_ACR, (mfdcr(PLB1_ACR) & ~PLB1_ACR_RDP_MASK) | - PLB1_ACR_RDP_4DEEP); + mtdcr(PLB4A0_ACR, (mfdcr(PLB4A0_ACR) & ~PLB4Ax_ACR_RDP_MASK) | + PLB4Ax_ACR_RDP_4DEEP); + mtdcr(PLB4A1_ACR, (mfdcr(PLB4A1_ACR) & ~PLB4Ax_ACR_RDP_MASK) | + PLB4Ax_ACR_RDP_4DEEP); #endif /* CONFIG_440SP/SPE || CONFIG_460EX/GT || CONFIG_405EX */ }