nds32: Support relocation.

Enable pie option for relocation.

Signed-off-by: rick <rick@andestech.com>
Cc: Andes <uboot@andestech.com>
diff --git a/arch/nds32/cpu/n1213/ag101/lowlevel_init.S b/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
index 1a94868..abdd340 100644
--- a/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
+++ b/arch/nds32/cpu/n1213/ag101/lowlevel_init.S
@@ -6,6 +6,8 @@
  * SPDX-License-Identifier:	GPL-2.0+
  */
 
+.pic
+
 .text
 
 #include <common.h>
@@ -248,16 +250,11 @@
     */
 	li	$r5, AHBC_BSR6_A
 	lwi $r8, [$r5]
-	li	$r4, 0xfff00000
+	li	$r4, 0xfff00000   /* r4 = bank6 base */
 	and $r4, $r4, $r8
 
-
-	li	$r5, 0x0
-	la	$r1, relo_base				/* get $pc or $lp */
-	sub	$r2, $r0, $r1
-	sethi	$r6, hi20(_end)
-	ori	$r6, $r6, lo12(_end)
-	add	$r6, $r6, $r2
+	la	$r5, _start@GOTOFF
+	la  $r6, _end@GOTOFF
 1:
 	lwi.p	$r7, [$r5], #4
 	swi.p	$r7, [$r4], #4
diff --git a/arch/nds32/cpu/n1213/start.S b/arch/nds32/cpu/n1213/start.S
index 8b7f8f4..7b2b637 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 @@
  */
 
 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 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 @@
  * 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 @@
  * 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 @@
 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 */
 
-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
+	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
+
+	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 @@
  * 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 @@
 
 	/* 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 @@
 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$
  */
diff --git a/arch/nds32/cpu/n1213/u-boot.lds b/arch/nds32/cpu/n1213/u-boot.lds
index b88d742..40db0e6 100644
--- a/arch/nds32/cpu/n1213/u-boot.lds
+++ b/arch/nds32/cpu/n1213/u-boot.lds
@@ -31,25 +31,28 @@
 
 	.got : {
 		__got_start = .;
-		 *(.got.plt) *(.got)
+		*(.got.plt) *(.got)
 		__got_end = .;
 	}
 
-	. = .;
-
 	. = ALIGN(4);
 	.u_boot_list : {
 		KEEP(*(SORT(.u_boot_list*)));
 	}
 
 	. = ALIGN(4);
-
+	/DISCARD/ : { *(.rela.plt*) }
+	.rela.dyn : {
+		__rel_dyn_start = .;
+		*(.rela*)
+		__rel_dyn_end = .;
+ }
 	_end = .;
 
 	.bss : {
 		__bss_start = .;
 		*(.bss)
-		 . = ALIGN(4);
+		. = ALIGN(4);
 		__bss_end = .;
 	}