xref: /openbmc/u-boot/arch/arm/lib/vectors.S (revision d1e15041)
183d290c5STom Rini/* SPDX-License-Identifier: GPL-2.0+ */
241623c91SAlbert ARIBAUD/*
341623c91SAlbert ARIBAUD *  vectors - Generic ARM exception table code
441623c91SAlbert ARIBAUD *
541623c91SAlbert ARIBAUD *  Copyright (c) 1998	Dan Malek <dmalek@jlc.net>
641623c91SAlbert ARIBAUD *  Copyright (c) 1999	Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
741623c91SAlbert ARIBAUD *  Copyright (c) 2000	Wolfgang Denk <wd@denx.de>
841623c91SAlbert ARIBAUD *  Copyright (c) 2001	Alex Züpke <azu@sysgo.de>
941623c91SAlbert ARIBAUD *  Copyright (c) 2001	Marius Gröger <mag@sysgo.de>
1041623c91SAlbert ARIBAUD *  Copyright (c) 2002	Alex Züpke <azu@sysgo.de>
1141623c91SAlbert ARIBAUD *  Copyright (c) 2002	Gary Jennejohn <garyj@denx.de>
1241623c91SAlbert ARIBAUD *  Copyright (c) 2002	Kyle Harris <kharris@nexus-tech.net>
1341623c91SAlbert ARIBAUD */
1441623c91SAlbert ARIBAUD
15db993fc8SChristian Riesch#include <config.h>
16db993fc8SChristian Riesch
1741623c91SAlbert ARIBAUD/*
18ef70a42fSPhilipp Tomsich * A macro to allow insertion of an ARM exception vector either
19ef70a42fSPhilipp Tomsich * for the non-boot0 case or by a boot0-header.
20ef70a42fSPhilipp Tomsich */
21ef70a42fSPhilipp Tomsich        .macro ARM_VECTORS
22*f70b72e3SLokesh Vutla#ifdef CONFIG_ARCH_K3
23*f70b72e3SLokesh Vutla	ldr     pc, _reset
24*f70b72e3SLokesh Vutla#else
25ef70a42fSPhilipp Tomsich	b	reset
26*f70b72e3SLokesh Vutla#endif
27ef70a42fSPhilipp Tomsich	ldr	pc, _undefined_instruction
28ef70a42fSPhilipp Tomsich	ldr	pc, _software_interrupt
29ef70a42fSPhilipp Tomsich	ldr	pc, _prefetch_abort
30ef70a42fSPhilipp Tomsich	ldr	pc, _data_abort
31ef70a42fSPhilipp Tomsich	ldr	pc, _not_used
32ef70a42fSPhilipp Tomsich	ldr	pc, _irq
33ef70a42fSPhilipp Tomsich	ldr	pc, _fiq
34ef70a42fSPhilipp Tomsich	.endm
35ef70a42fSPhilipp Tomsich
36ef70a42fSPhilipp Tomsich
37ef70a42fSPhilipp Tomsich/*
3841623c91SAlbert ARIBAUD *************************************************************************
3941623c91SAlbert ARIBAUD *
4041623c91SAlbert ARIBAUD * Symbol _start is referenced elsewhere, so make it global
4141623c91SAlbert ARIBAUD *
4241623c91SAlbert ARIBAUD *************************************************************************
4341623c91SAlbert ARIBAUD */
4441623c91SAlbert ARIBAUD
4541623c91SAlbert ARIBAUD.globl _start
4641623c91SAlbert ARIBAUD
4741623c91SAlbert ARIBAUD/*
4841623c91SAlbert ARIBAUD *************************************************************************
4941623c91SAlbert ARIBAUD *
5041623c91SAlbert ARIBAUD * Vectors have their own section so linker script can map them easily
5141623c91SAlbert ARIBAUD *
5241623c91SAlbert ARIBAUD *************************************************************************
5341623c91SAlbert ARIBAUD */
5441623c91SAlbert ARIBAUD
55c57a6423SGeorges Savoundararadj	.section ".vectors", "ax"
5641623c91SAlbert ARIBAUD
57ef70a42fSPhilipp Tomsich#if defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
58ef70a42fSPhilipp Tomsich/*
59ef70a42fSPhilipp Tomsich * Various SoCs need something special and SoC-specific up front in
60ef70a42fSPhilipp Tomsich * order to boot, allow them to set that in their boot0.h file and then
61ef70a42fSPhilipp Tomsich * use it here.
62ef70a42fSPhilipp Tomsich *
63ef70a42fSPhilipp Tomsich * To allow a boot0 hook to insert a 'special' sequence after the vector
64ef70a42fSPhilipp Tomsich * table (e.g. for the socfpga), the presence of a boot0 hook supresses
65ef70a42fSPhilipp Tomsich * the below vector table and assumes that the vector table is filled in
66ef70a42fSPhilipp Tomsich * by the boot0 hook.  The requirements for a boot0 hook thus are:
67ef70a42fSPhilipp Tomsich *   (1) defines '_start:' as appropriate
68ef70a42fSPhilipp Tomsich *   (2) inserts the vector table using ARM_VECTORS as appropriate
69ef70a42fSPhilipp Tomsich */
70ef70a42fSPhilipp Tomsich#include <asm/arch/boot0.h>
71ef70a42fSPhilipp Tomsich
72ef70a42fSPhilipp Tomsich#else
73ef70a42fSPhilipp Tomsich
7441623c91SAlbert ARIBAUD/*
7541623c91SAlbert ARIBAUD *************************************************************************
7641623c91SAlbert ARIBAUD *
7741623c91SAlbert ARIBAUD * Exception vectors as described in ARM reference manuals
7841623c91SAlbert ARIBAUD *
7941623c91SAlbert ARIBAUD * Uses indirect branch to allow reaching handlers anywhere in memory.
8041623c91SAlbert ARIBAUD *
8141623c91SAlbert ARIBAUD *************************************************************************
8241623c91SAlbert ARIBAUD */
8341623c91SAlbert ARIBAUD
84a7f99bf1SBenoît Thébaudeau_start:
8541623c91SAlbert ARIBAUD#ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
8641623c91SAlbert ARIBAUD	.word	CONFIG_SYS_DV_NOR_BOOT_CFG
8741623c91SAlbert ARIBAUD#endif
88ef70a42fSPhilipp Tomsich	ARM_VECTORS
89ef70a42fSPhilipp Tomsich#endif /* !defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK) */
90cdaa633fSAndre Przywara
9141623c91SAlbert ARIBAUD/*
9241623c91SAlbert ARIBAUD *************************************************************************
9341623c91SAlbert ARIBAUD *
9441623c91SAlbert ARIBAUD * Indirect vectors table
9541623c91SAlbert ARIBAUD *
9641623c91SAlbert ARIBAUD * Symbols referenced here must be defined somewhere else
9741623c91SAlbert ARIBAUD *
9841623c91SAlbert ARIBAUD *************************************************************************
9941623c91SAlbert ARIBAUD */
10041623c91SAlbert ARIBAUD
101*f70b72e3SLokesh Vutla	.globl  _reset
10241623c91SAlbert ARIBAUD	.globl	_undefined_instruction
10341623c91SAlbert ARIBAUD	.globl	_software_interrupt
10441623c91SAlbert ARIBAUD	.globl	_prefetch_abort
10541623c91SAlbert ARIBAUD	.globl	_data_abort
10641623c91SAlbert ARIBAUD	.globl	_not_used
10741623c91SAlbert ARIBAUD	.globl	_irq
10841623c91SAlbert ARIBAUD	.globl	_fiq
10941623c91SAlbert ARIBAUD
110*f70b72e3SLokesh Vutla#ifdef CONFIG_ARCH_K3
111*f70b72e3SLokesh Vutla_reset:			.word reset
112*f70b72e3SLokesh Vutla#endif
11341623c91SAlbert ARIBAUD_undefined_instruction:	.word undefined_instruction
11441623c91SAlbert ARIBAUD_software_interrupt:	.word software_interrupt
11541623c91SAlbert ARIBAUD_prefetch_abort:	.word prefetch_abort
11641623c91SAlbert ARIBAUD_data_abort:		.word data_abort
11741623c91SAlbert ARIBAUD_not_used:		.word not_used
11841623c91SAlbert ARIBAUD_irq:			.word irq
11941623c91SAlbert ARIBAUD_fiq:			.word fiq
12041623c91SAlbert ARIBAUD
12141623c91SAlbert ARIBAUD	.balignl 16,0xdeadbeef
12241623c91SAlbert ARIBAUD
12341623c91SAlbert ARIBAUD/*
12441623c91SAlbert ARIBAUD *************************************************************************
12541623c91SAlbert ARIBAUD *
12641623c91SAlbert ARIBAUD * Interrupt handling
12741623c91SAlbert ARIBAUD *
12841623c91SAlbert ARIBAUD *************************************************************************
12941623c91SAlbert ARIBAUD */
13041623c91SAlbert ARIBAUD
13141623c91SAlbert ARIBAUD/* SPL interrupt handling: just hang */
13241623c91SAlbert ARIBAUD
13341623c91SAlbert ARIBAUD#ifdef CONFIG_SPL_BUILD
13441623c91SAlbert ARIBAUD
13541623c91SAlbert ARIBAUD	.align	5
13641623c91SAlbert ARIBAUDundefined_instruction:
13741623c91SAlbert ARIBAUDsoftware_interrupt:
13841623c91SAlbert ARIBAUDprefetch_abort:
13941623c91SAlbert ARIBAUDdata_abort:
14041623c91SAlbert ARIBAUDnot_used:
14141623c91SAlbert ARIBAUDirq:
14241623c91SAlbert ARIBAUDfiq:
14341623c91SAlbert ARIBAUD1:
144a1b73c18SAndrew F. Davis	b	1b			/* hang and never return */
14541623c91SAlbert ARIBAUD
14641623c91SAlbert ARIBAUD#else	/* !CONFIG_SPL_BUILD */
14741623c91SAlbert ARIBAUD
14841623c91SAlbert ARIBAUD/* IRQ stack memory (calculated at run-time) + 8 bytes */
14941623c91SAlbert ARIBAUD.globl IRQ_STACK_START_IN
15041623c91SAlbert ARIBAUDIRQ_STACK_START_IN:
15169c5d76fSLothar Waßmann#ifdef IRAM_BASE_ADDR
15269c5d76fSLothar Waßmann	.word   IRAM_BASE_ADDR + 0x20
15369c5d76fSLothar Waßmann#else
15441623c91SAlbert ARIBAUD	.word	0x0badc0de
15569c5d76fSLothar Waßmann#endif
15641623c91SAlbert ARIBAUD
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
18241623c91SAlbert ARIBAUD#define MODE_SVC 0x13
18341623c91SAlbert ARIBAUD#define I_BIT	 0x80
18441623c91SAlbert ARIBAUD
18541623c91SAlbert ARIBAUD/*
18641623c91SAlbert ARIBAUD * use bad_save_user_regs for abort/prefetch/undef/swi ...
18741623c91SAlbert ARIBAUD * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
18841623c91SAlbert ARIBAUD */
18941623c91SAlbert ARIBAUD
19041623c91SAlbert ARIBAUD	.macro	bad_save_user_regs
19141623c91SAlbert ARIBAUD	@ carve out a frame on current user stack
19241623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
19341623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}	@ Save user registers (now in svc mode) r0-r12
19441623c91SAlbert ARIBAUD	ldr	r2, IRQ_STACK_START_IN
19541623c91SAlbert ARIBAUD	@ get values for "aborted" pc and cpsr (into parm regs)
19641623c91SAlbert ARIBAUD	ldmia	r2, {r2 - r3}
19741623c91SAlbert ARIBAUD	add	r0, sp, #S_FRAME_SIZE		@ grab pointer to old stack
19841623c91SAlbert ARIBAUD	add	r5, sp, #S_SP
19941623c91SAlbert ARIBAUD	mov	r1, lr
20041623c91SAlbert ARIBAUD	stmia	r5, {r0 - r3}	@ save sp_SVC, lr_SVC, pc, cpsr
20141623c91SAlbert ARIBAUD	mov	r0, sp		@ save current stack into r0 (param register)
20241623c91SAlbert ARIBAUD	.endm
20341623c91SAlbert ARIBAUD
20441623c91SAlbert ARIBAUD	.macro	irq_save_user_regs
20541623c91SAlbert ARIBAUD	sub	sp, sp, #S_FRAME_SIZE
20641623c91SAlbert ARIBAUD	stmia	sp, {r0 - r12}			@ Calling r0-r12
20741623c91SAlbert ARIBAUD	@ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
20841623c91SAlbert ARIBAUD	add	r8, sp, #S_PC
20941623c91SAlbert ARIBAUD	stmdb	r8, {sp, lr}^		@ Calling SP, LR
21041623c91SAlbert ARIBAUD	str	lr, [r8, #0]		@ Save calling PC
21141623c91SAlbert ARIBAUD	mrs	r6, spsr
21241623c91SAlbert ARIBAUD	str	r6, [r8, #4]		@ Save CPSR
21341623c91SAlbert ARIBAUD	str	r0, [r8, #8]		@ Save OLD_R0
21441623c91SAlbert ARIBAUD	mov	r0, sp
21541623c91SAlbert ARIBAUD	.endm
21641623c91SAlbert ARIBAUD
21741623c91SAlbert ARIBAUD	.macro	irq_restore_user_regs
21841623c91SAlbert ARIBAUD	ldmia	sp, {r0 - lr}^			@ Calling r0 - lr
21941623c91SAlbert ARIBAUD	mov	r0, r0
22041623c91SAlbert ARIBAUD	ldr	lr, [sp, #S_PC]			@ Get PC
22141623c91SAlbert ARIBAUD	add	sp, sp, #S_FRAME_SIZE
22241623c91SAlbert ARIBAUD	subs	pc, lr, #4		@ return & move spsr_svc into cpsr
22341623c91SAlbert ARIBAUD	.endm
22441623c91SAlbert ARIBAUD
22541623c91SAlbert ARIBAUD	.macro get_bad_stack
22641623c91SAlbert ARIBAUD	ldr	r13, IRQ_STACK_START_IN		@ setup our mode stack
22741623c91SAlbert ARIBAUD
22841623c91SAlbert ARIBAUD	str	lr, [r13]	@ save caller lr in position 0 of saved stack
22941623c91SAlbert ARIBAUD	mrs	lr, spsr	@ get the spsr
23041623c91SAlbert ARIBAUD	str	lr, [r13, #4]	@ save spsr in position 1 of saved stack
23141623c91SAlbert ARIBAUD	mov	r13, #MODE_SVC	@ prepare SVC-Mode
23241623c91SAlbert ARIBAUD	@ msr	spsr_c, r13
23341623c91SAlbert ARIBAUD	msr	spsr, r13	@ switch modes, make sure moves will execute
23441623c91SAlbert ARIBAUD	mov	lr, pc		@ capture return pc
23541623c91SAlbert ARIBAUD	movs	pc, lr		@ jump to next instruction & switch modes.
23641623c91SAlbert ARIBAUD	.endm
23741623c91SAlbert ARIBAUD
23841623c91SAlbert ARIBAUD	.macro get_irq_stack			@ setup IRQ stack
23941623c91SAlbert ARIBAUD	ldr	sp, IRQ_STACK_START
24041623c91SAlbert ARIBAUD	.endm
24141623c91SAlbert ARIBAUD
24241623c91SAlbert ARIBAUD	.macro get_fiq_stack			@ setup FIQ stack
24341623c91SAlbert ARIBAUD	ldr	sp, FIQ_STACK_START
24441623c91SAlbert ARIBAUD	.endm
24541623c91SAlbert ARIBAUD
24641623c91SAlbert ARIBAUD/*
24741623c91SAlbert ARIBAUD * exception handlers
24841623c91SAlbert ARIBAUD */
24941623c91SAlbert ARIBAUD
25041623c91SAlbert ARIBAUD	.align  5
25141623c91SAlbert ARIBAUDundefined_instruction:
25241623c91SAlbert ARIBAUD	get_bad_stack
25341623c91SAlbert ARIBAUD	bad_save_user_regs
25441623c91SAlbert ARIBAUD	bl	do_undefined_instruction
25541623c91SAlbert ARIBAUD
25641623c91SAlbert ARIBAUD	.align	5
25741623c91SAlbert ARIBAUDsoftware_interrupt:
25841623c91SAlbert ARIBAUD	get_bad_stack
25941623c91SAlbert ARIBAUD	bad_save_user_regs
26041623c91SAlbert ARIBAUD	bl	do_software_interrupt
26141623c91SAlbert ARIBAUD
26241623c91SAlbert ARIBAUD	.align	5
26341623c91SAlbert ARIBAUDprefetch_abort:
26441623c91SAlbert ARIBAUD	get_bad_stack
26541623c91SAlbert ARIBAUD	bad_save_user_regs
26641623c91SAlbert ARIBAUD	bl	do_prefetch_abort
26741623c91SAlbert ARIBAUD
26841623c91SAlbert ARIBAUD	.align	5
26941623c91SAlbert ARIBAUDdata_abort:
27041623c91SAlbert ARIBAUD	get_bad_stack
27141623c91SAlbert ARIBAUD	bad_save_user_regs
27241623c91SAlbert ARIBAUD	bl	do_data_abort
27341623c91SAlbert ARIBAUD
27441623c91SAlbert ARIBAUD	.align	5
27541623c91SAlbert ARIBAUDnot_used:
27641623c91SAlbert ARIBAUD	get_bad_stack
27741623c91SAlbert ARIBAUD	bad_save_user_regs
27841623c91SAlbert ARIBAUD	bl	do_not_used
27941623c91SAlbert ARIBAUD
28041623c91SAlbert ARIBAUD
28141623c91SAlbert ARIBAUD	.align	5
28241623c91SAlbert ARIBAUDirq:
28341623c91SAlbert ARIBAUD	get_bad_stack
28441623c91SAlbert ARIBAUD	bad_save_user_regs
28541623c91SAlbert ARIBAUD	bl	do_irq
28641623c91SAlbert ARIBAUD
28741623c91SAlbert ARIBAUD	.align	5
28841623c91SAlbert ARIBAUDfiq:
28941623c91SAlbert ARIBAUD	get_bad_stack
29041623c91SAlbert ARIBAUD	bad_save_user_regs
29141623c91SAlbert ARIBAUD	bl	do_fiq
29241623c91SAlbert ARIBAUD
29341623c91SAlbert ARIBAUD#endif	/* CONFIG_SPL_BUILD */
294