diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c index 45403641cfa03eca0a805e9482eda5137a1d9df2..53e059655483361c0e850842c17dd671d062381f 100644 --- a/arch/powerpc/cpu/mpc85xx/fdt.c +++ b/arch/powerpc/cpu/mpc85xx/fdt.c @@ -48,6 +48,7 @@ void ft_fixup_cpu(void *blob, u64 memory_limit) ulong spin_tbl_addr = get_spin_phys_addr(); u32 bootpg = determine_mp_bootpg(); u32 id = get_my_id(); + const char *enable_method; off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4); while (off != -FDT_ERR_NOTFOUND) { @@ -63,10 +64,25 @@ void ft_fixup_cpu(void *blob, u64 memory_limit) fdt_setprop_string(blob, off, "status", "disabled"); } + + if (hold_cores_in_reset(0)) { +#ifdef CONFIG_FSL_CORENET + /* Cores held in reset, use BRR to release */ + enable_method = "fsl,brr-holdoff"; +#else + /* Cores held in reset, use EEBPCR to release */ + enable_method = "fsl,eebpcr-holdoff"; +#endif + } else { + /* Cores out of reset and in a spin-loop */ + enable_method = "spin-table"; + + fdt_setprop(blob, off, "cpu-release-addr", + &val, sizeof(val)); + } + fdt_setprop_string(blob, off, "enable-method", - "spin-table"); - fdt_setprop(blob, off, "cpu-release-addr", - &val, sizeof(val)); + enable_method); } else { printf ("cpu NULL\n"); } diff --git a/arch/powerpc/cpu/mpc85xx/mp.c b/arch/powerpc/cpu/mpc85xx/mp.c index 603baef1bd493645ee62a0617fa83c8296acd61e..a019b1bdb13fd90bda59d6ba8edea90ff4cddf91 100644 --- a/arch/powerpc/cpu/mpc85xx/mp.c +++ b/arch/powerpc/cpu/mpc85xx/mp.c @@ -36,6 +36,27 @@ u32 get_my_id() return mfspr(SPRN_PIR); } +/* + * Determine if U-Boot should keep secondary cores in reset, or let them out + * of reset and hold them in a spinloop + */ +int hold_cores_in_reset(int verbose) +{ + const char *s = getenv("mp_holdoff"); + + /* Default to no, overriden by 'y', 'yes', 'Y', 'Yes', or '1' */ + if (s && (*s == 'y' || *s == 'Y' || *s == '1')) { + if (verbose) { + puts("Secondary cores are being held in reset.\n"); + puts("See 'mp_holdoff' environment variable\n"); + } + + return 1; + } + + return 0; +} + int cpu_reset(int nr) { volatile ccsr_pic_t *pic = (void *)(CONFIG_SYS_MPC8xxx_PIC_ADDR); @@ -51,6 +72,9 @@ int cpu_status(int nr) { u32 *table, id = get_my_id(); + if (hold_cores_in_reset(1)) + return 0; + if (nr == id) { table = (u32 *)get_spin_virt_addr(); printf("table base @ 0x%p\n", table); @@ -133,6 +157,9 @@ int cpu_release(int nr, int argc, char * const argv[]) u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY; u64 boot_addr; + if (hold_cores_in_reset(1)) + return 0; + if (nr == get_my_id()) { printf("Invalid to release the boot core.\n\n"); return 1; @@ -353,6 +380,10 @@ void setup_mp(void) ulong fixup = (ulong)&__secondary_start_page; u32 bootpg = determine_mp_bootpg(); + /* Some OSes expect secondary cores to be held in reset */ + if (hold_cores_in_reset(0)) + return; + /* Store the bootpg's SDRAM address for use by secondary CPU cores */ __bootpg_addr = bootpg; diff --git a/arch/powerpc/cpu/mpc85xx/mp.h b/arch/powerpc/cpu/mpc85xx/mp.h index 3422cc107009ac66582302b338da3f6a8671779b..87bac3715268df45949dc892f68d610450c1e17d 100644 --- a/arch/powerpc/cpu/mpc85xx/mp.h +++ b/arch/powerpc/cpu/mpc85xx/mp.h @@ -6,6 +6,7 @@ ulong get_spin_phys_addr(void); ulong get_spin_virt_addr(void); u32 get_my_id(void); +int hold_cores_in_reset(int verbose); #define BOOT_ENTRY_ADDR_UPPER 0 #define BOOT_ENTRY_ADDR_LOWER 1