diff options
Diffstat (limited to 'arch/nds32/cpu/n1213/start.S')
-rw-r--r-- | arch/nds32/cpu/n1213/start.S | 120 |
1 files changed, 63 insertions, 57 deletions
diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S index 8b7f8f4540..7b2b637af3 100644 --- a/arch/nds32/cpu/n1213/start.S +++ b/arch/nds32/cpu/n1213/start.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ +.pic + #include <asm-offsets.h> #include <config.h> #include <common.h> @@ -116,6 +118,18 @@ IRQ_STACK_START_IN: */ reset: + +/* + * gp = ~0 for burn mode + * = ~load_address for load mode + */ +reset_gp: + .relax_hint 0 + sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) + .relax_hint 0 + ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) + add5.pc $gp + set_ivb: li $r0, 0x0 @@ -124,20 +138,31 @@ set_ivb: /* set IVIC, vector size: 4 bytes, base: 0x0 */ mtsr $r0, $ivb -load_lli: #ifndef CONFIG_SKIP_LOWLEVEL_INIT - jal load_lowlevel_init - jral $p0 + jal lowlevel_init +/* + * gp = ~VMA for burn mode + * = ~load_address for load mode + */ +update_gp: + .relax_hint 0 + sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_-8) + .relax_hint 0 + ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_-4) + add5.pc $gp #endif /* + * do critical initializations first (shall be in short time) + * do self_relocation ASAP. + */ + +/* * Set the N1213 (Whitiger) core to superuser mode * According to spec, it is already when reset */ -turnoff_wtdog: #ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG - jal load_turnoff_watchdog - jral $p0 + jal turnoff_watchdog #endif /* @@ -145,7 +170,7 @@ turnoff_wtdog: * not when booting from ram */ #ifdef CONFIG_INIT_CRITICAL - bal cpu_init_crit ! Do CPU critical regs init + jal cpu_init_crit ! Do CPU critical regs init #endif /* @@ -174,6 +199,11 @@ call_board_init_f: * after relocating the monitor code. * */ + +/* + * gp = ~RAM_SIZE - TEXT_SIZE for burn/load mode + */ + .globl relocate_code relocate_code: move $r4, $r0 /* save addr_sp */ @@ -184,49 +214,43 @@ relocate_code: stack_setup: move $sp, $r4 - la $r0, _start - + la $r0, _start@GOTOFF beq $r0, $r6, clear_bss /* skip relocation */ - move $r1, $r6 /* r1 <- scratch for copy_loop */ - la $r3, __bss_start - sub $r3, $r3, $r0 /* r3 <- __bss_start_ofs */ - add $r2, $r0, $r3 /* r2 <- source end address */ + la $r1, _end@GOTOFF + move $r2, $r6 /* r2 <- scratch for copy_loop */ copy_loop: lwi.p $r7, [$r0], #4 - swi.p $r7, [$r1], #4 - blt $r0, $r2, copy_loop + swi.p $r7, [$r2], #4 + blt $r0, $r1, copy_loop /* * fix relocations related issues */ fix_relocations: - l.w $r0, _TEXT_BASE /* r0 <- Text base */ - sub $r9, $r6, $r0 /* r9 <- relocation offset */ + l.w $r0, _TEXT_BASE@GOTOFF /* r0 <- Text base */ + sub $r9, $r6, $r0 /* r9 <- relocation offset */ + + la $r7, __rel_dyn_start@GOTOFF + add $r7, $r7, $r9 /* r2 <- rel __got_start in RAM */ + la $r8, __rel_dyn_end@GOTOFF + add $r8, $r8, $r9 /* r2 <- rel __got_start in RAM */ + li $r3, #0x2a /* R_NDS32_RELATIVE */ +1: + lmw.bim $r0, [$r7], $r2 /* r0,r1,r2 <- adr,type,addend */ + bne $r1, $r3, 2f -fix_got: -/* - * Now we want to update GOT. - * - * GOT[0] is reserved. GOT[1] is also reserved for the dynamic object - * generated by GNU ld. Skip these reserved entries from relocation. - */ - la $r2, __got_start /* r2 <- rel __got_start in FLASH */ - add $r2, $r2, $r9 /* r2 <- rel __got_start in RAM */ - la $r3, __got_end /* r3 <- rel __got_end in FLASH */ - add $r3, $r3, $r9 /* r3 <- rel __got_end in RAM */ - addi $r2, $r2, #8 /* skipping first two entries */ -fix_got_loop: - lwi $r0, [$r2] /* r0 <- location in FLASH to fix up */ - add $r0, $r0, $r9 /* r0 <- location fix up to RAM */ - swi.p $r0, [$r2], #4 /* r0 <- store fix into .got in RAM */ - blt $r2, $r3, fix_got_loop + add $r0, $r0, $r9 + add $r2, $r2, $r9 + sw $r2, [$r0] +2: + blt $r7, $r8, 1b clear_bss: - la $r0, __bss_start /* r0 <- rel __bss_start in FLASH */ + la $r0, __bss_start@GOTOFF /* r0 <- rel __bss_start in FLASH */ add $r0, $r0, $r9 /* r0 <- rel __bss_start in FLASH */ - la $r1, __bss_end /* r1 <- rel __bss_end in RAM */ + la $r1, __bss_end@GOTOFF /* r1 <- rel __bss_end in RAM */ add $r1, $r1, $r9 /* r0 <- rel __bss_end in RAM */ li $r2, 0x00000000 /* clear */ @@ -240,7 +264,7 @@ clbss_l: * initialization, now running from RAM. */ call_board_init_r: - la $r0, board_init_r + la $r0, board_init_r@GOTOFF move $lp, $r0 /* offset of board_init_r() */ add $lp, $lp, $r9 /* real address of board_init_r() */ /* setup parameters for board_init_r */ @@ -275,8 +299,8 @@ cpu_init_crit: /* Flush caches and TLB */ /* Invalidate caches */ - bal invalidate_icac - bal invalidate_dcac + jal invalidate_icac + jal invalidate_dcac /* Flush TLB */ mfsr $p0, $MMU_CFG @@ -299,24 +323,6 @@ cpu_init_crit: 2: ret -#ifndef CONFIG_SKIP_LOWLEVEL_INIT -load_lowlevel_init: - la $r6, lowlevel_init - la $r7, load_lli + 4 - sub $p0, $r6, $r7 - add $p0, $p0, $lp -ret -#endif - -#ifndef CONFIG_SKIP_TRUNOFF_WATCHDOG -load_turnoff_watchdog: - la $r6, turnoff_watchdog - la $r7, turnoff_wtdog + 4 - sub $p0, $r6, $r7 - add $p0, $p0, $lp -ret -#endif - /* * Invalidate I$ */ |