]>
Commit | Line | Data |
---|---|---|
8ed96046 WD |
1 | /* |
2 | * armboot - Startup Code for OMP2420/ARM1136 CPU-core | |
3 | * | |
082acfd4 | 4 | * Copyright (c) 2004 Texas Instruments <r-woodruff2@ti.com> |
8ed96046 | 5 | * |
fa82f871 AA |
6 | * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> |
7 | * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> | |
792a09eb | 8 | * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> |
8ed96046 WD |
9 | * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> |
10 | * Copyright (c) 2003 Kshitij <kshitij@ti.com> | |
11 | * | |
3765b3e7 | 12 | * SPDX-License-Identifier: GPL-2.0+ |
8ed96046 WD |
13 | */ |
14 | ||
25ddd1fb | 15 | #include <asm-offsets.h> |
8ed96046 WD |
16 | #include <config.h> |
17 | #include <version.h> | |
8ed96046 | 18 | .globl _start |
082acfd4 | 19 | _start: b reset |
401bb30b | 20 | #ifdef CONFIG_SPL_BUILD |
751b9b51 KP |
21 | ldr pc, _hang |
22 | ldr pc, _hang | |
23 | ldr pc, _hang | |
24 | ldr pc, _hang | |
25 | ldr pc, _hang | |
26 | ldr pc, _hang | |
27 | ldr pc, _hang | |
28 | ||
29 | _hang: | |
30 | .word do_hang | |
31 | .word 0x12345678 | |
32 | .word 0x12345678 | |
33 | .word 0x12345678 | |
34 | .word 0x12345678 | |
35 | .word 0x12345678 | |
36 | .word 0x12345678 | |
37 | .word 0x12345678 /* now 16*4=64 */ | |
38 | #else | |
8ed96046 WD |
39 | ldr pc, _undefined_instruction |
40 | ldr pc, _software_interrupt | |
41 | ldr pc, _prefetch_abort | |
42 | ldr pc, _data_abort | |
43 | ldr pc, _not_used | |
44 | ldr pc, _irq | |
45 | ldr pc, _fiq | |
46 | ||
082acfd4 | 47 | _undefined_instruction: .word undefined_instruction |
8ed96046 WD |
48 | _software_interrupt: .word software_interrupt |
49 | _prefetch_abort: .word prefetch_abort | |
50 | _data_abort: .word data_abort | |
51 | _not_used: .word not_used | |
52 | _irq: .word irq | |
53 | _fiq: .word fiq | |
082acfd4 | 54 | _pad: .word 0x12345678 /* now 16*4=64 */ |
401bb30b | 55 | #endif /* CONFIG_SPL_BUILD */ |
8ed96046 WD |
56 | .global _end_vect |
57 | _end_vect: | |
58 | ||
59 | .balignl 16,0xdeadbeef | |
60 | /* | |
61 | ************************************************************************* | |
62 | * | |
63 | * Startup Code (reset vector) | |
64 | * | |
65 | * do important init only if we don't start from memory! | |
66 | * setup Memory and board specific bits prior to relocation. | |
67 | * relocate armboot to ram | |
68 | * setup stack | |
69 | * | |
70 | ************************************************************************* | |
71 | */ | |
72 | ||
8ed96046 WD |
73 | #ifdef CONFIG_USE_IRQ |
74 | /* IRQ stack memory (calculated at run-time) */ | |
75 | .globl IRQ_STACK_START | |
76 | IRQ_STACK_START: | |
77 | .word 0x0badc0de | |
78 | ||
79 | /* IRQ stack memory (calculated at run-time) */ | |
80 | .globl FIQ_STACK_START | |
81 | FIQ_STACK_START: | |
82 | .word 0x0badc0de | |
83 | #endif | |
84 | ||
e48b7c0a HS |
85 | /* IRQ stack memory (calculated at run-time) + 8 bytes */ |
86 | .globl IRQ_STACK_START_IN | |
87 | IRQ_STACK_START_IN: | |
88 | .word 0x0badc0de | |
e48b7c0a | 89 | |
e48b7c0a HS |
90 | /* |
91 | * the actual reset code | |
92 | */ | |
93 | ||
94 | reset: | |
95 | /* | |
96 | * set the cpu to SVC32 mode | |
97 | */ | |
98 | mrs r0,cpsr | |
99 | bic r0,r0,#0x1f | |
100 | orr r0,r0,#0xd3 | |
101 | msr cpsr,r0 | |
102 | ||
e48b7c0a HS |
103 | /* the mask ROM code should have PLL and others stable */ |
104 | #ifndef CONFIG_SKIP_LOWLEVEL_INIT | |
105 | bl cpu_init_crit | |
106 | #endif | |
107 | ||
e05e5de7 | 108 | bl _main |
e48b7c0a HS |
109 | |
110 | /*------------------------------------------------------------------------------*/ | |
111 | ||
e05e5de7 AA |
112 | .globl c_runtime_cpu_setup |
113 | c_runtime_cpu_setup: | |
e48b7c0a | 114 | |
e05e5de7 | 115 | bx lr |
bafe7437 | 116 | |
8ed96046 WD |
117 | /* |
118 | ************************************************************************* | |
119 | * | |
120 | * CPU_init_critical registers | |
121 | * | |
122 | * setup important registers | |
123 | * setup memory timing | |
124 | * | |
125 | ************************************************************************* | |
126 | */ | |
40c642bc | 127 | #ifndef CONFIG_SKIP_LOWLEVEL_INIT |
8ed96046 WD |
128 | cpu_init_crit: |
129 | /* | |
130 | * flush v4 I/D caches | |
131 | */ | |
132 | mov r0, #0 | |
409a07c9 GD |
133 | mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ |
134 | mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ | |
8ed96046 WD |
135 | |
136 | /* | |
137 | * disable MMU stuff and caches | |
138 | */ | |
139 | mrc p15, 0, r0, c1, c0, 0 | |
140 | bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) | |
141 | bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) | |
142 | orr r0, r0, #0x00000002 @ set bit 2 (A) Align | |
8ed96046 | 143 | orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache |
8ed96046 WD |
144 | mcr p15, 0, r0, c1, c0, 0 |
145 | ||
146 | /* | |
082acfd4 WD |
147 | * Jump to board specific initialization... The Mask ROM will have already initialized |
148 | * basic memory. Go here to bump up clock rate and handle wake up conditions. | |
8ed96046 | 149 | */ |
082acfd4 | 150 | mov ip, lr /* persevere link reg across call */ |
87cb6862 | 151 | bl lowlevel_init /* go setup pll,mux,memory */ |
082acfd4 WD |
152 | mov lr, ip /* restore link */ |
153 | mov pc, lr /* back to my caller */ | |
40c642bc | 154 | #endif /* CONFIG_SKIP_LOWLEVEL_INIT */ |
751b9b51 | 155 | |
401bb30b | 156 | #ifndef CONFIG_SPL_BUILD |
8ed96046 WD |
157 | /* |
158 | ************************************************************************* | |
159 | * | |
160 | * Interrupt handling | |
161 | * | |
162 | ************************************************************************* | |
163 | */ | |
164 | @ | |
165 | @ IRQ stack frame. | |
166 | @ | |
167 | #define S_FRAME_SIZE 72 | |
168 | ||
169 | #define S_OLD_R0 68 | |
170 | #define S_PSR 64 | |
171 | #define S_PC 60 | |
172 | #define S_LR 56 | |
173 | #define S_SP 52 | |
174 | ||
175 | #define S_IP 48 | |
176 | #define S_FP 44 | |
177 | #define S_R10 40 | |
178 | #define S_R9 36 | |
179 | #define S_R8 32 | |
180 | #define S_R7 28 | |
181 | #define S_R6 24 | |
182 | #define S_R5 20 | |
183 | #define S_R4 16 | |
184 | #define S_R3 12 | |
185 | #define S_R2 8 | |
186 | #define S_R1 4 | |
187 | #define S_R0 0 | |
188 | ||
189 | #define MODE_SVC 0x13 | |
190 | #define I_BIT 0x80 | |
191 | ||
192 | /* | |
193 | * use bad_save_user_regs for abort/prefetch/undef/swi ... | |
194 | * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling | |
195 | */ | |
196 | ||
197 | .macro bad_save_user_regs | |
082acfd4 | 198 | sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack |
8ed96046 WD |
199 | stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 |
200 | ||
e48b7c0a | 201 | ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack |
082acfd4 | 202 | ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs) |
8ed96046 WD |
203 | add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack |
204 | ||
205 | add r5, sp, #S_SP | |
206 | mov r1, lr | |
082acfd4 WD |
207 | stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr |
208 | mov r0, sp @ save current stack into r0 (param register) | |
8ed96046 WD |
209 | .endm |
210 | ||
211 | .macro irq_save_user_regs | |
212 | sub sp, sp, #S_FRAME_SIZE | |
213 | stmia sp, {r0 - r12} @ Calling r0-r12 | |
082acfd4 WD |
214 | add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. |
215 | stmdb r8, {sp, lr}^ @ Calling SP, LR | |
216 | str lr, [r8, #0] @ Save calling PC | |
217 | mrs r6, spsr | |
218 | str r6, [r8, #4] @ Save CPSR | |
219 | str r0, [r8, #8] @ Save OLD_R0 | |
8ed96046 WD |
220 | mov r0, sp |
221 | .endm | |
222 | ||
223 | .macro irq_restore_user_regs | |
224 | ldmia sp, {r0 - lr}^ @ Calling r0 - lr | |
225 | mov r0, r0 | |
226 | ldr lr, [sp, #S_PC] @ Get PC | |
227 | add sp, sp, #S_FRAME_SIZE | |
228 | subs pc, lr, #4 @ return & move spsr_svc into cpsr | |
229 | .endm | |
230 | ||
231 | .macro get_bad_stack | |
e48b7c0a | 232 | ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode) |
8ed96046 WD |
233 | |
234 | str lr, [r13] @ save caller lr in position 0 of saved stack | |
082acfd4 WD |
235 | mrs lr, spsr @ get the spsr |
236 | str lr, [r13, #4] @ save spsr in position 1 of saved stack | |
8ed96046 WD |
237 | |
238 | mov r13, #MODE_SVC @ prepare SVC-Mode | |
239 | @ msr spsr_c, r13 | |
082acfd4 WD |
240 | msr spsr, r13 @ switch modes, make sure moves will execute |
241 | mov lr, pc @ capture return pc | |
242 | movs pc, lr @ jump to next instruction & switch modes. | |
8ed96046 WD |
243 | .endm |
244 | ||
245 | .macro get_bad_stack_swi | |
082acfd4 WD |
246 | sub r13, r13, #4 @ space on current stack for scratch reg. |
247 | str r0, [r13] @ save R0's value. | |
e48b7c0a | 248 | ldr r0, IRQ_STACK_START_IN @ get data regions start |
8ed96046 | 249 | str lr, [r0] @ save caller lr in position 0 of saved stack |
4411b2ae | 250 | mrs lr, spsr @ get the spsr |
082acfd4 | 251 | str lr, [r0, #4] @ save spsr in position 1 of saved stack |
4411b2ae | 252 | ldr lr, [r0] @ restore lr |
082acfd4 WD |
253 | ldr r0, [r13] @ restore r0 |
254 | add r13, r13, #4 @ pop stack entry | |
8ed96046 WD |
255 | .endm |
256 | ||
257 | .macro get_irq_stack @ setup IRQ stack | |
258 | ldr sp, IRQ_STACK_START | |
259 | .endm | |
260 | ||
261 | .macro get_fiq_stack @ setup FIQ stack | |
262 | ldr sp, FIQ_STACK_START | |
263 | .endm | |
401bb30b | 264 | #endif /* CONFIG_SPL_BUILD */ |
8ed96046 WD |
265 | |
266 | /* | |
267 | * exception handlers | |
268 | */ | |
401bb30b | 269 | #ifdef CONFIG_SPL_BUILD |
751b9b51 KP |
270 | .align 5 |
271 | do_hang: | |
751b9b51 | 272 | bl hang /* hang and never return */ |
401bb30b | 273 | #else /* !CONFIG_SPL_BUILD */ |
082acfd4 | 274 | .align 5 |
8ed96046 WD |
275 | undefined_instruction: |
276 | get_bad_stack | |
277 | bad_save_user_regs | |
082acfd4 | 278 | bl do_undefined_instruction |
8ed96046 WD |
279 | |
280 | .align 5 | |
281 | software_interrupt: | |
282 | get_bad_stack_swi | |
283 | bad_save_user_regs | |
082acfd4 | 284 | bl do_software_interrupt |
8ed96046 WD |
285 | |
286 | .align 5 | |
287 | prefetch_abort: | |
288 | get_bad_stack | |
289 | bad_save_user_regs | |
082acfd4 | 290 | bl do_prefetch_abort |
8ed96046 WD |
291 | |
292 | .align 5 | |
293 | data_abort: | |
294 | get_bad_stack | |
295 | bad_save_user_regs | |
082acfd4 | 296 | bl do_data_abort |
8ed96046 WD |
297 | |
298 | .align 5 | |
299 | not_used: | |
300 | get_bad_stack | |
301 | bad_save_user_regs | |
082acfd4 | 302 | bl do_not_used |
8ed96046 WD |
303 | |
304 | #ifdef CONFIG_USE_IRQ | |
305 | ||
306 | .align 5 | |
307 | irq: | |
308 | get_irq_stack | |
309 | irq_save_user_regs | |
082acfd4 | 310 | bl do_irq |
8ed96046 WD |
311 | irq_restore_user_regs |
312 | ||
313 | .align 5 | |
314 | fiq: | |
315 | get_fiq_stack | |
316 | /* someone ought to write a more effiction fiq_save_user_regs */ | |
317 | irq_save_user_regs | |
082acfd4 | 318 | bl do_fiq |
8ed96046 WD |
319 | irq_restore_user_regs |
320 | ||
321 | #else | |
322 | ||
323 | .align 5 | |
324 | irq: | |
325 | get_bad_stack | |
326 | bad_save_user_regs | |
082acfd4 | 327 | bl do_irq |
8ed96046 WD |
328 | |
329 | .align 5 | |
330 | fiq: | |
331 | get_bad_stack | |
332 | bad_save_user_regs | |
082acfd4 | 333 | bl do_fiq |
8ed96046 WD |
334 | |
335 | #endif | |
336 | .align 5 | |
337 | .global arm1136_cache_flush | |
338 | arm1136_cache_flush: | |
e47f2db5 | 339 | #if !defined(CONFIG_SYS_ICACHE_OFF) |
8ed96046 | 340 | mcr p15, 0, r1, c7, c5, 0 @ invalidate I cache |
7e4a9e6d | 341 | #endif |
e47f2db5 | 342 | #if !defined(CONFIG_SYS_DCACHE_OFF) |
7e4a9e6d HS |
343 | mcr p15, 0, r1, c7, c14, 0 @ invalidate D cache |
344 | #endif | |
8ed96046 | 345 | mov pc, lr @ back to caller |
401bb30b | 346 | #endif /* CONFIG_SPL_BUILD */ |