]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/cpu/arm926ejs/start.S
0717327050d06200a2871da2bcccfb290a45d1d7
[people/ms/u-boot.git] / arch / arm / cpu / arm926ejs / start.S
1 /*
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 * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net>
14 *
15 * SPDX-License-Identifier: GPL-2.0+
16 */
17
18 #include <asm-offsets.h>
19 #include <config.h>
20 #include <common.h>
21 #include <version.h>
22
23 /*
24 *************************************************************************
25 *
26 * Jump vector table as in table 3.1 in [1]
27 *
28 *************************************************************************
29 */
30
31
32 #ifdef CONFIG_SYS_DV_NOR_BOOT_CFG
33 .globl _start
34 _start:
35 .globl _NOR_BOOT_CFG
36 _NOR_BOOT_CFG:
37 .word CONFIG_SYS_DV_NOR_BOOT_CFG
38 b reset
39 #else
40 .globl _start
41 _start:
42 b reset
43 #endif
44 #ifdef CONFIG_SPL_BUILD
45 /* No exception handlers in preloader */
46 ldr pc, _hang
47 ldr pc, _hang
48 ldr pc, _hang
49 ldr pc, _hang
50 ldr pc, _hang
51 ldr pc, _hang
52 ldr pc, _hang
53
54 _hang:
55 .word do_hang
56 /* pad to 64 byte boundary */
57 .word 0x12345678
58 .word 0x12345678
59 .word 0x12345678
60 .word 0x12345678
61 .word 0x12345678
62 .word 0x12345678
63 .word 0x12345678
64 #else
65 ldr pc, _undefined_instruction
66 ldr pc, _software_interrupt
67 ldr pc, _prefetch_abort
68 ldr pc, _data_abort
69 ldr pc, _not_used
70 ldr pc, _irq
71 ldr pc, _fiq
72
73 _undefined_instruction:
74 .word undefined_instruction
75 _software_interrupt:
76 .word software_interrupt
77 _prefetch_abort:
78 .word prefetch_abort
79 _data_abort:
80 .word data_abort
81 _not_used:
82 .word not_used
83 _irq:
84 .word irq
85 _fiq:
86 .word fiq
87
88 #endif /* CONFIG_SPL_BUILD */
89 .balignl 16,0xdeadbeef
90
91
92 /*
93 *************************************************************************
94 *
95 * Startup Code (reset vector)
96 *
97 * do important init only if we don't start from memory!
98 * setup Memory and board specific bits prior to relocation.
99 * relocate armboot to ram
100 * setup stack
101 *
102 *************************************************************************
103 */
104
105 #ifdef CONFIG_USE_IRQ
106 /* IRQ stack memory (calculated at run-time) */
107 .globl IRQ_STACK_START
108 IRQ_STACK_START:
109 .word 0x0badc0de
110
111 /* IRQ stack memory (calculated at run-time) */
112 .globl FIQ_STACK_START
113 FIQ_STACK_START:
114 .word 0x0badc0de
115 #endif
116
117 /* IRQ stack memory (calculated at run-time) + 8 bytes */
118 .globl IRQ_STACK_START_IN
119 IRQ_STACK_START_IN:
120 .word 0x0badc0de
121
122 /*
123 * the actual reset code
124 */
125
126 reset:
127 /*
128 * set the cpu to SVC32 mode
129 */
130 mrs r0,cpsr
131 bic r0,r0,#0x1f
132 orr r0,r0,#0xd3
133 msr cpsr,r0
134
135 /*
136 * we do sys-critical inits only at reboot,
137 * not when booting from ram!
138 */
139 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
140 bl cpu_init_crit
141 #endif
142
143 bl _main
144
145 /*------------------------------------------------------------------------------*/
146
147 .globl c_runtime_cpu_setup
148 c_runtime_cpu_setup:
149
150 bx lr
151
152 /*
153 *************************************************************************
154 *
155 * CPU_init_critical registers
156 *
157 * setup important registers
158 * setup memory timing
159 *
160 *************************************************************************
161 */
162 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
163 cpu_init_crit:
164 /*
165 * flush D cache before disabling it
166 */
167 mov r0, #0
168 flush_dcache:
169 mrc p15, 0, r15, c7, c10, 3
170 bne flush_dcache
171
172 mcr p15, 0, r0, c8, c7, 0 /* invalidate TLB */
173 mcr p15, 0, r0, c7, c5, 0 /* invalidate I Cache */
174
175 /*
176 * disable MMU and D cache
177 * enable I cache if CONFIG_SYS_ICACHE_OFF is not defined
178 */
179 mrc p15, 0, r0, c1, c0, 0
180 bic r0, r0, #0x00000300 /* clear bits 9:8 (---- --RS) */
181 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
182 #ifdef CONFIG_SYS_EXCEPTION_VECTORS_HIGH
183 orr r0, r0, #0x00002000 /* set bit 13 (--V- ----) */
184 #else
185 bic r0, r0, #0x00002000 /* clear bit 13 (--V- ----) */
186 #endif
187 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
188 #ifndef CONFIG_SYS_ICACHE_OFF
189 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
190 #endif
191 mcr p15, 0, r0, c1, c0, 0
192
193 /*
194 * Go setup Memory and board specific bits prior to relocation.
195 */
196 mov ip, lr /* perserve link reg across call */
197 bl lowlevel_init /* go setup pll,mux,memory */
198 mov lr, ip /* restore link */
199 mov pc, lr /* back to my caller */
200 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
201
202 #ifndef CONFIG_SPL_BUILD
203 /*
204 *************************************************************************
205 *
206 * Interrupt handling
207 *
208 *************************************************************************
209 */
210
211 @
212 @ IRQ stack frame.
213 @
214 #define S_FRAME_SIZE 72
215
216 #define S_OLD_R0 68
217 #define S_PSR 64
218 #define S_PC 60
219 #define S_LR 56
220 #define S_SP 52
221
222 #define S_IP 48
223 #define S_FP 44
224 #define S_R10 40
225 #define S_R9 36
226 #define S_R8 32
227 #define S_R7 28
228 #define S_R6 24
229 #define S_R5 20
230 #define S_R4 16
231 #define S_R3 12
232 #define S_R2 8
233 #define S_R1 4
234 #define S_R0 0
235
236 #define MODE_SVC 0x13
237 #define I_BIT 0x80
238
239 /*
240 * use bad_save_user_regs for abort/prefetch/undef/swi ...
241 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
242 */
243
244 .macro bad_save_user_regs
245 @ carve out a frame on current user stack
246 sub sp, sp, #S_FRAME_SIZE
247 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
248 ldr r2, IRQ_STACK_START_IN
249 @ get values for "aborted" pc and cpsr (into parm regs)
250 ldmia r2, {r2 - r3}
251 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
252 add r5, sp, #S_SP
253 mov r1, lr
254 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
255 mov r0, sp @ save current stack into r0 (param register)
256 .endm
257
258 .macro irq_save_user_regs
259 sub sp, sp, #S_FRAME_SIZE
260 stmia sp, {r0 - r12} @ Calling r0-r12
261 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
262 add r8, sp, #S_PC
263 stmdb r8, {sp, lr}^ @ Calling SP, LR
264 str lr, [r8, #0] @ Save calling PC
265 mrs r6, spsr
266 str r6, [r8, #4] @ Save CPSR
267 str r0, [r8, #8] @ Save OLD_R0
268 mov r0, sp
269 .endm
270
271 .macro irq_restore_user_regs
272 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
273 mov r0, r0
274 ldr lr, [sp, #S_PC] @ Get PC
275 add sp, sp, #S_FRAME_SIZE
276 subs pc, lr, #4 @ return & move spsr_svc into cpsr
277 .endm
278
279 .macro get_bad_stack
280 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
281
282 str lr, [r13] @ save caller lr in position 0 of saved stack
283 mrs lr, spsr @ get the spsr
284 str lr, [r13, #4] @ save spsr in position 1 of saved stack
285 mov r13, #MODE_SVC @ prepare SVC-Mode
286 @ msr spsr_c, r13
287 msr spsr, r13 @ switch modes, make sure moves will execute
288 mov lr, pc @ capture return pc
289 movs pc, lr @ jump to next instruction & switch modes.
290 .endm
291
292 .macro get_irq_stack @ setup IRQ stack
293 ldr sp, IRQ_STACK_START
294 .endm
295
296 .macro get_fiq_stack @ setup FIQ stack
297 ldr sp, FIQ_STACK_START
298 .endm
299 #endif /* CONFIG_SPL_BUILD */
300
301 /*
302 * exception handlers
303 */
304 #ifdef CONFIG_SPL_BUILD
305 .align 5
306 do_hang:
307 1:
308 bl 1b /* hang and never return */
309 #else /* !CONFIG_SPL_BUILD */
310 .align 5
311 undefined_instruction:
312 get_bad_stack
313 bad_save_user_regs
314 bl do_undefined_instruction
315
316 .align 5
317 software_interrupt:
318 get_bad_stack
319 bad_save_user_regs
320 bl do_software_interrupt
321
322 .align 5
323 prefetch_abort:
324 get_bad_stack
325 bad_save_user_regs
326 bl do_prefetch_abort
327
328 .align 5
329 data_abort:
330 get_bad_stack
331 bad_save_user_regs
332 bl do_data_abort
333
334 .align 5
335 not_used:
336 get_bad_stack
337 bad_save_user_regs
338 bl do_not_used
339
340 #ifdef CONFIG_USE_IRQ
341
342 .align 5
343 irq:
344 get_irq_stack
345 irq_save_user_regs
346 bl do_irq
347 irq_restore_user_regs
348
349 .align 5
350 fiq:
351 get_fiq_stack
352 /* someone ought to write a more effiction fiq_save_user_regs */
353 irq_save_user_regs
354 bl do_fiq
355 irq_restore_user_regs
356
357 #else
358
359 .align 5
360 irq:
361 get_bad_stack
362 bad_save_user_regs
363 bl do_irq
364
365 .align 5
366 fiq:
367 get_bad_stack
368 bad_save_user_regs
369 bl do_fiq
370
371 #endif
372 #endif /* CONFIG_SPL_BUILD */