diff options
| -rw-r--r-- | cpu/mpc85xx/fdt.c | 2 | ||||
| -rw-r--r-- | cpu/mpc85xx/mp.c | 70 | ||||
| -rw-r--r-- | cpu/mpc85xx/mp.h | 3 | ||||
| -rw-r--r-- | cpu/mpc85xx/release.S | 34 | ||||
| -rw-r--r-- | include/asm-ppc/config.h | 10 | 
5 files changed, 88 insertions, 31 deletions
| diff --git a/cpu/mpc85xx/fdt.c b/cpu/mpc85xx/fdt.c index efb651882..de2dcac81 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 b5c6020c7..00b645069 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 2c2929eb0..3422cc107 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 ecbd0d585..a1ae78a7f 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 eba79010b..af0853b0d 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 |