sparc: leon3: Updates for generic board initialization
Reworked the LEON3 start.S code to call board_init_f function at startup.
Also implemented the relocate_code function in assembly to relocate the
monitor and setup the stack pointer before calling relocated board_init_r.
Add the CONFIG_SYS_GENERIC_BOARD variable to all the LEON3 boards.
Signed-off-by: Francois Retief <fgretief@spaceteq.co.za>
diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c
index 0ce2f89..9c76657 100644
--- a/arch/sparc/cpu/leon3/cpu_init.c
+++ b/arch/sparc/cpu/leon3/cpu_init.c
@@ -47,17 +47,6 @@
#endif
}
-/* Routine called from start.S,
- *
- * Run from FLASH/PROM:
- * - memory controller has already been setup up, stack can be used
- * - global variables available for read/writing
- * - constants avaiable
- */
-void cpu_init_f2(void)
-{
-}
-
/* If cache snooping is available in hardware the result will be set
* to 0x800000, otherwise 0.
*/
diff --git a/arch/sparc/cpu/leon3/start.S b/arch/sparc/cpu/leon3/start.S
index 1988ee1..52e82b5 100644
--- a/arch/sparc/cpu/leon3/start.S
+++ b/arch/sparc/cpu/leon3/start.S
@@ -257,11 +257,18 @@
set WIM_INIT, %g3
mov %g3, %wim
-stackp:
+stackinit:
set CONFIG_SYS_INIT_SP_OFFSET, %fp
andn %fp, 0x0f, %fp
sub %fp, 64, %sp
+tbrinit:
+ set CONFIG_SYS_TEXT_BASE, %g2
+ wr %g0, %g2, %tbr
+ nop
+ nop
+ nop
+
/* Obtain the address of _GLOBAL_OFFSET_TABLE_ */
SPARC_PIC_THUNK_CALL(l7)
@@ -298,25 +305,50 @@
call cpu_init_f
nop
-/* un relocated start address of monitor */
-#define TEXT_START _text
+board_init_unreloc:
+ call board_init_f
+ clr %o0 ! boot_flags
-/* un relocated end address of monitor */
-#define DATA_END __init_end
+dead_unreloc:
+ mov 1, %g1 ! For GRMON2 to exit normally.
+ ta 0 ! If board_init_f call returns.. (unlikely)
+ nop
+ nop
+ ba dead_unreloc ! infinte loop
+ nop
+!-------------------------------------------------------------------------------
+
+/* void relocate_code (addr_sp, gd, addr_moni)
+ *
+ * This "function" does not return, instead it continues in RAM after
+ * relocating the monitor code.
+ *
+ * %o0 = Relocated stack pointer
+ * %o1 = Relocated global data pointer
+ * %o2 = Relocated text pointer
+ *
+ * %l7 = _GLOBAL_OFFSET_TABLE_ address
+ */
+ .globl relocate_code
+ .type relocate_code, #function
+ .align 4
+relocate_code:
+ !SPARC_PIC_THUNK_CALL(l7)
reloc:
- SPARC_LOAD_ADDRESS(TEXT_START, l7, g2)
- SPARC_LOAD_ADDRESS(DATA_END, l7, g3)
- set CONFIG_SYS_RELOC_MONITOR_BASE,%g4
-reloc_loop:
- ldd [%g2],%l0
- ldd [%g2+8],%l2
- std %l0,[%g4]
- std %l2,[%g4+8]
- inc 16,%g2
- subcc %g3,%g2,%g0
- bne reloc_loop
- inc 16,%g4
+ SPARC_LOAD_ADDRESS(_text, l7, g2) ! start address of monitor
+ SPARC_LOAD_ADDRESS(__init_end, l7, g3) ! end address of monitor
+ mov %o2, %g4 ! relocation address
+ sub %g4, %g2, %g6 ! relocation offset
+ /* copy .text & .data to relocated address */
+10: ldd [%g2], %l0
+ ldd [%g2+8], %l2
+ std %l0, [%g4]
+ std %l2, [%g4+8]
+ inc 16, %g2 ! src += 16
+ cmp %g2, %g3
+ bcs 10b ! while (src < end)
+ inc 16, %g4 ! dst += 16
clr %l0
clr %l1
@@ -331,49 +363,42 @@
*
*/
+ /* clear the relocated .bss area */
clr_bss:
-/* clear bss area (the relocated) */
SPARC_LOAD_ADDRESS(__bss_start, l7, g2)
SPARC_LOAD_ADDRESS(__bss_end, l7, g3)
- sub %g3,%g2,%g3
+ sub %g3,%g2,%g3 ! length of .bss area
add %g3,%g4,%g3
+ /* clearing 16byte a time ==> linker script need to align to 16 byte offset */
clr %g1 /* std %g0 uses g0 and g1 */
-/* clearing 16byte a time ==> linker script need to align to 16 byte offset */
-clr_bss_16:
- std %g0,[%g4]
- std %g0,[%g4+8]
- inc 16,%g4
- cmp %g3,%g4
- bne clr_bss_16
+20:
+ std %g0, [%g4]
+ std %g0, [%g4+8]
+ inc 16, %g4 ! ptr += 16
+ cmp %g4, %g3
+ bcs 20b ! while (ptr < end)
nop
-/* add offsets to GOT table */
+ /* add offsets to GOT table */
fixup_got:
SPARC_LOAD_ADDRESS(__got_start, l7, g4)
+ add %g4, %g6, %g4
SPARC_LOAD_ADDRESS(__got_end, l7, g3)
-/*
- * new got offset = (old GOT-PTR (read with ld) -
- * CONFIG_SYS_RELOC_MONITOR_BASE(from define) ) +
- * Destination Address (from define)
- */
- set CONFIG_SYS_RELOC_MONITOR_BASE,%g2
- SPARC_LOAD_ADDRESS(TEXT_START, l7, g1)
- add %g4,%g2,%g4
- sub %g4,%g1,%g4
- add %g3,%g2,%g3
- sub %g3,%g1,%g3
- sub %g2,%g1,%g2 ! prepare register with (new base address) -
- ! (old base address)
-got_loop:
- ld [%g4],%l0 ! load old GOT-PTR
- add %l0,%g2,%l0 ! increase with (new base address) -
- ! (old base)
- st %l0,[%g4]
- inc 4,%g4
- cmp %g3,%g4
- bne got_loop
+ add %g3, %g6, %g3
+30: ld [%g4], %l0
+#ifdef CONFIG_RELOC_GOT_SKIP_NULL
+ cmp %l0, 0
+ be 32f
+#endif
+ add %l0, %g6, %l0 ! relocate GOT pointer
+ st %l0, [%g4]
+32: inc 4, %g4 ! ptr += 4
+ cmp %g4, %g3
+ bcs 30b ! while (ptr < end)
nop
+#if 0 /* FIXME: Relocated PROM address should be calculated! */
+
prom_relocate:
SPARC_LOAD_ADDRESS(__prom_start, l7, g2)
SPARC_LOAD_ADDRESS(__prom_end, l7, g3)
@@ -389,35 +414,46 @@
bne prom_relocate_loop
inc 16,%g4
+#endif
+
+! %o0 = stack pointer (relocated)
+! %o1 = global data pointer (relocated)
+! %o2 = text pointer (relocated)
+
+! %g6 = relocation offset
+! %l7 = _GLOBAL_OFFSET_TABLE_
+
/* Trap table has been moved, lets tell CPU about
* the new trap table address
*/
-
- set CONFIG_SYS_RELOC_MONITOR_BASE, %g2
- wr %g0, %g2, %tbr
+update_trap_table_address:
+ wr %g0, %o2, %tbr
nop
nop
nop
-/* Call relocated init functions */
-jump:
- SPARC_LOAD_ADDRESS(cpu_init_f2, l7, o1)
- set CONFIG_SYS_RELOC_MONITOR_BASE,%o2
- add %o1,%o2,%o1
- sub %o1,%g1,%o1
- call %o1
- clr %o0
+update_stack_pointers:
+ mov %o0, %fp
+ andn %fp, 0x0f, %fp ! align to 16 bytes
+ add %fp, -64, %fp ! make space for a window push
+ mov %fp, %sp ! setup stack pointer
- SPARC_LOAD_ADDRESS(board_init_f, l7, o1)
- set CONFIG_SYS_RELOC_MONITOR_BASE,%o2
- SPARC_LOAD_ADDRESS(TEXT_START, l7, g1)
- add %o1,%o2,%o1
- sub %o1,%g1,%o1
- call %o1
- clr %o0
+jump_board_init_r:
+ mov %o1, %o0 ! relocated global data pointer
+ mov %o2, %o1 ! relocated text pointer
+ SPARC_LOAD_ADDRESS(board_init_r, l7, o3)
+ add %o3, %g6, %o3 ! add relocation offset
+ call %o3
+ nop
-dead: ta 0 ! if call returns...
- nop
+dead:
+ mov 1, %g1 ! For GRMON2 to exit normally.
+ ta 0 ! if call returns.. (unlikely)
+ nop
+ b dead ! infinte loop
+ nop
+
+!------------------------------------------------------------------------------
/* Interrupt handler caller,
* reg L7: interrupt number
@@ -446,54 +482,56 @@
RESTORE_ALL
-!Window overflow trap handler.
+!------------------------------------------------------------------------------
+
+/*
+ * Window overflow trap handler
+ */
.global _window_overflow
_window_overflow:
mov %wim, %l3 ! Calculate next WIM
- mov %g1, %l7
- srl %l3, 1, %g1
- sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4
- or %l4, %g1, %g1
-
+ mov %g1, %l7
+ srl %l3, 1, %g1
+ sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4
+ or %g1, %l4, %g1
save ! Get into window to be saved.
- mov %g1, %wim
- nop;
- nop;
- nop
- st %l0, [%sp + 0];
- st %l1, [%sp + 4];
- st %l2, [%sp + 8];
- st %l3, [%sp + 12];
- st %l4, [%sp + 16];
- st %l5, [%sp + 20];
- st %l6, [%sp + 24];
- st %l7, [%sp + 28];
- st %i0, [%sp + 32];
- st %i1, [%sp + 36];
- st %i2, [%sp + 40];
- st %i3, [%sp + 44];
- st %i4, [%sp + 48];
- st %i5, [%sp + 52];
- st %i6, [%sp + 56];
- st %i7, [%sp + 60];
+ mov %g1, %wim
+ nop; nop; nop
+ st %l0, [%sp + 0] ! Save window to the stack
+ st %l1, [%sp + 4]
+ st %l2, [%sp + 8]
+ st %l3, [%sp + 12]
+ st %l4, [%sp + 16]
+ st %l5, [%sp + 20]
+ st %l6, [%sp + 24]
+ st %l7, [%sp + 28]
+ st %i0, [%sp + 32]
+ st %i1, [%sp + 36]
+ st %i2, [%sp + 40]
+ st %i3, [%sp + 44]
+ st %i4, [%sp + 48]
+ st %i5, [%sp + 52]
+ st %i6, [%sp + 56]
+ st %i7, [%sp + 60]
restore ! Go back to trap window.
- mov %l7, %g1
+ mov %l7, %g1
jmp %l1 ! Re-execute save.
- rett %l2
+ rett %l2
-/* Window underflow trap handler. */
-
+/*
+ * Window underflow trap handler
+ */
.global _window_underflow
_window_underflow:
- mov %wim, %l3 ! Calculate next WIM
- sll %l3, 1, %l4
- srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5
- or %l5, %l4, %l5
- mov %l5, %wim
+ mov %wim, %l3 ! Calculate next WIM
+ srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l5
+ sll %l3, 1, %l4
+ or %l5, %l4, %l5
+ mov %l5, %wim
nop; nop; nop
restore ! Two restores to get into the
restore ! window to restore
@@ -516,9 +554,9 @@
save ! Get back to the trap window.
save
jmp %l1 ! Re-execute restore.
- rett %l2
+ rett %l2
- retl
+!------------------------------------------------------------------------------
_nmi_trap:
nop
diff --git a/include/configs/gr_cpci_ax2000.h b/include/configs/gr_cpci_ax2000.h
index 67538d0..a16f59a 100644
--- a/include/configs/gr_cpci_ax2000.h
+++ b/include/configs/gr_cpci_ax2000.h
@@ -14,6 +14,8 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD
+
/*
* High Level Configuration Options
* (easy to change)
diff --git a/include/configs/gr_ep2s60.h b/include/configs/gr_ep2s60.h
index 387596d..f472179 100644
--- a/include/configs/gr_ep2s60.h
+++ b/include/configs/gr_ep2s60.h
@@ -15,6 +15,8 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD
+
/*
* High Level Configuration Options
* (easy to change)
diff --git a/include/configs/gr_xc3s_1500.h b/include/configs/gr_xc3s_1500.h
index 5fb800b..8598ac1 100644
--- a/include/configs/gr_xc3s_1500.h
+++ b/include/configs/gr_xc3s_1500.h
@@ -13,6 +13,8 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD
+
/*
* High Level Configuration Options
* (easy to change)
diff --git a/include/configs/grsim.h b/include/configs/grsim.h
index 932f330..e280dee 100644
--- a/include/configs/grsim.h
+++ b/include/configs/grsim.h
@@ -13,6 +13,8 @@
#ifndef __CONFIG_H__
#define __CONFIG_H__
+#define CONFIG_SYS_GENERIC_BOARD
+
/*
* High Level Configuration Options
* (easy to change)