diff options
Diffstat (limited to 'arch/arm/cpu/arm1176/start.S')
| -rw-r--r-- | arch/arm/cpu/arm1176/start.S | 286 | 
1 files changed, 286 insertions, 0 deletions
| diff --git a/arch/arm/cpu/arm1176/start.S b/arch/arm/cpu/arm1176/start.S index f98a7aa35..e5e7913d9 100644 --- a/arch/arm/cpu/arm1176/start.S +++ b/arch/arm/cpu/arm1176/start.S @@ -95,6 +95,7 @@ _end_vect:   *************************************************************************   */ +.globl _TEXT_BASE  _TEXT_BASE:  	.word	TEXT_BASE @@ -106,9 +107,11 @@ _TEXT_BASE:  _TEXT_PHY_BASE:  	.word	CONFIG_SYS_PHY_UBOOT_BASE +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)  .globl _armboot_start  _armboot_start:  	.word _start +#endif  /*   * These are defined in the board-specific linker script. @@ -121,6 +124,275 @@ _bss_start:  _bss_end:  	.word _end +#if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: +	.word	0x0badc0de + +.globl _datarel_start +_datarel_start: +	.word __datarel_start + +.globl _datarelrolocal_start +_datarelrolocal_start: +	.word __datarelrolocal_start + +.globl _datarellocal_start +_datarellocal_start: +	.word __datarellocal_start + +.globl _datarelro_start +_datarelro_start: +	.word __datarelro_start + +.globl _got_start +_got_start: +	.word __got_start + +.globl _got_end +_got_end: +	.word __got_end + +/* + * the actual reset code + */ + +reset: +	/* +	 * set the cpu to SVC32 mode +	 */ +	mrs	r0, cpsr +	bic	r0, r0, #0x3f +	orr	r0, r0, #0xd3 +	msr	cpsr, r0 + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + * setup important registers + * setup memory timing + * + ************************************************************************* + */ +	/* +	 * we do sys-critical inits only at reboot, +	 * not when booting from ram! +	 */ +cpu_init_crit: +	/* +	 * When booting from NAND - it has definitely been a reset, so, no need +	 * to flush caches and disable the MMU +	 */ +#ifndef CONFIG_NAND_SPL +	/* +	 * flush v4 I/D caches +	 */ +	mov	r0, #0 +	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */ +	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */ + +	/* +	 * disable MMU stuff and caches +	 */ +	mrc	p15, 0, r0, c1, c0, 0 +	bic	r0, r0, #0x00002300	@ clear bits 13, 9:8 (--V- --RS) +	bic	r0, r0, #0x00000087	@ clear bits 7, 2:0 (B--- -CAM) +	orr	r0, r0, #0x00000002	@ set bit 2 (A) Align +	orr	r0, r0, #0x00001000	@ set bit 12 (I) I-Cache + +	/* Prepare to disable the MMU */ +	adr	r2, mmu_disable_phys +	sub	r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - TEXT_BASE) +	b	mmu_disable + +	.align 5 +	/* Run in a single cache-line */ +mmu_disable: +	mcr	p15, 0, r0, c1, c0, 0 +	nop +	nop +	mov	pc, r2 +mmu_disable_phys: + +#ifdef CONFIG_DISABLE_TCM +	/* +	 * Disable the TCMs +	 */ +	mrc	p15, 0, r0, c0, c0, 2	/* Return TCM details */ +	cmp	r0, #0 +	beq	skip_tcmdisable +	mov	r1, #0 +	mov	r2, #1 +	tst	r0, r2 +	mcrne	p15, 0, r1, c9, c1, 1	/* Disable Instruction TCM if present*/ +	tst	r0, r2, LSL #16 +	mcrne	p15, 0, r1, c9, c1, 0	/* Disable Data TCM if present*/ +skip_tcmdisable: +#endif +#endif + +#ifdef CONFIG_PERIPORT_REMAP +	/* Peri port setup */ +	ldr	r0, =CONFIG_PERIPORT_BASE +	orr	r0, r0, #CONFIG_PERIPORT_SIZE +	mcr	p15,0,r0,c15,c2,4 +#endif + +	/* +	 * Go setup Memory and board specific bits prior to relocation. +	 */ +	bl	lowlevel_init		/* go setup pll,mux,memory */ + +/* Set stackpointer in internal RAM to call board_init_f */ +call_board_init_f: +	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR) +	ldr	r0,=0x00000000 +	bl	board_init_f + +/*------------------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + */ +	.globl	relocate_code +relocate_code: +	mov	r4, r0	/* save addr_sp */ +	mov	r5, r1	/* save addr of gd */ +	mov	r6, r2	/* save addr of destination */ +	mov	r7, r2	/* save addr of destination */ + +	/* Set up the stack						    */ +stack_setup: +	mov	sp, r4 + +	adr	r0, _start +	ldr	r2, _TEXT_BASE +	ldr	r3, _bss_start +	sub	r2, r3, r2		/* r2 <- size of armboot	    */ +	add	r2, r0, r2		/* r2 <- source end address	    */ +	cmp	r0, r6 +	beq	clear_bss + +#ifndef CONFIG_SKIP_RELOCATE_UBOOT +copy_loop: +	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */ +	stmia	r6!, {r9-r10}		/* copy to   target address [r1]    */ +	cmp	r0, r2			/* until source end addreee [r2]    */ +	ble	copy_loop + +#ifndef CONFIG_PRELOADER +	/* fix got entries */ +	ldr	r1, _TEXT_BASE		/* Text base */ +	mov	r0, r7			/* reloc addr */ +	ldr	r2, _got_start		/* addr in Flash */ +	ldr	r3, _got_end		/* addr in Flash */ +	sub	r3, r3, r1 +	add	r3, r3, r0 +	sub	r2, r2, r1 +	add	r2, r2, r0 + +fixloop: +	ldr	r4, [r2] +	sub	r4, r4, r1 +	add	r4, r4, r0 +	str	r4, [r2] +	add	r2, r2, #4 +	cmp	r2, r3 +	bne	fixloop +#endif +#endif	/* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */ + +#ifdef CONFIG_ENABLE_MMU +enable_mmu: +	/* enable domain access */ +	ldr	r5, =0x0000ffff +	mcr	p15, 0, r5, c3, c0, 0	/* load domain access register */ + +	/* Set the TTB register */ +	ldr	r0, _mmu_table_base +	ldr	r1, =CONFIG_SYS_PHY_UBOOT_BASE +	ldr	r2, =0xfff00000 +	bic	r0, r0, r2 +	orr	r1, r0, r1 +	mcr	p15, 0, r1, c2, c0, 0 + +	/* Enable the MMU */ +	mrc	p15, 0, r0, c1, c0, 0 +	orr	r0, r0, #1		/* Set CR_M to enable MMU */ + +	/* Prepare to enable the MMU */ +	adr	r1, skip_hw_init +	and	r1, r1, #0x3fc +	ldr	r2, _TEXT_BASE +	ldr	r3, =0xfff00000 +	and	r2, r2, r3 +	orr	r2, r2, r1 +	b	mmu_enable + +	.align 5 +	/* Run in a single cache-line */ +mmu_enable: + +	mcr	p15, 0, r0, c1, c0, 0 +	nop +	nop +	mov	pc, r2 +skip_hw_init: +#endif + +clear_bss: +#ifndef CONFIG_PRELOADER +	ldr	r0, _bss_start +	ldr	r1, _bss_end +	ldr	r3, _TEXT_BASE		/* Text base */ +	mov	r4, r7			/* reloc addr */ +	sub	r0, r0, r3 +	add	r0, r0, r4 +	sub	r1, r1, r3 +	add	r1, r1, r4 +	mov	r2, #0x00000000		/* clear			    */ + +clbss_l:str	r2, [r0]		/* clear loop...		    */ +	add	r0, r0, #4 +	cmp	r0, r1 +	bne	clbss_l + +	bl coloured_LED_init +	bl red_LED_on +#endif + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +#ifdef CONFIG_NAND_SPL +	ldr     pc, _nand_boot + +_nand_boot: .word nand_boot +#else +	ldr	r0, _TEXT_BASE +	ldr	r2, _board_init_r +	sub	r2, r2, r0 +	add	r2, r2, r7	/* position from board_init_r in RAM */ +	/* setup parameters for board_init_r */ +	mov	r0, r5		/* gd_t */ +	mov	r1, r7		/* dest_addr */ +	/* jump to it ... */ +	mov	lr, r2 +	mov	pc, lr + +_board_init_r: .word board_init_r +#endif + +#else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ +  /*   * the actual reset code   */ @@ -299,6 +571,8 @@ _start_armboot:  /*	.word nand_boot*/  #endif +#endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */ +  #ifdef CONFIG_ENABLE_MMU  _mmu_table_base:  	.word mmu_table @@ -385,10 +659,14 @@ phy_last_jump:  	/* Save user registers (now in svc mode) r0-r12 */  	stmia	sp, {r0 - r12} +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)  	ldr	r2, _armboot_start  	sub	r2, r2, #(CONFIG_SYS_MALLOC_LEN)  	/* set base 2 words into abort stack */  	sub	r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) +#else +	ldr	r2, IRQ_STACK_START_IN +#endif  	/* get values for "aborted" pc and cpsr (into parm regs) */  	ldmia	r2, {r2 - r3}  	/* grab pointer to old stack */ @@ -403,12 +681,16 @@ phy_last_jump:  	.endm  	.macro get_bad_stack +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)  	/* setup our mode stack (enter in banked mode) */  	ldr	r13, _armboot_start  	/* move past malloc pool */  	sub	r13, r13, #(CONFIG_SYS_MALLOC_LEN)  	/* move to reserved a couple spots for abort stack */  	sub	r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) +#else +	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack +#endif  	/* save caller lr in position 0 of saved stack */  	str	lr, [r13] @@ -433,12 +715,16 @@ phy_last_jump:  	sub	r13, r13, #4  	/* save R0's value. */  	str	r0, [r13] +#if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)  	/* get data regions start */  	ldr	r0, _armboot_start  	/* move past malloc pool */  	sub	r0, r0, #(CONFIG_SYS_MALLOC_LEN)  	/* move past gbl and a couple spots for abort stack */  	sub	r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) +#else +	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack +#endif  	/* save caller lr in position 0 of saved stack */  	str	lr, [r0]  	/* get the spsr */ |