blob: cf675995dd7c80895ad32daa8aaebac6311290f4 [file] [log] [blame]
Marek Vasut926227e2011-11-08 23:18:21 +00001/*
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 Groger <mag@sysgo.de>
9 * Copyright (c) 2002 Alex Zupke <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 * Change to support call back into iMX28 bootrom
16 * Copyright (c) 2011 Marek Vasut <marek.vasut@gmail.com>
17 * on behalf of DENX Software Engineering GmbH
18 *
19 * See file CREDITS for list of people who contributed to this
20 * project.
21 *
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; either version 2 of
25 * the License, or (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35 * MA 02111-1307 USA
36 */
37
38#include <asm-offsets.h>
39#include <config.h>
40#include <common.h>
41#include <version.h>
42
43#if defined(CONFIG_OMAP1610)
44#include <./configs/omap1510.h>
45#elif defined(CONFIG_OMAP730)
46#include <./configs/omap730.h>
47#endif
48
49/*
50 *************************************************************************
51 *
52 * Jump vector table as in table 3.1 in [1]
53 *
54 *************************************************************************
55 */
56
57
58.globl _start
59_start:
60 b reset
61#ifdef CONFIG_SPL_BUILD
62/* No exception handlers in preloader */
63 ldr pc, _hang
64 ldr pc, _hang
65 ldr pc, _hang
66 ldr pc, _hang
67 b reset
68 ldr pc, _hang
69 ldr pc, _hang
70
71_hang:
72 .word do_hang
73/* pad to 64 byte boundary */
74 .word 0x12345678
75 .word 0x12345678
76 .word 0x12345678
77 .word 0x12345678
78 .word 0x12345678
79 .word 0x12345678
80 .word 0x12345678
81#else
82 ldr pc, _undefined_instruction
83 ldr pc, _software_interrupt
84 ldr pc, _prefetch_abort
85 ldr pc, _data_abort
86 ldr pc, _not_used
87 ldr pc, _irq
88 ldr pc, _fiq
89
90_undefined_instruction:
91 .word undefined_instruction
92_software_interrupt:
93 .word software_interrupt
94_prefetch_abort:
95 .word prefetch_abort
96_data_abort:
97 .word data_abort
98_not_used:
99 .word not_used
100_irq:
101 .word irq
102_fiq:
103 .word fiq
104
105#endif /* CONFIG_SPL_BUILD */
106 .balignl 16,0xdeadbeef
107
108
109/*
110 *************************************************************************
111 *
112 * Startup Code (reset vector)
113 *
114 * do important init only if we don't start from memory!
115 * setup Memory and board specific bits prior to relocation.
116 * relocate armboot to ram
117 * setup stack
118 *
119 *************************************************************************
120 */
121
122.globl _TEXT_BASE
123_TEXT_BASE:
124 .word CONFIG_SYS_TEXT_BASE
125
126/*
127 * These are defined in the board-specific linker script.
128 * Subtracting _start from them lets the linker put their
129 * relative position in the executable instead of leaving
130 * them null.
131 */
132.globl _bss_start_ofs
133_bss_start_ofs:
134 .word __bss_start - _start
135
136.globl _bss_end_ofs
137_bss_end_ofs:
138 .word __bss_end__ - _start
139
140.globl _end_ofs
141_end_ofs:
142 .word _end - _start
143
144#ifdef CONFIG_USE_IRQ
145/* IRQ stack memory (calculated at run-time) */
146.globl IRQ_STACK_START
147IRQ_STACK_START:
148 .word 0x0badc0de
149
150/* IRQ stack memory (calculated at run-time) */
151.globl FIQ_STACK_START
152FIQ_STACK_START:
153 .word 0x0badc0de
154#endif
155
156/* IRQ stack memory (calculated at run-time) + 8 bytes */
157.globl IRQ_STACK_START_IN
158IRQ_STACK_START_IN:
159 .word 0x0badc0de
160
161/*
162 * the actual reset code
163 */
164
165reset:
166 /*
167 * Store all registers on old stack pointer, this will allow us later to
168 * return to the BootROM and let the BootROM load U-Boot into RAM.
169 */
170 push {r0-r12,r14}
171
172 /*
173 * set the cpu to SVC32 mode
174 */
175 mrs r0,cpsr
176 bic r0,r0,#0x1f
177 orr r0,r0,#0xd3
178 msr cpsr,r0
179
180 /*
181 * we do sys-critical inits only at reboot,
182 * not when booting from ram!
183 */
184#ifndef CONFIG_SKIP_LOWLEVEL_INIT
185 bl cpu_init_crit
186#endif
187
188 bl board_init_ll
189
190 pop {r0-r12,r14}
191 bx lr
192
193/*
194 *************************************************************************
195 *
196 * CPU_init_critical registers
197 *
198 * setup important registers
199 * setup memory timing
200 *
201 *************************************************************************
202 */
203#ifndef CONFIG_SKIP_LOWLEVEL_INIT
204cpu_init_crit:
205 /*
206 * flush v4 I/D caches
207 */
208 mov r0, #0
209 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
210 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
211
212 /*
213 * disable MMU stuff and caches
214 */
215 mrc p15, 0, r0, c1, c0, 0
216 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
217 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
218 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
219 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
220 mcr p15, 0, r0, c1, c0, 0
221
222 mov pc, lr /* back to my caller */
223#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
224
225#ifndef CONFIG_SPL_BUILD
226/*
227 *************************************************************************
228 *
229 * Interrupt handling
230 *
231 *************************************************************************
232 */
233
234@
235@ IRQ stack frame.
236@
237#define S_FRAME_SIZE 72
238
239#define S_OLD_R0 68
240#define S_PSR 64
241#define S_PC 60
242#define S_LR 56
243#define S_SP 52
244
245#define S_IP 48
246#define S_FP 44
247#define S_R10 40
248#define S_R9 36
249#define S_R8 32
250#define S_R7 28
251#define S_R6 24
252#define S_R5 20
253#define S_R4 16
254#define S_R3 12
255#define S_R2 8
256#define S_R1 4
257#define S_R0 0
258
259#define MODE_SVC 0x13
260#define I_BIT 0x80
261
262/*
263 * use bad_save_user_regs for abort/prefetch/undef/swi ...
264 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
265 */
266
267 .macro bad_save_user_regs
268 @ carve out a frame on current user stack
269 sub sp, sp, #S_FRAME_SIZE
270 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12
271 ldr r2, IRQ_STACK_START_IN
272 @ get values for "aborted" pc and cpsr (into parm regs)
273 ldmia r2, {r2 - r3}
274 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack
275 add r5, sp, #S_SP
276 mov r1, lr
277 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
278 mov r0, sp @ save current stack into r0 (param register)
279 .endm
280
281 .macro irq_save_user_regs
282 sub sp, sp, #S_FRAME_SIZE
283 stmia sp, {r0 - r12} @ Calling r0-r12
284 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good.
285 add r8, sp, #S_PC
286 stmdb r8, {sp, lr}^ @ Calling SP, LR
287 str lr, [r8, #0] @ Save calling PC
288 mrs r6, spsr
289 str r6, [r8, #4] @ Save CPSR
290 str r0, [r8, #8] @ Save OLD_R0
291 mov r0, sp
292 .endm
293
294 .macro irq_restore_user_regs
295 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
296 mov r0, r0
297 ldr lr, [sp, #S_PC] @ Get PC
298 add sp, sp, #S_FRAME_SIZE
299 subs pc, lr, #4 @ return & move spsr_svc into cpsr
300 .endm
301
302 .macro get_bad_stack
303 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
304
305 str lr, [r13] @ save caller lr in position 0 of saved stack
306 mrs lr, spsr @ get the spsr
307 str lr, [r13, #4] @ save spsr in position 1 of saved stack
308 mov r13, #MODE_SVC @ prepare SVC-Mode
309 @ msr spsr_c, r13
310 msr spsr, r13 @ switch modes, make sure moves will execute
311 mov lr, pc @ capture return pc
312 movs pc, lr @ jump to next instruction & switch modes.
313 .endm
314
315 .macro get_irq_stack @ setup IRQ stack
316 ldr sp, IRQ_STACK_START
317 .endm
318
319 .macro get_fiq_stack @ setup FIQ stack
320 ldr sp, FIQ_STACK_START
321 .endm
322#endif /* CONFIG_SPL_BUILD */
323
324/*
325 * exception handlers
326 */
327#ifdef CONFIG_SPL_BUILD
328 .align 5
329do_hang:
330 ldr sp, _TEXT_BASE /* switch to abort stack */
3311:
332 bl 1b /* hang and never return */
333#else /* !CONFIG_SPL_BUILD */
334 .align 5
335undefined_instruction:
336 get_bad_stack
337 bad_save_user_regs
338 bl do_undefined_instruction
339
340 .align 5
341software_interrupt:
342 get_bad_stack
343 bad_save_user_regs
344 bl do_software_interrupt
345
346 .align 5
347prefetch_abort:
348 get_bad_stack
349 bad_save_user_regs
350 bl do_prefetch_abort
351
352 .align 5
353data_abort:
354 get_bad_stack
355 bad_save_user_regs
356 bl do_data_abort
357
358 .align 5
359not_used:
360 get_bad_stack
361 bad_save_user_regs
362 bl do_not_used
363
364#ifdef CONFIG_USE_IRQ
365
366 .align 5
367irq:
368 get_irq_stack
369 irq_save_user_regs
370 bl do_irq
371 irq_restore_user_regs
372
373 .align 5
374fiq:
375 get_fiq_stack
376 /* someone ought to write a more effiction fiq_save_user_regs */
377 irq_save_user_regs
378 bl do_fiq
379 irq_restore_user_regs
380
381#else
382
383 .align 5
384irq:
385 get_bad_stack
386 bad_save_user_regs
387 bl do_irq
388
389 .align 5
390fiq:
391 get_bad_stack
392 bad_save_user_regs
393 bl do_fiq
394
395#endif
396#endif /* CONFIG_SPL_BUILD */