blob: fdedc915fb5822481f59481343e142a936bac01a [file] [log] [blame]
wdenkfe8c2802002-11-03 00:38:21 +00001/*
2 * armboot - Startup Code for ARM720 CPU-core
3 *
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26
wdenkfe8c2802002-11-03 00:38:21 +000027#include <config.h>
28#include <version.h>
29
30
31/*
32 *************************************************************************
33 *
34 * Jump vector table as in table 3.1 in [1]
35 *
36 *************************************************************************
37 */
38
39
40.globl _start
41_start: b reset
42 ldr pc, _undefined_instruction
43 ldr pc, _software_interrupt
44 ldr pc, _prefetch_abort
45 ldr pc, _data_abort
46 ldr pc, _not_used
47 ldr pc, _irq
48 ldr pc, _fiq
49
50_undefined_instruction: .word undefined_instruction
51_software_interrupt: .word software_interrupt
52_prefetch_abort: .word prefetch_abort
53_data_abort: .word data_abort
54_not_used: .word not_used
55_irq: .word irq
56_fiq: .word fiq
57
58 .balignl 16,0xdeadbeef
59
60
61/*
62 *************************************************************************
63 *
64 * Startup Code (reset vector)
65 *
66 * do important init only if we don't start from memory!
67 * relocate armboot to ram
68 * setup stack
69 * jump to second stage
70 *
71 *************************************************************************
72 */
73
wdenkfe8c2802002-11-03 00:38:21 +000074_TEXT_BASE:
75 .word TEXT_BASE
76
77.globl _armboot_start
78_armboot_start:
79 .word _start
80
81/*
82 * Note: _armboot_end_data and _armboot_end are defined
83 * by the (board-dependent) linker script.
84 * _armboot_end_data is the first usable FLASH address after armboot
85 */
86.globl _armboot_end_data
87_armboot_end_data:
88 .word armboot_end_data
89.globl _armboot_end
90_armboot_end:
91 .word armboot_end
92
93/*
94 * _armboot_real_end is the first usable RAM address behind armboot
95 * and the various stacks
96 */
97.globl _armboot_real_end
98_armboot_real_end:
99 .word 0x0badc0de
100
101#ifdef CONFIG_USE_IRQ
102/* IRQ stack memory (calculated at run-time) */
103.globl IRQ_STACK_START
104IRQ_STACK_START:
105 .word 0x0badc0de
106
107/* IRQ stack memory (calculated at run-time) */
108.globl FIQ_STACK_START
109FIQ_STACK_START:
110 .word 0x0badc0de
111#endif
112
113
114/*
115 * the actual reset code
116 */
117
118reset:
119 /*
120 * set the cpu to SVC32 mode
121 */
122 mrs r0,cpsr
123 bic r0,r0,#0x1f
124 orr r0,r0,#0x13
125 msr cpsr,r0
126
127 /*
128 * we do sys-critical inits only at reboot,
129 * not when booting from ram!
130 */
131#ifdef CONFIG_INIT_CRITICAL
132 bl cpu_init_crit
133#endif
134
135relocate:
136 /*
137 * relocate armboot to RAM
138 */
139 adr r0, _start /* r0 <- current position of code */
140 ldr r2, _armboot_start
141 ldr r3, _armboot_end
142 sub r2, r3, r2 /* r2 <- size of armboot */
143 ldr r1, _TEXT_BASE /* r1 <- destination address */
144 add r2, r0, r2 /* r2 <- source end address */
145
146 /*
147 * r0 = source address
148 * r1 = target address
149 * r2 = source end address
150 */
151copy_loop:
152 ldmia r0!, {r3-r10}
153 stmia r1!, {r3-r10}
154 cmp r0, r2
155 ble copy_loop
156
157 /* set up the stack */
158 ldr r0, _armboot_end
159 add r0, r0, #CONFIG_STACKSIZE
160 sub sp, r0, #12 /* leave 3 words for abort-stack */
161
162 ldr pc, _start_armboot
163
164_start_armboot: .word start_armboot
165
166
167/*
168 *************************************************************************
169 *
170 * CPU_init_critical registers
171 *
172 * setup important registers
173 * setup memory timing
174 *
175 *************************************************************************
176 */
177
178
179/* Interupt-Controller base addresses */
180INTMR1: .word 0x80000280 @ 32 bit size
181INTMR2: .word 0x80001280 @ 16 bit size
182INTMR3: .word 0x80002280 @ 8 bit size
183
184/* SYSCONs */
185SYSCON1: .word 0x80000100
186SYSCON2: .word 0x80001100
187SYSCON3: .word 0x80002200
188
189#define CLKCTL 0x6 /* mask */
190#define CLKCTL_18 0x0 /* 18.432 MHz */
191#define CLKCTL_36 0x2 /* 36.864 MHz */
192#define CLKCTL_49 0x4 /* 49.152 MHz */
193#define CLKCTL_73 0x6 /* 73.728 MHz */
194
195cpu_init_crit:
196 /*
197 * mask all IRQs by clearing all bits in the INTMRs
198 */
199 mov r1, #0x00
200 ldr r0, INTMR1
201 str r1, [r0]
202 ldr r0, INTMR2
203 str r1, [r0]
204 ldr r0, INTMR3
205 str r1, [r0]
206
207 /*
208 * flush v4 I/D caches
209 */
210 mov r0, #0
211 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
212 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
213
214 /*
215 * disable MMU stuff and caches
216 */
217 mrc p15,0,r0,c1,c0
218 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
219 bic r0, r0, #0x0000008f @ clear bits 7, 3:0 (B--- WCAM)
220 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
221 mcr p15,0,r0,c1,c0
222
223#ifdef CONFIG_ARM7_REVD
224 /* set clock speed */
225 /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */
226 /* !!! not doing DRAM refresh properly! */
227 ldr r0, SYSCON3
228 ldr r1, [r0]
229 bic r1, r1, #CLKCTL
230 orr r1, r1, #CLKCTL_36
231 str r1, [r0]
232#endif
233
234 /*
235 * before relocating, we have to setup RAM timing
236 * because memory timing is board-dependend, you will
237 * find a memsetup.S in your board directory.
238 */
239 mov ip, lr
240 bl memsetup
241 mov lr, ip
242
243 mov pc, lr
244
245
wdenkfe8c2802002-11-03 00:38:21 +0000246/*
247 *************************************************************************
248 *
249 * Interrupt handling
250 *
251 *************************************************************************
252 */
253
254@
255@ IRQ stack frame.
256@
257#define S_FRAME_SIZE 72
258
259#define S_OLD_R0 68
260#define S_PSR 64
261#define S_PC 60
262#define S_LR 56
263#define S_SP 52
264
265#define S_IP 48
266#define S_FP 44
267#define S_R10 40
268#define S_R9 36
269#define S_R8 32
270#define S_R7 28
271#define S_R6 24
272#define S_R5 20
273#define S_R4 16
274#define S_R3 12
275#define S_R2 8
276#define S_R1 4
277#define S_R0 0
278
279#define MODE_SVC 0x13
280#define I_BIT 0x80
281
282/*
283 * use bad_save_user_regs for abort/prefetch/undef/swi ...
284 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
285 */
286
287 .macro bad_save_user_regs
288 sub sp, sp, #S_FRAME_SIZE
289 stmia sp, {r0 - r12} @ Calling r0-r12
290 add r8, sp, #S_PC
291
292 ldr r2, _armboot_end
293 add r2, r2, #CONFIG_STACKSIZE
294 sub r2, r2, #8
295 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0
296 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
297
298 add r5, sp, #S_SP
299 mov r1, lr
300 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r
301 mov r0, sp
302 .endm
303
304 .macro irq_save_user_regs
305 sub sp, sp, #S_FRAME_SIZE
306 stmia sp, {r0 - r12} @ Calling r0-r12
307 add r8, sp, #S_PC
308 stmdb r8, {sp, lr}^ @ Calling SP, LR
309 str lr, [r8, #0] @ Save calling PC
310 mrs r6, spsr
311 str r6, [r8, #4] @ Save CPSR
312 str r0, [r8, #8] @ Save OLD_R0
313 mov r0, sp
314 .endm
315
316 .macro irq_restore_user_regs
317 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
318 mov r0, r0
319 ldr lr, [sp, #S_PC] @ Get PC
320 add sp, sp, #S_FRAME_SIZE
321 subs pc, lr, #4 @ return & move spsr_svc into cpsr
322 .endm
323
324 .macro get_bad_stack
325 ldr r13, _armboot_end @ setup our mode stack
326 add r13, r13, #CONFIG_STACKSIZE @ resides at top of normal stack
327 sub r13, r13, #8
328
329 str lr, [r13] @ save caller lr / spsr
330 mrs lr, spsr
331 str lr, [r13, #4]
332
333 mov r13, #MODE_SVC @ prepare SVC-Mode
334 msr spsr_c, r13
335 mov lr, pc
336 movs pc, lr
337 .endm
338
339 .macro get_irq_stack @ setup IRQ stack
340 ldr sp, IRQ_STACK_START
341 .endm
342
343 .macro get_fiq_stack @ setup FIQ stack
344 ldr sp, FIQ_STACK_START
345 .endm
346
347/*
348 * exception handlers
349 */
350 .align 5
351undefined_instruction:
352 get_bad_stack
353 bad_save_user_regs
354 bl do_undefined_instruction
355
356 .align 5
357software_interrupt:
358 get_bad_stack
359 bad_save_user_regs
360 bl do_software_interrupt
361
362 .align 5
363prefetch_abort:
364 get_bad_stack
365 bad_save_user_regs
366 bl do_prefetch_abort
367
368 .align 5
369data_abort:
370 get_bad_stack
371 bad_save_user_regs
372 bl do_data_abort
373
374 .align 5
375not_used:
376 get_bad_stack
377 bad_save_user_regs
378 bl do_not_used
379
380#ifdef CONFIG_USE_IRQ
381
382 .align 5
383irq:
384 get_irq_stack
385 irq_save_user_regs
386 bl do_irq
387 irq_restore_user_regs
388
389 .align 5
390fiq:
391 get_fiq_stack
392 /* someone ought to write a more effiction fiq_save_user_regs */
393 irq_save_user_regs
394 bl do_fiq
395 irq_restore_user_regs
396
397#else
398
399 .align 5
400irq:
401 get_bad_stack
402 bad_save_user_regs
403 bl do_irq
404
405 .align 5
406fiq:
407 get_bad_stack
408 bad_save_user_regs
409 bl do_fiq
410
411#endif
412
413 .align 5
414.globl reset_cpu
415reset_cpu:
416 mov ip, #0
417 mcr p15, 0, ip, c7, c7, 0 @ invalidate cache
418 mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4)
419 mrc p15, 0, ip, c1, c0, 0 @ get ctrl register
420 bic ip, ip, #0x000f @ ............wcam
421 bic ip, ip, #0x2100 @ ..v....s........
422 mcr p15, 0, ip, c1, c0, 0 @ ctrl register
423 mov pc, r0