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