[U-Boot] [PATCH v2 06/10] sparc: Reworked LEON3 startup for generic board-init
Francois Retief
fgretief at spaceteq.co.za
Wed Nov 5 13:08:19 CET 2014
Reworked the LEON3 startup 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 board_init_r.
Signed-off-by: Francois Retief <fgretief at spaceteq.co.za>
---
Changes in v2:
- Add snoop detect function to restore lost feature
arch/sparc/cpu/leon3/cpu_init.c | 13 +-
arch/sparc/cpu/leon3/start.S | 436 ++++++++++++++++++++++------------------
2 files changed, 248 insertions(+), 201 deletions(-)
diff --git a/arch/sparc/cpu/leon3/cpu_init.c b/arch/sparc/cpu/leon3/cpu_init.c
index 1144610..b0c7088 100644
--- a/arch/sparc/cpu/leon3/cpu_init.c
+++ b/arch/sparc/cpu/leon3/cpu_init.c
@@ -29,13 +29,23 @@ ambapp_dev_irqmp *irqmp = NULL;
ambapp_dev_mctrl memctrl;
ambapp_dev_gptimer *gptimer = NULL;
unsigned int gptimer_irq = 0;
-int leon3_snooping_avail = 0;
+int leon3_snooping_avail = 0; /* used by arch/sparc/cpu/leon3/usb_uhci.c */
struct {
gd_t gd_area;
bd_t bd;
} global_data;
+/* If CACHE snooping is available in hardware the result will be set
+ * to 0x800000, otherwise 0.
+ */
+static unsigned int snoop_detect(void)
+{
+ unsigned int result;
+ asm("lda [%%g0] 2, %0" : "=r"(result));
+ return result & 0x00800000;
+}
+
/*
* Breath some life into the CPU...
*
@@ -92,6 +102,7 @@ void cpu_init_f(void)
irqmp->cpu_force[0] = 0; /* no force IRQ on CPU 0 */
/* cache */
+ leon3_snooping_avail = snoop_detect();
}
#ifndef CONFIG_SYS_GENERIC_BOARD
diff --git a/arch/sparc/cpu/leon3/start.S b/arch/sparc/cpu/leon3/start.S
index cf897f6..5cd791c 100644
--- a/arch/sparc/cpu/leon3/start.S
+++ b/arch/sparc/cpu/leon3/start.S
@@ -179,15 +179,6 @@ _trap_table:
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f4-f7
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! f8-fb
SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; SOFT_TRAP; ! fc-ff
-/*
- * Version string
- */
-
- .data
- .extern leon3_snooping_avail
- .globl version_string
-version_string:
- .ascii U_BOOT_VERSION_STRING, "\0"
.section ".text"
.align 4
@@ -232,151 +223,237 @@ clear_window:
bge clear_window
save
-wininit:
+wiminit:
set WIM_INIT, %g3
mov %g3, %wim
-stackp:
+stack_init:
set CONFIG_SYS_INIT_SP_OFFSET, %fp
andn %fp, 0x0f, %fp
sub %fp, 64, %sp
+tbr_init:
+ set CONFIG_SYS_TEXT_BASE, %g2
+ wr %g0, %g2, %tbr
+ nop
+ nop
+ nop
+
+#ifdef CONFIG_TARGET_GR712RC_BOARD /* can't do this here, if we run from flash, we will be writing to flash! */
+clr_bss:
+ call 1f ! Use call to get hold of address for data table
+ nop
+ /* addresses of BSS segment */
+ .word __bss_start ! 0x08
+ .word __bss_end ! 0x0C
+1: ld [%o7+0x08], %g2 ! __bss_start
+ ld [%o7+0x0C], %g3 ! __bss_stop
+ /* clearing 16byte a time ==> linker script need to align to 16 byte offset */
+ clr %g1 /* std %g0 uses g0 and g1 */
+2: std %g0, [%g2]
+ std %g0, [%g2+8]
+ inc 16, %g2 ! ptr += 16
+ cmp %g2, %g3
+ bcs 2b ! while (ptr < end)
+ nop
+#endif
+
cpu_init_unreloc:
call cpu_init_f
- nop
+ nop
-/* un relocated start address of monitor */
-#define TEXT_START _text
-
-/* un relocated end address of monitor */
-#define DATA_END __init_end
-
-reloc:
- set TEXT_START,%g2
- set DATA_END,%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
-
- clr %l0
- clr %l1
- clr %l2
- clr %l3
- clr %g2
+board_init_unreloc:
+ call board_init_f
+ clr %o0 ! boot_flags
+
+dead:
+ mov 1, %g1 ! For GRMON2 to exit normally
+ ta 0 ! if call returns.. (unlikely)
+ nop
+
+!-------------------------------------------------------------------------------
-/* register g4 contain address to start
- * This means that BSS must be directly after data and code segments
+/*
+ * void relocate_code (addr_sp, gd, addr_moni)
*
- * g3 is length of bss = (__bss_end-__bss_start)
+ * This "function" does not return, instead it continues in RAM
+ * after relocating the monitor code.
*
+ * %i0 = Relocated stack pointer
+ * %i1 = Relocated global data pointer
+ * %i2 = Relocated text pointer
*/
-
-clr_bss:
-/* clear bss area (the relocated) */
- set __bss_start,%g2
- set __bss_end,%g3
- sub %g3,%g2,%g3
- add %g3,%g4,%g3
- 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
+ .globl relocate_code
+ .type relocate_code, #function
+relocate_code:
+ call 1f ! Use call to get hold of the actual address our data table
+ nop
+ /* final function to call */
+ .word board_init_r ! 0x00
+ /* start address of text segment */
+ .word _text ! 0x04
+ /* addresses of BSS segment */
+ .word __bss_start ! 0x08
+ .word __bss_end ! 0x0C
+ /* addresses of GOT segment */
+ .word __got_start ! 0x10
+ .word __got_end ! 0x14
+1:
+ add %o7, 0x08, %g5 ! data table address
+
+ /* disable traps */
+! mov %psr, %l0
+! and %l0, 0xFFFFFFDF, %l0
+! mov %l0, %psr
+
+ ! %o0 = Relocated stack pointer
+ ! %o1 = Relocated global data pointer
+ ! %o2 = Relocated text pointer
+ ! %o7 = Actual address of relocate_code
+
+ ! %g5 = Data table address
+ ! %g6 = Relocation offset
+
+_reloc:
+ ld [%g5+0x04], %g2 ! _text
+ sub %o2, %g2, %g6 ! relocation offset
+ ld [%g5+0x0C], %g3 ! __bss_stop
+ mov %o2, %g4 ! relocation pointer
+ /* copy text & bss to relocated address */
+10: ldd [%g2], %l0
+ ldd [%g2+8], %l2
+ std %l0, [%g4]
+ std %l2, [%g4+8]
+ inc 16, %g2
+ cmp %g2, %g3
+ bcs 10b ! while (ptr < end)
+ inc 16, %g4
+
+ /* add offsets to GOT table */
+_fixup_got:
+ ld [%g5+0x10], %g4 ! __got_start
+ add %g4, %g6, %g4
+ ld [%g5+0x14], %g3 ! __got_end
+ 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
+ cmp %g4, %g3
+ bcs 30b ! while (ptr < end)
+ nop
+
+ ! %o0 = stack pointer (relocated)
+ ! %o1 = global data pointer (relocated)
+ ! %o2 = text pointer (relocated)
+
+ ! %g5 = data table address
+ ! %g6 = relocation offset
+
+ /* Trap table has been moved, tell CPU about new trap table address */
+_update_trap_table_address:
+ wr %g0, %o2, %tbr
+ nop
+ nop
nop
-/* add offsets to GOT table */
-fixup_got:
- set __got_start,%g4
- set __got_end,%g3
+_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
+
+_jump_board_init_r:
+ mov %o1, %o0 ! relocated global data pointer
+ mov %o2, %o1 ! relocated text pointer
+
+ ld [%g5+0x00], %o3 ! board_init_r
+ add %o3, %g6, %o3 ! relocate address
+ call %o3
+ nop
+
+ mov 1, %g1 ! should not reach this point
+ ta 0
+ nop
+
+!-------------------------------------------------------------------------------
+
/*
- * new got offset = (old GOT-PTR (read with ld) -
- * CONFIG_SYS_RELOC_MONITOR_BASE(from define) ) +
- * Destination Address (from define)
+ * Window overflow trap handler
*/
- set CONFIG_SYS_RELOC_MONITOR_BASE,%g2
- set TEXT_START, %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
+ .global _window_overflow
+_window_overflow:
+ mov %wim, %l3 ! Calculate next WIM
+ sll %l3, (CONFIG_SYS_SPARC_NWINDOWS-1) , %l4
+ srl %l3, 1, %l3
+ or %l3, %l4, %l3
+
+ mov %g0, %wim ! Disable WIM traps
+ nop
+ nop
nop
-prom_relocate:
- set __prom_start, %g2
- set __prom_end, %g3
- set CONFIG_SYS_PROM_OFFSET, %g4
-
-prom_relocate_loop:
- ldd [%g2],%l0
- ldd [%g2+8],%l2
- std %l0,[%g4]
- std %l2,[%g4+8]
- inc 16,%g2
- subcc %g3,%g2,%g0
- bne prom_relocate_loop
- inc 16,%g4
-
-/* Trap table has been moved, lets tell CPU about
- * the new trap table address
- */
+ save ! Get into window to be saved
- set CONFIG_SYS_RELOC_MONITOR_BASE, %g2
- wr %g0, %g2, %tbr
+ std %l0, [%sp + 0] ! Save window to the stack
+ std %l2, [%sp + 8]
+ std %l4, [%sp + 16]
+ std %l6, [%sp + 24]
+ std %i0, [%sp + 32]
+ std %i2, [%sp + 40]
+ std %i4, [%sp + 48]
+ std %i6, [%sp + 56]
+
+ restore ! Go back to trap window
+
+ mov %l3, %wim ! Set new WIM trap
nop
nop
nop
-/* If CACHE snooping is available in hardware the
- * variable leon3_snooping_avail will be set to
- * 0x800000 else 0.
+ jmp %l1 ! Re-execute save
+ rett %l2
+
+!-------------------------------------------------------------------------------
+
+/*
+ * Window underflow trap handler
*/
-snoop_detect:
- sethi %hi(0x00800000), %o0
- lda [%g0] 2, %o1
- and %o0, %o1, %o0
- sethi %hi(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o1
- st %o0, [%lo(leon3_snooping_avail+CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE)+%o1]
-
-/* call relocate*/
+ .global _window_underflow
+_window_underflow:
+ mov %wim, %l3 ! Calculate next WIM
+ srl %l3, (CONFIG_SYS_SPARC_NWINDOWS-1), %l4
+ sll %l3, 1, %l3
+ or %l3, %l4, %l3
+
+ mov %l3, %wim ! set new value of window
+ nop
+ nop
nop
-/* Call relocated init functions */
-jump:
- set cpu_init_f2,%o1
- set CONFIG_SYS_RELOC_MONITOR_BASE,%o2
- add %o1,%o2,%o1
- sub %o1,%g1,%o1
- call %o1
- clr %o0
- set board_init_f,%o1
- set CONFIG_SYS_RELOC_MONITOR_BASE,%o2
- add %o1,%o2,%o1
- sub %o1,%g1,%o1
- call %o1
- clr %o0
+ restore ! Two restores to get into the
+ restore ! window to restore
-dead: ta 0 ! if call returns...
- nop
+ ldd [%sp + 0], %l0 ! Restore window from the stack
+ ldd [%sp + 8], %l2
+ ldd [%sp + 16], %l4
+ ldd [%sp + 24], %l6
+ ldd [%sp + 32], %i0
+ ldd [%sp + 40], %i2
+ ldd [%sp + 48], %i4
+ ldd [%sp + 56], %i6
+
+ save ! Get back to the trap window
+ save
+
+ jmp %l1 ! Re-execute restore
+ rett %l2
+
+!-------------------------------------------------------------------------------
/* Interrupt handler caller,
* reg L7: interrupt number
@@ -386,7 +463,25 @@ dead: ta 0 ! if call returns...
* reg L3: wim
*/
_irq_entry:
- SAVE_ALL
+ mov %o7, %l5 ! save original %o7
+ call 1f
+ ld [%o7+0x08], %l4 ! trap_setup
+ .word trap_setup ! 0x08
+#ifdef CONFIG_SYS_GENERIC_BOARD
+ .word _irq_entry ! 0x0c
+ !SAVE_ALL
+1:
+ ld [%o7+0x0C], %l6 ! _irq_entry
+ sub %o7, %l6, %l6 ! relocation offset (+4)
+ sub %l6, 4, %l6 ! relocation offset
+#else
+ .word handler_irq ! 0x0c
+ !SAVE_ALL
+1: set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %l6
+#endif
+ add %l4, %l6, %l4 ! relocated trap_setup
+ jmpl %l4, %l6
+ mov %l5, %o7 ! restore orignal %o7
or %l0, PSR_PIL, %g2
wr %g2, 0x0, %psr
@@ -394,10 +489,15 @@ _irq_entry:
wr %g2, PSR_ET, %psr
WRITE_PAUSE
mov %l7, %o0 ! irq level
- set handler_irq, %o1
+#ifdef CONFIG_SYS_GENERIC_BOARD
+ call handler_irq ! relative jump to handle_irq
+#else
+ sub %l6, 0x18, %o2 ! calculate _irq_entry address
+ ld [%o2 + 0x0c], %o1 ! handler_irq
set (CONFIG_SYS_RELOC_MONITOR_BASE-CONFIG_SYS_TEXT_BASE), %o2
add %o1, %o2, %o1
call %o1
+#endif
add %sp, SF_REGS_SZ, %o1 ! pt_regs ptr
or %l0, PSR_PIL, %g2 ! restore PIL after handler_irq
wr %g2, PSR_ET, %psr ! keep ET up
@@ -405,79 +505,9 @@ _irq_entry:
RESTORE_ALL
-!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
+!-------------------------------------------------------------------------------
- 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];
- restore ! Go back to trap window.
- mov %l7, %g1
- jmp %l1 ! Re-execute save.
- rett %l2
-
-/* 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
- nop; nop; nop
- restore ! Two restores to get into the
- restore ! window to restore
- ld [%sp + 0], %l0; ! Restore window from the stack
- ld [%sp + 4], %l1;
- ld [%sp + 8], %l2;
- ld [%sp + 12], %l3;
- ld [%sp + 16], %l4;
- ld [%sp + 20], %l5;
- ld [%sp + 24], %l6;
- ld [%sp + 28], %l7;
- ld [%sp + 32], %i0;
- ld [%sp + 36], %i1;
- ld [%sp + 40], %i2;
- ld [%sp + 44], %i3;
- ld [%sp + 48], %i4;
- ld [%sp + 52], %i5;
- ld [%sp + 56], %i6;
- ld [%sp + 60], %i7;
- save ! Get back to the trap window.
- save
- jmp %l1 ! Re-execute restore.
- rett %l2
-
- retl
_nmi_trap:
nop
@@ -597,6 +627,12 @@ ret_trap_entry:
* It resets the system by jumping to _start
*/
_reset_reloc:
- set start, %l0
+#if 1 /* DEBUG: When we run in GRMON, use the trap to exit normally. */
+ mov 1, %g1
+ ta 0 ! Cause program to exit normally in GRMON
+ nop
+#else
+ set CONFIG_SYS_RELOC_MONITOR_BASE, %l0
call %l0
- nop
+ nop
+#endif
--
1.9.3
________________________________
Disclaimer and confidentiality note – refer to our website for further details: www.spaceteq.co.za <http://www.spaceteq.co.za/home/emaildisclaimer/>
More information about the U-Boot
mailing list