summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu/mpc85xx/fdt.c2
-rw-r--r--cpu/mpc85xx/mp.c70
-rw-r--r--cpu/mpc85xx/mp.h3
-rw-r--r--cpu/mpc85xx/release.S34
-rw-r--r--include/asm-ppc/config.h10
5 files changed, 88 insertions, 31 deletions
diff --git a/cpu/mpc85xx/fdt.c b/cpu/mpc85xx/fdt.c
index efb6518..de2dcac 100644
--- a/cpu/mpc85xx/fdt.c
+++ b/cpu/mpc85xx/fdt.c
@@ -43,7 +43,7 @@ extern void ft_fixup_num_cores(void *blob);
void ft_fixup_cpu(void *blob, u64 memory_limit)
{
int off;
- ulong spin_tbl_addr = get_spin_addr();
+ ulong spin_tbl_addr = get_spin_phys_addr();
u32 bootpg = determine_mp_bootpg();
u32 id = get_my_id();
diff --git a/cpu/mpc85xx/mp.c b/cpu/mpc85xx/mp.c
index b5c6020..00b6450 100644
--- a/cpu/mpc85xx/mp.c
+++ b/cpu/mpc85xx/mp.c
@@ -52,10 +52,10 @@ int cpu_status(int nr)
u32 *table, id = get_my_id();
if (nr == id) {
- table = (u32 *)get_spin_addr();
+ table = (u32 *)get_spin_virt_addr();
printf("table base @ 0x%p\n", table);
} else {
- table = (u32 *)get_spin_addr() + nr * NUM_BOOT_ENTRY;
+ table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
printf("Running on cpu %d\n", id);
printf("\n");
printf("table @ 0x%p\n", table);
@@ -77,7 +77,7 @@ static u8 boot_entry_map[4] = {
int cpu_release(int nr, int argc, char *argv[])
{
- u32 i, val, *table = (u32 *)get_spin_addr() + nr * NUM_BOOT_ENTRY;
+ u32 i, val, *table = (u32 *)get_spin_virt_addr() + nr * NUM_BOOT_ENTRY;
u64 boot_addr;
if (nr == get_my_id()) {
@@ -124,23 +124,29 @@ u32 determine_mp_bootpg(void)
return (gd->ram_size - 4096);
}
-ulong get_spin_addr(void)
+ulong get_spin_phys_addr(void)
{
extern ulong __secondary_start_page;
extern ulong __spin_table;
- ulong addr =
- (ulong)&__spin_table - (ulong)&__secondary_start_page;
- addr += 0xfffff000;
+ return (determine_mp_bootpg() +
+ (ulong)&__spin_table - (ulong)&__secondary_start_page);
+}
+
+ulong get_spin_virt_addr(void)
+{
+ extern ulong __secondary_start_page;
+ extern ulong __spin_table;
- return addr;
+ return (CONFIG_BPTR_VIRT_ADDR +
+ (ulong)&__spin_table - (ulong)&__secondary_start_page);
}
#ifdef CONFIG_FSL_CORENET
static void plat_mp_up(unsigned long bootpg)
{
u32 up, cpu_up_mask, whoami;
- u32 *table = (u32 *)get_spin_addr();
+ u32 *table = (u32 *)get_spin_virt_addr();
volatile ccsr_gur_t *gur;
volatile ccsr_local_t *ccm;
volatile ccsr_rcpm_t *rcpm;
@@ -194,12 +200,23 @@ static void plat_mp_up(unsigned long bootpg)
mtspr(SPRN_TBWU, 0);
mtspr(SPRN_TBWL, 0);
out_be32(&rcpm->ctbenrl, (1 << nr_cpus) - 1);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
}
#else
static void plat_mp_up(unsigned long bootpg)
{
u32 up, cpu_up_mask, whoami;
- u32 *table = (u32 *)get_spin_addr();
+ u32 *table = (u32 *)get_spin_virt_addr();
volatile u32 bpcr;
volatile ccsr_local_ecm_t *ecm = (void *)(CONFIG_SYS_MPC85xx_ECM_ADDR);
volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
@@ -256,6 +273,17 @@ static void plat_mp_up(unsigned long bootpg)
devdisr &= ~(MPC85xx_DEVDISR_TB0 | MPC85xx_DEVDISR_TB1);
out_be32(&gur->devdisr, devdisr);
+
+#ifdef CONFIG_MPC8xxx_DISABLE_BPTR
+ /*
+ * Disabling Boot Page Translation allows the memory region 0xfffff000
+ * to 0xffffffff to be used normally. Leaving Boot Page Translation
+ * enabled remaps 0xfffff000 to SDRAM which makes that memory region
+ * unusable for normal operation but it does allow OSes to easily
+ * reset a processor core to put it back into U-Boot's spinloop.
+ */
+ clrbits_be32(&ecm->bptr, 0x80000000);
+#endif
}
#endif
@@ -269,33 +297,27 @@ void cpu_mp_lmb_reserve(struct lmb *lmb)
void setup_mp(void)
{
extern ulong __secondary_start_page;
+ extern ulong __bootpg_addr;
ulong fixup = (ulong)&__secondary_start_page;
u32 bootpg = determine_mp_bootpg();
+ /* Store the bootpg's SDRAM address for use by secondary CPU cores */
+ __bootpg_addr = bootpg;
+
/* look for the tlb covering the reset page, there better be one */
- int i = find_tlb_idx((void *)0xfffff000, 1);
+ int i = find_tlb_idx((void *)CONFIG_BPTR_VIRT_ADDR, 1);
/* we found a match */
if (i != -1) {
/* map reset page to bootpg so we can copy code there */
disable_tlb(i);
- set_tlb(1, 0xfffff000, bootpg, /* tlb, epn, rpn */
- MAS3_SX|MAS3_SW|MAS3_SR, MAS2_M, /* perms, wimge */
- 0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
-
- memcpy((void *)0xfffff000, (void *)fixup, 4096);
- flush_cache(0xfffff000, 4096);
-
- disable_tlb(i);
-
- /* setup reset page back to 1:1, we'll use HW boot translation
- * to map this where we want
- */
- set_tlb(1, 0xfffff000, 0xfffff000, /* tlb, epn, rpn */
+ set_tlb(1, CONFIG_BPTR_VIRT_ADDR, bootpg, /* tlb, epn, rpn */
MAS3_SX|MAS3_SW|MAS3_SR, MAS2_I, /* perms, wimge */
0, i, BOOKE_PAGESZ_4K, 1); /* ts, esel, tsize, iprot */
+ memcpy((void *)CONFIG_BPTR_VIRT_ADDR, (void *)fixup, 4096);
+
plat_mp_up(bootpg);
} else {
puts("WARNING: No reset page TLB. "
diff --git a/cpu/mpc85xx/mp.h b/cpu/mpc85xx/mp.h
index 2c2929e..3422cc1 100644
--- a/cpu/mpc85xx/mp.h
+++ b/cpu/mpc85xx/mp.h
@@ -3,7 +3,8 @@
#include <asm/mp.h>
-ulong get_spin_addr(void);
+ulong get_spin_phys_addr(void);
+ulong get_spin_virt_addr(void);
u32 get_my_id(void);
#define BOOT_ENTRY_ADDR_UPPER 0
diff --git a/cpu/mpc85xx/release.S b/cpu/mpc85xx/release.S
index ecbd0d5..a1ae78a 100644
--- a/cpu/mpc85xx/release.S
+++ b/cpu/mpc85xx/release.S
@@ -138,23 +138,38 @@ __secondary_start_page:
stw r3,ENTRY_R6_UPPER(r10)
stw r3,ENTRY_R6_LOWER(r10)
+ /* load r13 with the address of the 'bootpg' in SDRAM */
+ lis r13,toreset(__bootpg_addr)@h
+ ori r13,r13,toreset(__bootpg_addr)@l
+ lwz r13,0(r13)
+
/* setup mapping for AS = 1, and jump there */
lis r11,(MAS0_TLBSEL(1)|MAS0_ESEL(1))@h
mtspr SPRN_MAS0,r11
lis r11,(MAS1_VALID|MAS1_IPROT)@h
ori r11,r11,(MAS1_TS|MAS1_TSIZE(BOOKE_PAGESZ_4K))@l
mtspr SPRN_MAS1,r11
- lis r11,(0xfffff000|MAS2_I)@h
- ori r11,r11,(0xfffff000|MAS2_I)@l
+ oris r11,r13,(MAS2_I)@h
+ ori r11,r13,(MAS2_I)@l
mtspr SPRN_MAS2,r11
- lis r11,(0xfffff000|MAS3_SX|MAS3_SW|MAS3_SR)@h
- ori r11,r11,(0xfffff000|MAS3_SX|MAS3_SW|MAS3_SR)@l
+ oris r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h
+ ori r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l
mtspr SPRN_MAS3,r11
tlbwe
bl 1f
1: mflr r11
- addi r11,r11,28
+ /*
+ * OR in 0xfff to create a mask of the bootpg SDRAM address. We use
+ * this mask to fixup the cpu spin table and the address that we want
+ * to jump to, eg change them from 0xfffffxxx to 0x7ffffxxx if the
+ * bootpg is at 0x7ffff000 in SDRAM.
+ */
+ ori r13,r13,0xfff
+ and r11, r11, r13
+ and r10, r10, r13
+
+ addi r11,r11,(2f-1b)
mfmsr r13
ori r12,r13,MSR_IS|MSR_DS@l
@@ -227,6 +242,15 @@ __secondary_start_page:
mtspr SPRN_SRR1,r13
rfi
+ /*
+ * Allocate some space for the SDRAM address of the bootpg.
+ * This variable has to be in the boot page so that it can
+ * be accessed by secondary cores when they come out of reset.
+ */
+ .globl __bootpg_addr
+__bootpg_addr:
+ .long 0
+
.align L1_CACHE_SHIFT
.globl __spin_table
__spin_table:
diff --git a/include/asm-ppc/config.h b/include/asm-ppc/config.h
index eba7901..af0853b 100644
--- a/include/asm-ppc/config.h
+++ b/include/asm-ppc/config.h
@@ -47,6 +47,16 @@
#define CONFIG_MAX_CPUS 1
#endif
+/*
+ * Provide a default boot page translation virtual address that lines up with
+ * Freescale's default e500 reset page.
+ */
+#if (defined(CONFIG_E500) && defined(CONFIG_MP))
+#ifndef CONFIG_BPTR_VIRT_ADDR
+#define CONFIG_BPTR_VIRT_ADDR 0xfffff000
+#endif
+#endif
+
/* Relocation to SDRAM works on all PPC boards */
#define CONFIG_RELOC_FIXUP_WORKS