|
@@ -58,54 +58,58 @@
|
|
|
.globl _start
|
|
|
_start:
|
|
|
b reset
|
|
|
-#ifdef CONFIG_SPL_BUILD
|
|
|
-/* No exception handlers in preloader */
|
|
|
- ldr pc, _hang
|
|
|
- ldr pc, _hang
|
|
|
- ldr pc, _hang
|
|
|
- ldr pc, _hang
|
|
|
- b reset
|
|
|
- ldr pc, _hang
|
|
|
- ldr pc, _hang
|
|
|
+ b undefined_instruction
|
|
|
+ b software_interrupt
|
|
|
+ b prefetch_abort
|
|
|
+ b data_abort
|
|
|
+ b not_used
|
|
|
+ b irq
|
|
|
+ b fiq
|
|
|
|
|
|
-_hang:
|
|
|
- .word do_hang
|
|
|
-/* pad to 64 byte boundary */
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
- .word 0x12345678
|
|
|
-#else
|
|
|
- ldr pc, _undefined_instruction
|
|
|
- ldr pc, _software_interrupt
|
|
|
- ldr pc, _prefetch_abort
|
|
|
- ldr pc, _data_abort
|
|
|
- ldr pc, _not_used
|
|
|
- ldr pc, _irq
|
|
|
- ldr pc, _fiq
|
|
|
+/*
|
|
|
+ * Vector table, located at address 0x20.
|
|
|
+ * This table allows the code running AFTER SPL, the U-Boot, to install it's
|
|
|
+ * interrupt handlers here. The problem is that the U-Boot is loaded into RAM,
|
|
|
+ * including it's interrupt vectoring table and the table at 0x0 is still the
|
|
|
+ * SPLs. So if interrupt happens in U-Boot, the SPLs interrupt vectoring table
|
|
|
+ * is still used.
|
|
|
+ */
|
|
|
+_vt_reset:
|
|
|
+ .word _reset
|
|
|
+_vt_undefined_instruction:
|
|
|
+ .word _hang
|
|
|
+_vt_software_interrupt:
|
|
|
+ .word _hang
|
|
|
+_vt_prefetch_abort:
|
|
|
+ .word _hang
|
|
|
+_vt_data_abort:
|
|
|
+ .word _hang
|
|
|
+_vt_not_used:
|
|
|
+ .word _reset
|
|
|
+_vt_irq:
|
|
|
+ .word _hang
|
|
|
+_vt_fiq:
|
|
|
+ .word _hang
|
|
|
|
|
|
-_undefined_instruction:
|
|
|
- .word undefined_instruction
|
|
|
-_software_interrupt:
|
|
|
- .word software_interrupt
|
|
|
-_prefetch_abort:
|
|
|
- .word prefetch_abort
|
|
|
-_data_abort:
|
|
|
- .word data_abort
|
|
|
-_not_used:
|
|
|
- .word not_used
|
|
|
-_irq:
|
|
|
- .word irq
|
|
|
-_fiq:
|
|
|
- .word fiq
|
|
|
+reset:
|
|
|
+ ldr pc, _vt_reset
|
|
|
+undefined_instruction:
|
|
|
+ ldr pc, _vt_undefined_instruction
|
|
|
+software_interrupt:
|
|
|
+ ldr pc, _vt_software_interrupt
|
|
|
+prefetch_abort:
|
|
|
+ ldr pc, _vt_prefetch_abort
|
|
|
+data_abort:
|
|
|
+ ldr pc, _vt_data_abort
|
|
|
+not_used:
|
|
|
+ ldr pc, _vt_not_used
|
|
|
+irq:
|
|
|
+ ldr pc, _vt_irq
|
|
|
+fiq:
|
|
|
+ ldr pc, _vt_fiq
|
|
|
|
|
|
-#endif /* CONFIG_SPL_BUILD */
|
|
|
.balignl 16,0xdeadbeef
|
|
|
|
|
|
-
|
|
|
/*
|
|
|
*************************************************************************
|
|
|
*
|
|
@@ -162,7 +166,7 @@ IRQ_STACK_START_IN:
|
|
|
* the actual reset code
|
|
|
*/
|
|
|
|
|
|
-reset:
|
|
|
+_reset:
|
|
|
/*
|
|
|
* Store all registers on old stack pointer, this will allow us later to
|
|
|
* return to the BootROM and let the BootROM load U-Boot into RAM.
|
|
@@ -220,177 +224,11 @@ cpu_init_crit:
|
|
|
mcr p15, 0, r0, c1, c0, 0
|
|
|
|
|
|
mov pc, lr /* back to my caller */
|
|
|
-#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
|
|
|
-
|
|
|
-#ifndef CONFIG_SPL_BUILD
|
|
|
-/*
|
|
|
- *************************************************************************
|
|
|
- *
|
|
|
- * Interrupt handling
|
|
|
- *
|
|
|
- *************************************************************************
|
|
|
- */
|
|
|
-
|
|
|
-@
|
|
|
-@ IRQ stack frame.
|
|
|
-@
|
|
|
-#define S_FRAME_SIZE 72
|
|
|
-
|
|
|
-#define S_OLD_R0 68
|
|
|
-#define S_PSR 64
|
|
|
-#define S_PC 60
|
|
|
-#define S_LR 56
|
|
|
-#define S_SP 52
|
|
|
-
|
|
|
-#define S_IP 48
|
|
|
-#define S_FP 44
|
|
|
-#define S_R10 40
|
|
|
-#define S_R9 36
|
|
|
-#define S_R8 32
|
|
|
-#define S_R7 28
|
|
|
-#define S_R6 24
|
|
|
-#define S_R5 20
|
|
|
-#define S_R4 16
|
|
|
-#define S_R3 12
|
|
|
-#define S_R2 8
|
|
|
-#define S_R1 4
|
|
|
-#define S_R0 0
|
|
|
-
|
|
|
-#define MODE_SVC 0x13
|
|
|
-#define I_BIT 0x80
|
|
|
-
|
|
|
-/*
|
|
|
- * use bad_save_user_regs for abort/prefetch/undef/swi ...
|
|
|
- * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
|
|
|
- */
|
|
|
-
|
|
|
- .macro bad_save_user_regs
|
|
|
- @ carve out a frame on current user stack
|
|
|
- sub sp, sp, #S_FRAME_SIZE
|
|
|
- stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
|
|
|
- ldr r2, IRQ_STACK_START_IN
|
|
|
- @ get values for "aborted" pc and cpsr (into parm regs)
|
|
|
- ldmia r2, {r2 - r3}
|
|
|
- add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
|
|
|
- add r5, sp, #S_SP
|
|
|
- mov r1, lr
|
|
|
- stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
|
|
|
- mov r0, sp @ save current stack into r0 (param register)
|
|
|
- .endm
|
|
|
-
|
|
|
- .macro irq_save_user_regs
|
|
|
- sub sp, sp, #S_FRAME_SIZE
|
|
|
- stmia sp, {r0 - r12} @ Calling r0-r12
|
|
|
- @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
|
|
|
- add r8, sp, #S_PC
|
|
|
- stmdb r8, {sp, lr}^ @ Calling SP, LR
|
|
|
- str lr, [r8, #0] @ Save calling PC
|
|
|
- mrs r6, spsr
|
|
|
- str r6, [r8, #4] @ Save CPSR
|
|
|
- str r0, [r8, #8] @ Save OLD_R0
|
|
|
- mov r0, sp
|
|
|
- .endm
|
|
|
-
|
|
|
- .macro irq_restore_user_regs
|
|
|
- ldmia sp, {r0 - lr}^ @ Calling r0 - lr
|
|
|
- mov r0, r0
|
|
|
- ldr lr, [sp, #S_PC] @ Get PC
|
|
|
- add sp, sp, #S_FRAME_SIZE
|
|
|
- subs pc, lr, #4 @ return & move spsr_svc into cpsr
|
|
|
- .endm
|
|
|
-
|
|
|
- .macro get_bad_stack
|
|
|
- ldr r13, IRQ_STACK_START_IN @ setup our mode stack
|
|
|
-
|
|
|
- str lr, [r13] @ save caller lr in position 0 of saved stack
|
|
|
- mrs lr, spsr @ get the spsr
|
|
|
- str lr, [r13, #4] @ save spsr in position 1 of saved stack
|
|
|
- mov r13, #MODE_SVC @ prepare SVC-Mode
|
|
|
- @ msr spsr_c, r13
|
|
|
- msr spsr, r13 @ switch modes, make sure moves will execute
|
|
|
- mov lr, pc @ capture return pc
|
|
|
- movs pc, lr @ jump to next instruction & switch modes.
|
|
|
- .endm
|
|
|
-
|
|
|
- .macro get_irq_stack @ setup IRQ stack
|
|
|
- ldr sp, IRQ_STACK_START
|
|
|
- .endm
|
|
|
-
|
|
|
- .macro get_fiq_stack @ setup FIQ stack
|
|
|
- ldr sp, FIQ_STACK_START
|
|
|
- .endm
|
|
|
-#endif /* CONFIG_SPL_BUILD */
|
|
|
|
|
|
-/*
|
|
|
- * exception handlers
|
|
|
- */
|
|
|
-#ifdef CONFIG_SPL_BUILD
|
|
|
.align 5
|
|
|
-do_hang:
|
|
|
+#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
|
|
|
+
|
|
|
+_hang:
|
|
|
ldr sp, _TEXT_BASE /* switch to abort stack */
|
|
|
1:
|
|
|
bl 1b /* hang and never return */
|
|
|
-#else /* !CONFIG_SPL_BUILD */
|
|
|
- .align 5
|
|
|
-undefined_instruction:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_undefined_instruction
|
|
|
-
|
|
|
- .align 5
|
|
|
-software_interrupt:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_software_interrupt
|
|
|
-
|
|
|
- .align 5
|
|
|
-prefetch_abort:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_prefetch_abort
|
|
|
-
|
|
|
- .align 5
|
|
|
-data_abort:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_data_abort
|
|
|
-
|
|
|
- .align 5
|
|
|
-not_used:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_not_used
|
|
|
-
|
|
|
-#ifdef CONFIG_USE_IRQ
|
|
|
-
|
|
|
- .align 5
|
|
|
-irq:
|
|
|
- get_irq_stack
|
|
|
- irq_save_user_regs
|
|
|
- bl do_irq
|
|
|
- irq_restore_user_regs
|
|
|
-
|
|
|
- .align 5
|
|
|
-fiq:
|
|
|
- get_fiq_stack
|
|
|
- /* someone ought to write a more effiction fiq_save_user_regs */
|
|
|
- irq_save_user_regs
|
|
|
- bl do_fiq
|
|
|
- irq_restore_user_regs
|
|
|
-
|
|
|
-#else
|
|
|
-
|
|
|
- .align 5
|
|
|
-irq:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_irq
|
|
|
-
|
|
|
- .align 5
|
|
|
-fiq:
|
|
|
- get_bad_stack
|
|
|
- bad_save_user_regs
|
|
|
- bl do_fiq
|
|
|
-
|
|
|
-#endif
|
|
|
-#endif /* CONFIG_SPL_BUILD */
|