xref: /rk3399_rockchip-uboot/arch/arm/lib/vectors.S (revision 7cef79185b7a019281d828de6ba3f6fbcec95d45)
141623c91SAlbert ARIBAUD/*
241623c91SAlbert ARIBAUD *  vectors - Generic ARM exception table code
341623c91SAlbert ARIBAUD *
441623c91SAlbert ARIBAUD *  Copyright (c) 1998	Dan Malek <dmalek@jlc.net>
541623c91SAlbert ARIBAUD *  Copyright (c) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
641623c91SAlbert ARIBAUD *  Copyright (c) 2000	Wolfgang Denk <wd@denx.de>
741623c91SAlbert ARIBAUD *  Copyright (c) 2001	Alex Züpke <azu@sysgo.de>
841623c91SAlbert ARIBAUD *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
941623c91SAlbert ARIBAUD *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
1041623c91SAlbert ARIBAUD *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
1141623c91SAlbert ARIBAUD *  Copyright (c) 2002	Kyle Harris <kharris@nexus-tech.net>
1241623c91SAlbert ARIBAUD *
1341623c91SAlbert ARIBAUD * SPDX-License-Identifier:	GPL-2.0+
1441623c91SAlbert ARIBAUD */
1541623c91SAlbert ARIBAUD
16db993fc8SChristian Riesch#include <config.h>
17db993fc8SChristian Riesch
1841623c91SAlbert ARIBAUD/*
19733d51d5SPhilipp Tomsich * A macro to allow insertion of an ARM exception vector either
20733d51d5SPhilipp Tomsich * for the non-boot0 case or by a boot0-header.
21733d51d5SPhilipp Tomsich */
22733d51d5SPhilipp Tomsich        .macro ARM_VECTORS
23733d51d5SPhilipp Tomsich	b	reset
24733d51d5SPhilipp Tomsich	ldr	pc, _undefined_instruction
25733d51d5SPhilipp Tomsich	ldr	pc, _software_interrupt
26733d51d5SPhilipp Tomsich	ldr	pc, _prefetch_abort
27733d51d5SPhilipp Tomsich	ldr	pc, _data_abort
28733d51d5SPhilipp Tomsich	ldr	pc, _not_used
29733d51d5SPhilipp Tomsich	ldr	pc, _irq
30733d51d5SPhilipp Tomsich	ldr	pc, _fiq
31733d51d5SPhilipp Tomsich	.endm
32733d51d5SPhilipp Tomsich
33733d51d5SPhilipp Tomsich
34733d51d5SPhilipp Tomsich/*
3541623c91SAlbert ARIBAUD *************************************************************************
3641623c91SAlbert ARIBAUD *
3741623c91SAlbert ARIBAUD * Symbol _start is referenced elsewhere, so make it global
3841623c91SAlbert ARIBAUD *
3941623c91SAlbert ARIBAUD *************************************************************************
4041623c91SAlbert ARIBAUD */
4141623c91SAlbert ARIBAUD
4241623c91SAlbert ARIBAUD.globl _start
4341623c91SAlbert ARIBAUD
4441623c91SAlbert ARIBAUD/*
4541623c91SAlbert ARIBAUD *************************************************************************
4641623c91SAlbert ARIBAUD *
4741623c91SAlbert ARIBAUD * Vectors have their own section so linker script can map them easily
4841623c91SAlbert ARIBAUD *
4941623c91SAlbert ARIBAUD *************************************************************************
5041623c91SAlbert ARIBAUD */
5141623c91SAlbert ARIBAUD
52c57a6423SGeorges Savoundararadj	.section ".vectors", "ax"
5341623c91SAlbert ARIBAUD
54733d51d5SPhilipp Tomsich#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
55733d51d5SPhilipp Tomsich/*
56733d51d5SPhilipp Tomsich * Various SoCs need something special and SoC-specific up front in
57733d51d5SPhilipp Tomsich * order to boot, allow them to set that in their boot0.h file and then
58733d51d5SPhilipp Tomsich * use it here.
59733d51d5SPhilipp Tomsich *
60733d51d5SPhilipp Tomsich * To allow a boot0 hook to insert a 'special' sequence after the vector
61733d51d5SPhilipp Tomsich * table (e.g. for the socfpga), the presence of a boot0 hook supresses
62733d51d5SPhilipp Tomsich * the below vector table and assumes that the vector table is filled in
63733d51d5SPhilipp Tomsich * by the boot0 hook.  The requirements for a boot0 hook thus are:
64733d51d5SPhilipp Tomsich *   (1) defines '_start:' as appropriate
65733d51d5SPhilipp Tomsich *   (2) inserts the vector table using ARM_VECTORS as appropriate
66733d51d5SPhilipp Tomsich */
67733d51d5SPhilipp Tomsich#include <asm/arch/boot0.h>
68733d51d5SPhilipp Tomsich
69733d51d5SPhilipp Tomsich#else
70733d51d5SPhilipp Tomsich
7141623c91SAlbert ARIBAUD/*
7241623c91SAlbert ARIBAUD *************************************************************************
7341623c91SAlbert ARIBAUD *
7441623c91SAlbert ARIBAUD * Exception vectors as described in ARM reference manuals
7541623c91SAlbert ARIBAUD *
7641623c91SAlbert ARIBAUD * Uses indirect branch to allow reaching handlers anywhere in memory.
7741623c91SAlbert ARIBAUD *
7841623c91SAlbert ARIBAUD *************************************************************************
7941623c91SAlbert ARIBAUD */
8041623c91SAlbert ARIBAUD
81a7f99bf1SBenoît Thébaudeau_start:
8241623c91SAlbert ARIBAUD#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
8341623c91SAlbert ARIBAUD	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
8441623c91SAlbert ARIBAUD#endif
85733d51d5SPhilipp Tomsich	ARM_VECTORS
86733d51d5SPhilipp Tomsich#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
87cdaa633fSAndre Przywara
8841623c91SAlbert ARIBAUD/*
8941623c91SAlbert ARIBAUD *************************************************************************
9041623c91SAlbert ARIBAUD *
9141623c91SAlbert ARIBAUD * Indirect vectors table
9241623c91SAlbert ARIBAUD *
9341623c91SAlbert ARIBAUD * Symbols referenced here must be defined somewhere else
9441623c91SAlbert ARIBAUD *
9541623c91SAlbert ARIBAUD *************************************************************************
9641623c91SAlbert ARIBAUD */
9741623c91SAlbert ARIBAUD
9841623c91SAlbert ARIBAUD	.globl	_undefined_instruction
9941623c91SAlbert ARIBAUD	.globl	_software_interrupt
10041623c91SAlbert ARIBAUD	.globl	_prefetch_abort
10141623c91SAlbert ARIBAUD	.globl	_data_abort
10241623c91SAlbert ARIBAUD	.globl	_not_used
10341623c91SAlbert ARIBAUD	.globl	_irq
10441623c91SAlbert ARIBAUD	.globl	_fiq
10541623c91SAlbert ARIBAUD
10641623c91SAlbert ARIBAUD_undefined_instruction:	.word undefined_instruction
10741623c91SAlbert ARIBAUD_software_interrupt:	.word software_interrupt
10841623c91SAlbert ARIBAUD_prefetch_abort:	.word prefetch_abort
10941623c91SAlbert ARIBAUD_data_abort:		.word data_abort
11041623c91SAlbert ARIBAUD_not_used:		.word not_used
11141623c91SAlbert ARIBAUD_irq:			.word irq
11241623c91SAlbert ARIBAUD_fiq:			.word fiq
11341623c91SAlbert ARIBAUD
11441623c91SAlbert ARIBAUD	.balignl 16,0xdeadbeef
11541623c91SAlbert ARIBAUD
11641623c91SAlbert ARIBAUD/*
11741623c91SAlbert ARIBAUD *************************************************************************
11841623c91SAlbert ARIBAUD *
11941623c91SAlbert ARIBAUD * Interrupt handling
12041623c91SAlbert ARIBAUD *
12141623c91SAlbert ARIBAUD *************************************************************************
12241623c91SAlbert ARIBAUD */
12341623c91SAlbert ARIBAUD
12441623c91SAlbert ARIBAUD/* SPL interrupt handling: just hang */
12541623c91SAlbert ARIBAUD
12641623c91SAlbert ARIBAUD#ifdef CONFIG_SPL_BUILD
12741623c91SAlbert ARIBAUD
12841623c91SAlbert ARIBAUD	.align	5
12941623c91SAlbert ARIBAUDundefined_instruction:
13041623c91SAlbert ARIBAUDsoftware_interrupt:
13141623c91SAlbert ARIBAUDprefetch_abort:
13241623c91SAlbert ARIBAUDdata_abort:
13341623c91SAlbert ARIBAUDnot_used:
13441623c91SAlbert ARIBAUDirq:
13541623c91SAlbert ARIBAUDfiq:
13641623c91SAlbert ARIBAUD1:
13741623c91SAlbert ARIBAUD	bl	1b			/* hang and never return */
13841623c91SAlbert ARIBAUD
13941623c91SAlbert ARIBAUD#else	/* !CONFIG_SPL_BUILD */
14041623c91SAlbert ARIBAUD
14141623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) + 8 bytes */
14241623c91SAlbert ARIBAUD.globl IRQ_STACK_START_IN
14341623c91SAlbert ARIBAUDIRQ_STACK_START_IN:
14469c5d76fSLothar Waßmann#ifdef IRAM_BASE_ADDR
14569c5d76fSLothar Waßmann	.word   IRAM_BASE_ADDR + 0x20
14669c5d76fSLothar Waßmann#else
14741623c91SAlbert ARIBAUD	.word	0x0badc0de
14869c5d76fSLothar Waßmann#endif
14941623c91SAlbert ARIBAUD
150*7cef7918SJoseph Chen#if CONFIG_IS_ENABLED(IRQ)
151fa40f8a0SJoseph Chen/* IRQ stack memory (calculated at run-time) */
152fa40f8a0SJoseph Chen.globl IRQ_STACK_START
153fa40f8a0SJoseph ChenIRQ_STACK_START:
154fa40f8a0SJoseph Chen	.word	0x0badc0de
155fa40f8a0SJoseph Chen#endif
156fa40f8a0SJoseph Chen
15741623c91SAlbert ARIBAUD@
15841623c91SAlbert ARIBAUD@ IRQ stack frame.
15941623c91SAlbert ARIBAUD@
16041623c91SAlbert ARIBAUD#define S_FRAME_SIZE	72
16141623c91SAlbert ARIBAUD
16241623c91SAlbert ARIBAUD#define S_OLD_R0	68
16341623c91SAlbert ARIBAUD#define S_PSR		64
16441623c91SAlbert ARIBAUD#define S_PC		60
16541623c91SAlbert ARIBAUD#define S_LR		56
16641623c91SAlbert ARIBAUD#define S_SP		52
16741623c91SAlbert ARIBAUD
16841623c91SAlbert ARIBAUD#define S_IP		48
16941623c91SAlbert ARIBAUD#define S_FP		44
17041623c91SAlbert ARIBAUD#define S_R10		40
17141623c91SAlbert ARIBAUD#define S_R9		36
17241623c91SAlbert ARIBAUD#define S_R8		32
17341623c91SAlbert ARIBAUD#define S_R7		28
17441623c91SAlbert ARIBAUD#define S_R6		24
17541623c91SAlbert ARIBAUD#define S_R5		20
17641623c91SAlbert ARIBAUD#define S_R4		16
17741623c91SAlbert ARIBAUD#define S_R3		12
17841623c91SAlbert ARIBAUD#define S_R2		8
17941623c91SAlbert ARIBAUD#define S_R1		4
18041623c91SAlbert ARIBAUD#define S_R0		0
18141623c91SAlbert ARIBAUD
1829fa74d15SJoseph Chen#define MODE_IRQ 0x12
18341623c91SAlbert ARIBAUD#define MODE_SVC 0x13
18441623c91SAlbert ARIBAUD#define I_BIT	 0x80
18541623c91SAlbert ARIBAUD
18641623c91SAlbert ARIBAUD/*
18741623c91SAlbert ARIBAUD * use bad_save_user_regs for abort/prefetch/undef/swi ...
18841623c91SAlbert ARIBAUD * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
18941623c91SAlbert ARIBAUD */
19041623c91SAlbert ARIBAUD
19141623c91SAlbert ARIBAUD	.macro	bad_save_user_regs
19241623c91SAlbert ARIBAUD	@ carve out a frame on current user stack
19341623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
19441623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
19541623c91SAlbert ARIBAUD	ldr	r2, IRQ_STACK_START_IN
19641623c91SAlbert ARIBAUD	@ get values for "aborted" pc and cpsr (into parm regs)
19741623c91SAlbert ARIBAUD	ldmia	r2, {r2 - r3}
19841623c91SAlbert ARIBAUD	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
19941623c91SAlbert ARIBAUD	add	r5, sp, #S_SP
20041623c91SAlbert ARIBAUD	mov	r1, lr
20141623c91SAlbert ARIBAUD	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
20241623c91SAlbert ARIBAUD	mov	r0, sp		@ save current stack into r0 (param register)
20341623c91SAlbert ARIBAUD	.endm
20441623c91SAlbert ARIBAUD
20541623c91SAlbert ARIBAUD	.macro	irq_save_user_regs
20641623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
20741623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}			@ Calling r0-r12
20841623c91SAlbert ARIBAUD	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
20941623c91SAlbert ARIBAUD	add	r8, sp, #S_PC
2109fa74d15SJoseph Chen
2119fa74d15SJoseph Chen	cps	#MODE_SVC	@ SVC-Mode
2129fa74d15SJoseph Chen	isb
2139fa74d15SJoseph Chen	mov	r1, sp		@ svc_sp
2149fa74d15SJoseph Chen	mov	r2, lr		@ svc_lr
2159fa74d15SJoseph Chen	cps	#MODE_IRQ	@ IRQ-Mode
2169fa74d15SJoseph Chen	isb
2179fa74d15SJoseph Chen
2189fa74d15SJoseph Chen	stmdb	r8, {r1, r2}^		@ Calling svc_sp, svc_lr
21941623c91SAlbert ARIBAUD	str	lr, [r8, #0]		@ Save calling PC
22041623c91SAlbert ARIBAUD	mrs	r6, spsr
22141623c91SAlbert ARIBAUD	str	r6, [r8, #4]		@ Save CPSR
22241623c91SAlbert ARIBAUD	str	r0, [r8, #8]		@ Save OLD_R0
22341623c91SAlbert ARIBAUD	mov	r0, sp
22441623c91SAlbert ARIBAUD	.endm
22541623c91SAlbert ARIBAUD
22641623c91SAlbert ARIBAUD	.macro	irq_restore_user_regs
22741623c91SAlbert ARIBAUD	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
22841623c91SAlbert ARIBAUD	mov	r0, r0
22941623c91SAlbert ARIBAUD	ldr	lr, [sp, #S_PC]			@ Get PC
23041623c91SAlbert ARIBAUD	add	sp, sp, #S_FRAME_SIZE
23141623c91SAlbert ARIBAUD	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
23241623c91SAlbert ARIBAUD	.endm
23341623c91SAlbert ARIBAUD
23441623c91SAlbert ARIBAUD	.macro get_bad_stack
23541623c91SAlbert ARIBAUD	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
23641623c91SAlbert ARIBAUD
23741623c91SAlbert ARIBAUD	str	lr, [r13]	@ save caller lr in position 0 of saved stack
23841623c91SAlbert ARIBAUD	mrs	lr, spsr	@ get the spsr
23941623c91SAlbert ARIBAUD	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
24041623c91SAlbert ARIBAUD	mov	r13, #MODE_SVC	@ prepare SVC-Mode
24141623c91SAlbert ARIBAUD	@ msr	spsr_c, r13
24241623c91SAlbert ARIBAUD	msr	spsr, r13	@ switch modes, make sure moves will execute
24341623c91SAlbert ARIBAUD	mov	lr, pc		@ capture return pc
24441623c91SAlbert ARIBAUD	movs	pc, lr		@ jump to next instruction & switch modes.
24541623c91SAlbert ARIBAUD	.endm
24641623c91SAlbert ARIBAUD
24741623c91SAlbert ARIBAUD	.macro get_irq_stack			@ setup IRQ stack
24841623c91SAlbert ARIBAUD	ldr	sp, IRQ_STACK_START
24941623c91SAlbert ARIBAUD	.endm
25041623c91SAlbert ARIBAUD
25141623c91SAlbert ARIBAUD	.macro get_fiq_stack			@ setup FIQ stack
25241623c91SAlbert ARIBAUD	ldr	sp, FIQ_STACK_START
25341623c91SAlbert ARIBAUD	.endm
25441623c91SAlbert ARIBAUD
25541623c91SAlbert ARIBAUD/*
25641623c91SAlbert ARIBAUD * exception handlers
25741623c91SAlbert ARIBAUD */
25841623c91SAlbert ARIBAUD
25941623c91SAlbert ARIBAUD	.align  5
26041623c91SAlbert ARIBAUDundefined_instruction:
26141623c91SAlbert ARIBAUD	get_bad_stack
26241623c91SAlbert ARIBAUD	bad_save_user_regs
26341623c91SAlbert ARIBAUD	bl	do_undefined_instruction
26441623c91SAlbert ARIBAUD
26541623c91SAlbert ARIBAUD	.align	5
26641623c91SAlbert ARIBAUDsoftware_interrupt:
26741623c91SAlbert ARIBAUD	get_bad_stack
26841623c91SAlbert ARIBAUD	bad_save_user_regs
26941623c91SAlbert ARIBAUD	bl	do_software_interrupt
27041623c91SAlbert ARIBAUD
27141623c91SAlbert ARIBAUD	.align	5
27241623c91SAlbert ARIBAUDprefetch_abort:
27341623c91SAlbert ARIBAUD	get_bad_stack
27441623c91SAlbert ARIBAUD	bad_save_user_regs
27541623c91SAlbert ARIBAUD	bl	do_prefetch_abort
27641623c91SAlbert ARIBAUD
27741623c91SAlbert ARIBAUD	.align	5
27841623c91SAlbert ARIBAUDdata_abort:
27941623c91SAlbert ARIBAUD	get_bad_stack
28041623c91SAlbert ARIBAUD	bad_save_user_regs
28141623c91SAlbert ARIBAUD	bl	do_data_abort
28241623c91SAlbert ARIBAUD
28341623c91SAlbert ARIBAUD	.align	5
28441623c91SAlbert ARIBAUDnot_used:
28541623c91SAlbert ARIBAUD	get_bad_stack
28641623c91SAlbert ARIBAUD	bad_save_user_regs
28741623c91SAlbert ARIBAUD	bl	do_not_used
28841623c91SAlbert ARIBAUD
28941623c91SAlbert ARIBAUD
29041623c91SAlbert ARIBAUD	.align	5
29141623c91SAlbert ARIBAUDirq:
292*7cef7918SJoseph Chen#if CONFIG_IS_ENABLED(IRQ)
293fa40f8a0SJoseph Chen	get_irq_stack
294fa40f8a0SJoseph Chen	irq_save_user_regs
295fa40f8a0SJoseph Chen	bl	do_irq
296fa40f8a0SJoseph Chen	irq_restore_user_regs
297fa40f8a0SJoseph Chen#else
29841623c91SAlbert ARIBAUD	get_bad_stack
29941623c91SAlbert ARIBAUD	bad_save_user_regs
30041623c91SAlbert ARIBAUD	bl	do_irq
301fa40f8a0SJoseph Chen#endif
30241623c91SAlbert ARIBAUD
30341623c91SAlbert ARIBAUD	.align	5
30441623c91SAlbert ARIBAUDfiq:
30541623c91SAlbert ARIBAUD	get_bad_stack
30641623c91SAlbert ARIBAUD	bad_save_user_regs
30741623c91SAlbert ARIBAUD	bl	do_fiq
30841623c91SAlbert ARIBAUD
30941623c91SAlbert ARIBAUD#endif	/* CONFIG_SPL_BUILD */
310