X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=arch%2Farm%2Fcpu%2Farmv7%2Fstart.S;h=eee648bdc405f8ac8db7c0e4414f0c79c81d319f;hb=cdf1a2328a76cc57837d9a6e14a4f11f3a58b2e6;hp=1e0a1504bfc28a2ec413935c9464e63be1852ff5;hpb=b6c208ab1ebc2ac01e0029b8456210617ff67156;p=oweals%2Fu-boot.git diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index 1e0a1504bf..eee648bdc4 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -29,6 +29,7 @@ * MA 02111-1307 USA */ +#include #include #include @@ -65,23 +66,36 @@ _end_vect: * *************************************************************************/ +.globl _TEXT_BASE _TEXT_BASE: - .word TEXT_BASE + .word CONFIG_SYS_TEXT_BASE +#ifdef CONFIG_TEGRA2 +/* + * Tegra2 uses 2 separate CPUs - the AVP (ARM7TDMI) and the CPU (dual A9s). + * U-Boot runs on the AVP first, setting things up for the CPU (PLLs, + * muxes, clocks, clamps, etc.). Then the AVP halts, and expects the CPU + * to pick up its reset vector, which points here. + */ .globl _armboot_start _armboot_start: .word _start +#endif /* * These are defined in the board-specific linker script. */ -.globl _bss_start -_bss_start: - .word __bss_start +.globl _bss_start_ofs +_bss_start_ofs: + .word __bss_start - _start + +.globl _bss_end_ofs +_bss_end_ofs: + .word __bss_end__ - _start -.globl _bss_end -_bss_end: - .word _end +.globl _end_ofs +_end_ofs: + .word _end - _start #ifdef CONFIG_USE_IRQ /* IRQ stack memory (calculated at run-time) */ @@ -95,6 +109,11 @@ FIQ_STACK_START: .word 0x0badc0de #endif +/* IRQ stack memory (calculated at run-time) + 8 bytes */ +.globl IRQ_STACK_START_IN +IRQ_STACK_START_IN: + .word 0x0badc0de + /* * the actual reset code */ @@ -108,7 +127,7 @@ reset: orr r0, r0, #0xd3 msr cpsr,r0 -#if (CONFIG_OMAP34XX) +#if defined(CONFIG_OMAP34XX) /* Copy vectors to mask ROM indirect addr */ adr r0, _start @ r0 <- current position of code add r0, r0, #4 @ skip reset vector @@ -136,52 +155,135 @@ next: bl cpu_init_crit #endif -#ifndef CONFIG_SKIP_RELOCATE_UBOOT -relocate: @ relocate U-Boot to RAM - adr r0, _start @ r0 <- current position of code - ldr r1, _TEXT_BASE @ test if we run from flash or RAM - cmp r0, r1 @ don't reloc during debug - beq stack_setup +/* Set stackpointer in internal RAM to call board_init_f */ +call_board_init_f: + ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + ldr r0,=0x00000000 + bl board_init_f - ldr r2, _armboot_start - ldr r3, _bss_start - sub r2, r3, r2 @ r2 <- size of armboot - add r2, r0, r2 @ r2 <- source end address +/*------------------------------------------------------------------------------*/ -copy_loop: @ copy 32 bytes at a time - ldmia r0!, {r3 - r10} @ copy from source address [r0] - stmia r1!, {r3 - r10} @ copy to target address [r1] - cmp r0, r2 @ until source end addreee [r2] - ble copy_loop -#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ +/* + * 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 */ - /* Set up the stack */ + /* Set up the stack */ stack_setup: - ldr r0, _TEXT_BASE @ upper 128 KiB: relocated uboot - sub r0, r0, #CONFIG_SYS_MALLOC_LEN @ malloc area - sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE @ bdinfo -#ifdef CONFIG_USE_IRQ - sub r0, r0, #(CONFIG_STACKSIZE_IRQ + CONFIG_STACKSIZE_FIQ) + mov sp, r4 + + adr r0, _start +#ifndef CONFIG_PRELOADER + cmp r0, r6 + beq clear_bss /* skip relocation */ #endif - sub sp, r0, #12 @ leave 3 words for abort-stack - bic sp, sp, #7 @ 8-byte alignment for ABI compliance + mov r1, r6 /* r1 <- scratch for copy_loop */ + ldr r3, _bss_start_ofs + add r2, r0, r3 /* r2 <- source end address */ - /* Clear BSS (if any). Is below tx (watch load addr - need space) */ -clear_bss: - ldr r0, _bss_start @ find start of bss segment - ldr r1, _bss_end @ stop here - mov r2, #0x00000000 @ clear value -clbss_l: - str r2, [r0] @ clear BSS location - cmp r0, r1 @ are we at the end yet - add r0, r0, #4 @ increment clear index pointer - bne clbss_l @ keep clearing till at end +copy_loop: + ldmia r0!, {r9-r10} /* copy from source address [r0] */ + stmia r1!, {r9-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end address [r2] */ + blo copy_loop - ldr pc, _start_armboot @ jump to C code +#ifndef CONFIG_PRELOADER + /* + * fix .rel.dyn relocations + */ + ldr r0, _TEXT_BASE /* r0 <- Text base */ + sub r9, r6, r0 /* r9 <- relocation offset */ + ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */ + add r10, r10, r0 /* r10 <- sym table in FLASH */ + ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */ + add r2, r2, r0 /* r2 <- rel dyn start in FLASH */ + ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */ + add r3, r3, r0 /* r3 <- rel dyn end in FLASH */ +fixloop: + ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */ + add r0, r0, r9 /* r0 <- location to fix up in RAM */ + ldr r1, [r2, #4] + and r7, r1, #0xff + cmp r7, #23 /* relative fixup? */ + beq fixrel + cmp r7, #2 /* absolute fixup? */ + beq fixabs + /* ignore unknown type of fixup */ + b fixnext +fixabs: + /* absolute fix: set location to (offset) symbol value */ + mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */ + add r1, r10, r1 /* r1 <- address of symbol in table */ + ldr r1, [r1, #4] /* r1 <- symbol value */ + add r1, r1, r9 /* r1 <- relocated sym addr */ + b fixnext +fixrel: + /* relative fix: increase location by offset */ + ldr r1, [r0] + add r1, r1, r9 +fixnext: + str r1, [r0] + add r2, r2, #8 /* each rel.dyn entry is 8 bytes */ + cmp r2, r3 + blo fixloop -_start_armboot: .word start_armboot +clear_bss: + ldr r0, _bss_start_ofs + ldr r1, _bss_end_ofs + mov r4, r6 /* reloc addr */ + add r0, r0, r4 + 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 +#endif /* #ifndef CONFIG_PRELOADER */ +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +jump_2_ram: +/* + * If I-cache is enabled invalidate it + */ +#ifndef CONFIG_SYS_ICACHE_OFF + mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB +#endif + ldr r0, _board_init_r_ofs + adr r1, _start + add lr, r0, r1 + add lr, lr, r9 + /* setup parameters for board_init_r */ + mov r0, r5 /* gd_t */ + mov r1, r6 /* dest_addr */ + /* jump to it ... */ + mov pc, lr + +_board_init_r_ofs: + .word board_init_r - _start + +_rel_dyn_start_ofs: + .word __rel_dyn_start - _start +_rel_dyn_end_ofs: + .word __rel_dyn_end - _start +_dynsym_start_ofs: + .word __dynsym_start - _start +#ifndef CONFIG_SKIP_LOWLEVEL_INIT /************************************************************************* * * CPU_init_critical registers @@ -197,6 +299,9 @@ cpu_init_crit: mov r0, #0 @ set up for MCR mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs mcr p15, 0, r0, c7, c5, 0 @ invalidate icache + mcr p15, 0, r0, c7, c5, 6 @ invalidate BP array + mcr p15, 0, r0, c7, c10, 4 @ DSB + mcr p15, 0, r0, c7, c5, 4 @ ISB /* * disable MMU stuff and caches @@ -205,7 +310,12 @@ cpu_init_crit: bic r0, r0, #0x00002000 @ clear bits 13 (--V-) bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM) orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align - orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB + orr r0, r0, #0x00000800 @ set bit 11 (Z---) BTB +#ifdef CONFIG_SYS_ICACHE_OFF + bic r0, r0, #0x00001000 @ clear bit 12 (I) I-cache +#else + orr r0, r0, #0x00001000 @ set bit 12 (I) I-cache +#endif mcr p15, 0, r0, c1, c0, 0 /* @@ -218,6 +328,7 @@ cpu_init_crit: bl lowlevel_init @ go setup pll,mux,memory mov lr, ip @ restore link mov pc, lr @ back to my caller +#endif /* ************************************************************************* * @@ -263,10 +374,7 @@ cpu_init_crit: @ user stack stmia sp, {r0 - r12} @ Save user registers (now in @ svc mode) r0-r12 - - ldr r2, _armboot_start - sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) - sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ set base 2 words into abort + ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort @ stack ldmia r2, {r2 - r3} @ get values for "aborted" pc @ and cpsr (into parm regs) @@ -303,11 +411,8 @@ cpu_init_crit: .endm .macro get_bad_stack - ldr r13, _armboot_start @ setup our mode stack (enter + ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter @ in banked mode) - sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool - sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move to reserved a couple - @ spots for abort stack str lr, [r13] @ save caller lr in position 0 @ of saved stack @@ -328,9 +433,7 @@ cpu_init_crit: sub r13, r13, #4 @ space on current stack for @ scratch reg. str r0, [r13] @ save R0's value. - ldr r0, _armboot_start @ get data regions start - sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) @ move past malloc pool - sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) @ move past gbl and a couple + ldr r0, IRQ_STACK_START_IN @ get data regions start @ spots for abort stack str lr, [r0] @ save caller lr in position 0 @ of saved stack