diff options
| author | York Sun <yorksun@freescale.com> | 2012-10-08 07:44:30 +0000 | 
|---|---|---|
| committer | Andy Fleming <afleming@freescale.com> | 2012-10-22 14:31:32 -0500 | 
| commit | ffd06e0231ac3fd0c5810f39f6e23527948df1c7 (patch) | |
| tree | 7d648c2c312b9cc7a75c0350101aacc67afca399 /arch/powerpc/cpu/mpc85xx/release.S | |
| parent | 3f0997b3255c1498ac92453aa3a7a1cc95914dfd (diff) | |
| download | olio-uboot-2014.01-ffd06e0231ac3fd0c5810f39f6e23527948df1c7.tar.xz olio-uboot-2014.01-ffd06e0231ac3fd0c5810f39f6e23527948df1c7.zip | |
powerpc/mpc85xx: Rewrite spin table to comply with ePAPR v1.1
Move spin table to cached memory to comply with ePAPR v1.1.
Load R3 with 64-bit value if CONFIG_SYS_PPC64 is defined.
'M' bit is set for DDR TLB to maintain cache coherence.
See details in doc/README.mpc85xx-spin-table.
Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
Diffstat (limited to 'arch/powerpc/cpu/mpc85xx/release.S')
| -rw-r--r-- | arch/powerpc/cpu/mpc85xx/release.S | 179 | 
1 files changed, 104 insertions, 75 deletions
| diff --git a/arch/powerpc/cpu/mpc85xx/release.S b/arch/powerpc/cpu/mpc85xx/release.S index d08b1f3dc..4ba44a902 100644 --- a/arch/powerpc/cpu/mpc85xx/release.S +++ b/arch/powerpc/cpu/mpc85xx/release.S @@ -150,10 +150,14 @@ __secondary_start_page:  #define toreset(x) (x - __secondary_start_page + 0xfffff000)  	/* get our PIR to figure out our table entry */ -	lis	r3,toreset(__spin_table)@h -	ori	r3,r3,toreset(__spin_table)@l +	lis	r3,toreset(__spin_table_addr)@h +	ori	r3,r3,toreset(__spin_table_addr)@l +	lwz	r3,0(r3) -	/* r10 has the base address for the entry */ +	/* +	 * r10 has the base address for the entry. +	 * we cannot access it yet before setting up a new TLB +	 */  	mfspr	r0,SPRN_PIR  #if	defined(CONFIG_E6500)  /* @@ -180,7 +184,7 @@ __secondary_start_page:  #else  	mr	r4,r0  #endif -	slwi	r8,r4,5 +	slwi	r8,r4,6	/* spin table is padded to 64 byte */  	add	r10,r3,r8  #ifdef CONFIG_E6500 @@ -277,73 +281,111 @@ __secondary_start_page:  	beq	2b  #endif  3: - -#define EPAPR_MAGIC		(0x45504150) -#define ENTRY_ADDR_UPPER	0 -#define ENTRY_ADDR_LOWER	4 -#define ENTRY_R3_UPPER		8 -#define ENTRY_R3_LOWER		12 -#define ENTRY_RESV		16 -#define ENTRY_PIR		20 -#define ENTRY_R6_UPPER		24 -#define ENTRY_R6_LOWER		28 -#define ENTRY_SIZE		32 - -	/* setup the entry */ -	li	r3,0 -	li	r8,1 -	stw	r4,ENTRY_PIR(r10) -	stw	r3,ENTRY_ADDR_UPPER(r10) -	stw	r8,ENTRY_ADDR_LOWER(r10) -	stw	r3,ENTRY_R3_UPPER(r10) -	stw	r4,ENTRY_R3_LOWER(r10) -	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 +	/* setup mapping for the spin table, WIMGE=0b00100 */ +	lis	r13,toreset(__spin_table_addr)@h +	ori	r13,r13,toreset(__spin_table_addr)@l  	lwz	r13,0(r13) +	/* mask by 4K */ +	rlwinm	r13,r13,0,0,19 -	/* 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 -	oris	r11,r13,(MAS2_I|MAS2_G)@h -	ori	r11,r13,(MAS2_I|MAS2_G)@l +	oris	r11,r13,(MAS2_M|MAS2_G)@h +	ori	r11,r13,(MAS2_M|MAS2_G)@l  	mtspr	SPRN_MAS2,r11  	oris	r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@h  	ori	r11,r13,(MAS3_SX|MAS3_SW|MAS3_SR)@l  	mtspr	SPRN_MAS3,r11 +	li	r11,0 +	mtspr	SPRN_MAS7,r11  	tlbwe -	bl	1f -1:	mflr	r11  	/* -	 * 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. +	 * __bootpg_addr has the address of __second_half_boot_page +	 * jump there in AS=1 space with cache enabled  	 */ -	ori	r13,r13,0xfff -	and	r11, r11, r13 -	and	r10, r10, r13 - -	addi	r11,r11,(2f-1b) +	lis	r13,toreset(__bootpg_addr)@h +	ori	r13,r13,toreset(__bootpg_addr)@l +	lwz	r11,0(r13) +	mtspr	SPRN_SRR0,r11  	mfmsr	r13  	ori	r12,r13,MSR_IS|MSR_DS@l - -	mtspr	SPRN_SRR0,r11  	mtspr	SPRN_SRR1,r12  	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. +	 */ +	.align L1_CACHE_SHIFT +	.globl __bootpg_addr +__bootpg_addr: +	.long	0 + +	.global __spin_table_addr +__spin_table_addr: +	.long	0 + +	/* +	 * This variable is set by cpu_init_r() after parsing hwconfig +	 * to enable workaround for erratum NMG_CPU_A011. +	 */ +	.align L1_CACHE_SHIFT +	.global enable_cpu_a011_workaround +enable_cpu_a011_workaround: +	.long	1 + +	/* Fill in the empty space.  The actual reset vector is +	 * the last word of the page */ +__secondary_start_code_end: +	.space 4092 - (__secondary_start_code_end - __secondary_start_page) +__secondary_reset_vector: +	b	__secondary_start_page + + +/* this is a separated page for the spin table and cacheable boot code */ +	.align L1_CACHE_SHIFT +	.global __second_half_boot_page +__second_half_boot_page: +#define EPAPR_MAGIC		0x45504150 +#define ENTRY_ADDR_UPPER	0 +#define ENTRY_ADDR_LOWER	4 +#define ENTRY_R3_UPPER		8 +#define ENTRY_R3_LOWER		12 +#define ENTRY_RESV		16 +#define ENTRY_PIR		20 +#define ENTRY_SIZE		64 +	/* +	 * setup the entry +	 * r10 has the base address of the spin table. +	 * spin table is defined as +	 * struct { +	 *	uint64_t entry_addr; +	 *	uint64_t r3; +	 *	uint32_t rsvd1; +	 *	uint32_t pir; +	 * }; +	 * we pad this struct to 64 bytes so each entry is in its own cacheline +	 */ +	li	r3,0 +	li	r8,1 +	mfspr	r4,SPRN_PIR +	stw	r3,ENTRY_ADDR_UPPER(r10) +	stw	r3,ENTRY_R3_UPPER(r10) +	stw	r4,ENTRY_R3_LOWER(r10) +	stw	r3,ENTRY_RESV(r10) +	stw	r4,ENTRY_PIR(r10) +	msync +	stw	r8,ENTRY_ADDR_LOWER(r10) +  	/* spin waiting for addr */ -2: -	lwz	r4,ENTRY_ADDR_LOWER(r10) +3:	lwz	r4,ENTRY_ADDR_LOWER(r10)  	andi.	r11,r4,1 -	bne	2b +	bne	3b  	isync  	/* setup IVORs to match fixed offsets */ @@ -362,8 +404,17 @@ __secondary_start_page:  	/* mask by ~64M to setup our tlb we will jump to */  	rlwinm	r12,r4,0,0,5 -	/* setup r3, r4, r5, r6, r7, r8, r9 */ +	/* +	 * setup r3, r4, r5, r6, r7, r8, r9 +	 * r3 contains the value to put in the r3 register at secondary cpu +	 * entry. The high 32-bits are ignored on 32-bit chip implementations. +	 * 64-bit chip implementations however shall load all 64-bits +	 */ +#ifdef CONFIG_SYS_PPC64 +	ld	r3,ENTRY_R3_UPPER(r10) +#else  	lwz	r3,ENTRY_R3_LOWER(r10) +#endif  	li	r4,0  	li	r5,0  	li	r6,0 @@ -404,32 +455,10 @@ __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 +	.align 6  	.globl __spin_table  __spin_table:  	.space CONFIG_MAX_CPUS*ENTRY_SIZE - -	/* -	 * This variable is set by cpu_init_r() after parsing hwconfig -	 * to enable workaround for erratum NMG_CPU_A011. -	 */ -	.align L1_CACHE_SHIFT -	.global enable_cpu_a011_workaround -enable_cpu_a011_workaround: -	.long	1 - -	/* Fill in the empty space.  The actual reset vector is -	 * the last word of the page */ -__secondary_start_code_end: -	.space 4092 - (__secondary_start_code_end - __secondary_start_page) -__secondary_reset_vector: -	b	__secondary_start_page +__spin_table_end: +	.space 4096 - (__spin_table_end - __spin_table) |