On 11/09/2011 10:18 AM, Marek Vasut wrote: > This patch introduces proper ARM vector handling for i.MX28 CPU. This issue > wasn't addressed because the interrupts weren't enabled on any ARMv5 core, > therefore the issue wasn't noticed earlier. > > In previous implementation, the vectoring code used by i.MX28 CPU when an > exception happened was that of the SPL. With this change, the branch target > when > an exception happens can be reconfigured by U-Boot. > > Signed-off-by: Marek Vasut <marek.va...@gmail.com> > Cc: Stefano Babic <sba...@denx.de> > Cc: Wolfgang Denk <w...@denx.de> > Cc: Detlev Zundel <d...@denx.de> > > --- > arch/arm/cpu/arm926ejs/mx28/mx28.c | 22 +++ > board/denx/m28evk/start.S | 264 > +++++++----------------------------- > include/configs/m28evk.h | 1 + > 3 files changed, 74 insertions(+), 213 deletions(-) > > diff --git a/arch/arm/cpu/arm926ejs/mx28/mx28.c > b/arch/arm/cpu/arm926ejs/mx28/mx28.c > index e990f3c..088c019 100644 > --- a/arch/arm/cpu/arm926ejs/mx28/mx28.c > +++ b/arch/arm/cpu/arm926ejs/mx28/mx28.c > @@ -35,6 +35,8 @@ > #include <asm/arch/imx-regs.h> > #include <asm/arch/sys_proto.h> > > +DECLARE_GLOBAL_DATA_PTR; > + > /* 1 second delay should be plenty of time for block reset. */ > #define RESET_MAX_TIMEOUT 1000000 > > @@ -116,11 +118,31 @@ int mx28_reset_block(struct mx28_register *reg) > return 0; > } > > +void mx28_fixup_vt(uint32_t start_addr) > +{ > + uint32_t *vt = (uint32_t *)0x20; > + int i; > + > + for (i = 0; i < 8; i++) > + vt[i] = start_addr + (4 * i); > +} > + > +#ifdef CONFIG_ARCH_MISC_INIT > +int arch_misc_init(void) > +{ > + mx28_fixup_vt(gd->relocaddr); > + return 0; > +} > +#endif > + > #ifdef CONFIG_ARCH_CPU_INIT > int arch_cpu_init(void) > { > struct mx28_clkctrl_regs *clkctrl_regs = > (struct mx28_clkctrl_regs *)MXS_CLKCTRL_BASE; > + extern uint32_t _start; > + > + mx28_fixup_vt((uint32_t)&_start); > > /* > * Enable NAND clock > diff --git a/board/denx/m28evk/start.S b/board/denx/m28evk/start.S > index cf67599..94696d6 100644 > --- a/board/denx/m28evk/start.S > +++ b/board/denx/m28evk/start.S > @@ -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 */ > diff --git a/include/configs/m28evk.h b/include/configs/m28evk.h > index 59e3e05..381b01e 100644 > --- a/include/configs/m28evk.h > +++ b/include/configs/m28evk.h > @@ -41,6 +41,7 @@ > #define CONFIG_SYS_DCACHE_OFF > #define CONFIG_BOARD_EARLY_INIT_F > #define CONFIG_ARCH_CPU_INIT > +#define CONFIG_ARCH_MISC_INIT > > /* > * SPL
Applied to u-boot-imx, thanks. Best regards, Stefano Babic -- ===================================================================== DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: +49-8142-66989-0 Fax: +49-8142-66989-80 Email: off...@denx.de ===================================================================== _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot