blob: 5783df1ef2a6986eccc27438955d99450f697680 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * armboot - Startup Code for ARM926EJS CPU-core
3 *
4 * Copyright (c) 2003 Texas Instruments
5 *
6 * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------
7 *
8 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
9 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de>
11 * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com>
12 * Copyright (c) 2003 Kshitij <kshitij@ti.com>
13 *
14 * SPDX-License-Identifier: GPL-2.0+
15 */
16
17#include <asm-offsets.h>
18#include <config.h>
19#include <version.h>
20
21/*
22 *************************************************************************
23 *
24 * Jump vector table
25 *
26 *************************************************************************
27 */
28
29.globl _start
30_start:
31 b reset
32 ldr pc, _undefined_instruction
33 ldr pc, _software_interrupt
34 ldr pc, _prefetch_abort
35 ldr pc, _data_abort
36 ldr pc, _not_used
37 ldr pc, _irq
38 ldr pc, _fiq
39
40_undefined_instruction:
41 .word undefined_instruction
42_software_interrupt:
43 .word software_interrupt
44_prefetch_abort:
45 .word prefetch_abort
46_data_abort:
47 .word data_abort
48_not_used:
49 .word not_used
50_irq:
51 .word irq
52_fiq:
53 .word fiq
54
55 .balignl 16,0xdeadbeef
56
57/*
58 *************************************************************************
59 *
60 * Startup Code (reset vector)
61 *
62 * do important init only if we don't start from memory!
63 * setup memory and board specific bits prior to relocation.
64 * relocate armboot to ram
65 * setup stack
66 *
67 *************************************************************************
68 */
69
70.globl _TEXT_BASE
71_TEXT_BASE:
72#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE)
73 .word CONFIG_SPL_TEXT_BASE
74#else
75 .word CONFIG_SYS_TEXT_BASE
76#endif
77
78/*
79 * These are defined in the board-specific linker script.
80 * Subtracting _start from them lets the linker put their
81 * relative position in the executable instead of leaving
82 * them null.
83 */
84.globl _bss_start_ofs
85_bss_start_ofs:
86 .word __bss_start - _start
87
88.globl _bss_end_ofs
89_bss_end_ofs:
90 .word __bss_end - _start
91
92.globl _end_ofs
93_end_ofs:
94 .word _end - _start
95
96#ifdef CONFIG_USE_IRQ
97/* IRQ stack memory (calculated at run-time) */
98.globl IRQ_STACK_START
99IRQ_STACK_START:
100 .word 0x0badc0de
101
102/* IRQ stack memory (calculated at run-time) */
103.globl FIQ_STACK_START
104FIQ_STACK_START:
105 .word 0x0badc0de
106#endif
107
108/* IRQ stack memory (calculated at run-time) + 8 bytes */
109.globl IRQ_STACK_START_IN
110IRQ_STACK_START_IN:
111 .word 0x0badc0de
112
113/*
114 * the actual reset code
115 */
116
117reset:
118 /*
119 * set the cpu to SVC32 mode
120 */
121 mrs r0,cpsr
122 bic r0,r0,#0x1f
123 orr r0,r0,#0xd3
124 msr cpsr,r0
125
126 /*
127 * we do sys-critical inits only at reboot,
128 * not when booting from ram!
129 */
130#ifndef CONFIG_SKIP_LOWLEVEL_INIT
131 bl cpu_init_crit
132#endif
133
134 bl _main
135
136/*------------------------------------------------------------------------------*/
137
138 .globl c_runtime_cpu_setup
139c_runtime_cpu_setup:
140
141 mov pc, lr
142
143/*
144 *************************************************************************
145 *
146 * CPU_init_critical registers
147 *
148 * setup important registers
149 * setup memory timing
150 *
151 *************************************************************************
152 */
153
154#ifndef CONFIG_SKIP_LOWLEVEL_INIT
155cpu_init_crit:
156 /* arm_int_generic assumes the ARM boot monitor, or user software,
157 * has initialized the platform
158 */
159 mov pc, lr /* back to my caller */
160#endif
161/*
162 *************************************************************************
163 *
164 * Interrupt handling
165 *
166 *************************************************************************
167 */
168
169@
170@ IRQ stack frame.
171@
172#define S_FRAME_SIZE 72
173
174#define S_OLD_R0 68
175#define S_PSR 64
176#define S_PC 60
177#define S_LR 56
178#define S_SP 52
179
180#define S_IP 48
181#define S_FP 44
182#define S_R10 40
183#define S_R9 36
184#define S_R8 32
185#define S_R7 28
186#define S_R6 24
187#define S_R5 20
188#define S_R4 16
189#define S_R3 12
190#define S_R2 8
191#define S_R1 4
192#define S_R0 0
193
194#define MODE_SVC 0x13
195#define I_BIT 0x80
196
197/*
198 * use bad_save_user_regs for abort/prefetch/undef/swi ...
199 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
200 */
201
202 .macro bad_save_user_regs
203 @ carve out a frame on current user stack
204 sub sp, sp, #S_FRAME_SIZE
205 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
206
207 ldr r2, IRQ_STACK_START_IN
208 @ get values for "aborted" pc and cpsr (into parm regs)
209 ldmia r2, {r2 - r3}
210 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
211 add r5, sp, #S_SP
212 mov r1, lr
213 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
214 mov r0, sp @ save current stack into r0 (param register)
215 .endm
216
217 .macro irq_save_user_regs
218 sub sp, sp, #S_FRAME_SIZE
219 stmia sp, {r0 - r12} @ Calling r0-r12
220 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
221 add r8, sp, #S_PC
222 stmdb r8, {sp, lr}^ @ Calling SP, LR
223 str lr, [r8, #0] @ Save calling PC
224 mrs r6, spsr
225 str r6, [r8, #4] @ Save CPSR
226 str r0, [r8, #8] @ Save OLD_R0
227 mov r0, sp
228 .endm
229
230 .macro irq_restore_user_regs
231 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
232 mov r0, r0
233 ldr lr, [sp, #S_PC] @ Get PC
234 add sp, sp, #S_FRAME_SIZE
235 subs pc, lr, #4 @ return & move spsr_svc into cpsr
236 .endm
237
238 .macro get_bad_stack
239 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
240
241 str lr, [r13] @ save caller lr in position 0 of saved stack
242 mrs lr, spsr @ get the spsr
243 str lr, [r13, #4] @ save spsr in position 1 of saved stack
244 mov r13, #MODE_SVC @ prepare SVC-Mode
245 @ msr spsr_c, r13
246 msr spsr, r13 @ switch modes, make sure moves will execute
247 mov lr, pc @ capture return pc
248 movs pc, lr @ jump to next instruction & switch modes.
249 .endm
250
251 .macro get_irq_stack @ setup IRQ stack
252 ldr sp, IRQ_STACK_START
253 .endm
254
255 .macro get_fiq_stack @ setup FIQ stack
256 ldr sp, FIQ_STACK_START
257 .endm
258
259/*
260 * exception handlers
261 */
262 .align 5
263.globl undefined_instruction
264undefined_instruction:
265 get_bad_stack
266 bad_save_user_regs
267 bl do_undefined_instruction
268
269 .align 5
270.globl software_interrupt
271software_interrupt:
272 get_bad_stack
273 bad_save_user_regs
274 bl do_software_interrupt
275
276 .align 5
277.globl prefetch_abort
278prefetch_abort:
279 get_bad_stack
280 bad_save_user_regs
281 bl do_prefetch_abort
282
283 .align 5
284.globl data_abort
285data_abort:
286 get_bad_stack
287 bad_save_user_regs
288 bl do_data_abort
289
290 .align 5
291.globl not_used
292not_used:
293 get_bad_stack
294 bad_save_user_regs
295 bl do_not_used
296
297#ifdef CONFIG_USE_IRQ
298 .align 5
299.globl irq
300irq:
301 get_irq_stack
302 irq_save_user_regs
303 bl do_irq
304 irq_restore_user_regs
305
306 .align 5
307.globl fiq
308fiq:
309 get_fiq_stack
310 /* someone ought to write a more effiction fiq_save_user_regs */
311 irq_save_user_regs
312 bl do_fiq
313 irq_restore_user_regs
314
315#else
316
317 .align 5
318.globl irq
319irq:
320 get_bad_stack
321 bad_save_user_regs
322 bl do_irq
323
324 .align 5
325.globl fiq
326fiq:
327 get_bad_stack
328 bad_save_user_regs
329 bl do_fiq
330
331#endif