]> git.ipfire.org Git - people/ms/u-boot.git/blob - arch/arm/cpu/arm1176/start.S
Merge branch 'master' of git://git.denx.de/u-boot-arm
[people/ms/u-boot.git] / arch / arm / cpu / arm1176 / start.S
1 /*
2 * armboot - Startup Code for ARM1176 CPU-core
3 *
4 * Copyright (c) 2007 Samsung Electronics
5 *
6 * Copyright (C) 2008
7 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
8 *
9 * See file CREDITS for list of people who contributed to this
10 * project.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
25 * MA 02111-1307 USA
26 *
27 * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com)
28 * 2007-09-21 - Added MoviNAND and OneNAND boot codes by
29 * jsgood (jsgood.yang@samsung.com)
30 * Base codes by scsuh (sc.suh)
31 */
32
33 #include <config.h>
34 #include <version.h>
35 #ifdef CONFIG_ENABLE_MMU
36 #include <asm/proc/domain.h>
37 #endif
38
39 #if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
40 #define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE
41 #endif
42
43 /*
44 *************************************************************************
45 *
46 * Jump vector table as in table 3.1 in [1]
47 *
48 *************************************************************************
49 */
50
51 .globl _start
52 _start: b reset
53 #ifndef CONFIG_NAND_SPL
54 ldr pc, _undefined_instruction
55 ldr pc, _software_interrupt
56 ldr pc, _prefetch_abort
57 ldr pc, _data_abort
58 ldr pc, _not_used
59 ldr pc, _irq
60 ldr pc, _fiq
61
62 _undefined_instruction:
63 .word undefined_instruction
64 _software_interrupt:
65 .word software_interrupt
66 _prefetch_abort:
67 .word prefetch_abort
68 _data_abort:
69 .word data_abort
70 _not_used:
71 .word not_used
72 _irq:
73 .word irq
74 _fiq:
75 .word fiq
76 _pad:
77 .word 0x12345678 /* now 16*4=64 */
78 #else
79 . = _start + 64
80 #endif
81
82 .global _end_vect
83 _end_vect:
84 .balignl 16,0xdeadbeef
85 /*
86 *************************************************************************
87 *
88 * Startup Code (reset vector)
89 *
90 * do important init only if we don't start from memory!
91 * setup Memory and board specific bits prior to relocation.
92 * relocate armboot to ram
93 * setup stack
94 *
95 *************************************************************************
96 */
97
98 _TEXT_BASE:
99 .word TEXT_BASE
100
101 /*
102 * Below variable is very important because we use MMU in U-Boot.
103 * Without it, we cannot run code correctly before MMU is ON.
104 * by scsuh.
105 */
106 _TEXT_PHY_BASE:
107 .word CONFIG_SYS_PHY_UBOOT_BASE
108
109 .globl _armboot_start
110 _armboot_start:
111 .word _start
112
113 /*
114 * These are defined in the board-specific linker script.
115 */
116 .globl _bss_start
117 _bss_start:
118 .word __bss_start
119
120 .globl _bss_end
121 _bss_end:
122 .word _end
123
124 /*
125 * the actual reset code
126 */
127
128 reset:
129 /*
130 * set the cpu to SVC32 mode
131 */
132 mrs r0, cpsr
133 bic r0, r0, #0x3f
134 orr r0, r0, #0xd3
135 msr cpsr, r0
136
137 /*
138 *************************************************************************
139 *
140 * CPU_init_critical registers
141 *
142 * setup important registers
143 * setup memory timing
144 *
145 *************************************************************************
146 */
147 /*
148 * we do sys-critical inits only at reboot,
149 * not when booting from ram!
150 */
151 cpu_init_crit:
152 /*
153 * When booting from NAND - it has definitely been a reset, so, no need
154 * to flush caches and disable the MMU
155 */
156 #ifndef CONFIG_NAND_SPL
157 /*
158 * flush v4 I/D caches
159 */
160 mov r0, #0
161 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
162 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
163
164 /*
165 * disable MMU stuff and caches
166 */
167 mrc p15, 0, r0, c1, c0, 0
168 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
169 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
170 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
171 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
172
173 /* Prepare to disable the MMU */
174 adr r2, mmu_disable_phys
175 sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - TEXT_BASE)
176 b mmu_disable
177
178 .align 5
179 /* Run in a single cache-line */
180 mmu_disable:
181 mcr p15, 0, r0, c1, c0, 0
182 nop
183 nop
184 mov pc, r2
185 mmu_disable_phys:
186
187 #ifdef CONFIG_DISABLE_TCM
188 /*
189 * Disable the TCMs
190 */
191 mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */
192 cmp r0, #0
193 beq skip_tcmdisable
194 mov r1, #0
195 mov r2, #1
196 tst r0, r2
197 mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/
198 tst r0, r2, LSL #16
199 mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/
200 skip_tcmdisable:
201 #endif
202 #endif
203
204 #ifdef CONFIG_PERIPORT_REMAP
205 /* Peri port setup */
206 ldr r0, =CONFIG_PERIPORT_BASE
207 orr r0, r0, #CONFIG_PERIPORT_SIZE
208 mcr p15,0,r0,c15,c2,4
209 #endif
210
211 /*
212 * Go setup Memory and board specific bits prior to relocation.
213 */
214 bl lowlevel_init /* go setup pll,mux,memory */
215
216 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
217 relocate: /* relocate U-Boot to RAM */
218 adr r0, _start /* r0 <- current position of code */
219 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
220 cmp r0, r1 /* don't reloc during debug */
221 beq stack_setup
222
223 ldr r2, _armboot_start
224 ldr r3, _bss_start
225 sub r2, r3, r2 /* r2 <- size of armboot */
226 add r2, r0, r2 /* r2 <- source end address */
227
228 copy_loop:
229 ldmia r0!, {r3-r10} /* copy from source address [r0] */
230 stmia r1!, {r3-r10} /* copy to target address [r1] */
231 cmp r0, r2 /* until source end addreee [r2] */
232 ble copy_loop
233 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
234
235 #ifdef CONFIG_ENABLE_MMU
236 enable_mmu:
237 /* enable domain access */
238 ldr r5, =0x0000ffff
239 mcr p15, 0, r5, c3, c0, 0 /* load domain access register */
240
241 /* Set the TTB register */
242 ldr r0, _mmu_table_base
243 ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
244 ldr r2, =0xfff00000
245 bic r0, r0, r2
246 orr r1, r0, r1
247 mcr p15, 0, r1, c2, c0, 0
248
249 /* Enable the MMU */
250 mrc p15, 0, r0, c1, c0, 0
251 orr r0, r0, #1 /* Set CR_M to enable MMU */
252
253 /* Prepare to enable the MMU */
254 adr r1, skip_hw_init
255 and r1, r1, #0x3fc
256 ldr r2, _TEXT_BASE
257 ldr r3, =0xfff00000
258 and r2, r2, r3
259 orr r2, r2, r1
260 b mmu_enable
261
262 .align 5
263 /* Run in a single cache-line */
264 mmu_enable:
265
266 mcr p15, 0, r0, c1, c0, 0
267 nop
268 nop
269 mov pc, r2
270 skip_hw_init:
271 #endif
272
273 /* Set up the stack */
274 stack_setup:
275 ldr r0, =CONFIG_SYS_UBOOT_BASE /* base of copy in DRAM */
276 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
277 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
278 sub sp, r0, #12 /* leave 3 words for abort-stack */
279
280 clear_bss:
281 ldr r0, _bss_start /* find start of bss segment */
282 ldr r1, _bss_end /* stop here */
283 mov r2, #0 /* clear */
284
285 clbss_l:
286 str r2, [r0] /* clear loop... */
287 add r0, r0, #4
288 cmp r0, r1
289 ble clbss_l
290
291 #ifndef CONFIG_NAND_SPL
292 ldr pc, _start_armboot
293
294 _start_armboot:
295 .word start_armboot
296 #else
297 b nand_boot
298 /* .word nand_boot*/
299 #endif
300
301 #ifdef CONFIG_ENABLE_MMU
302 _mmu_table_base:
303 .word mmu_table
304 #endif
305
306 #ifndef CONFIG_NAND_SPL
307 /*
308 * we assume that cache operation is done before. (eg. cleanup_before_linux())
309 * actually, we don't need to do anything about cache if not use d-cache in
310 * U-Boot. So, in this function we clean only MMU. by scsuh
311 *
312 * void theLastJump(void *kernel, int arch_num, uint boot_params);
313 */
314 #ifdef CONFIG_ENABLE_MMU
315 .globl theLastJump
316 theLastJump:
317 mov r9, r0
318 ldr r3, =0xfff00000
319 ldr r4, _TEXT_PHY_BASE
320 adr r5, phy_last_jump
321 bic r5, r5, r3
322 orr r5, r5, r4
323 mov pc, r5
324 phy_last_jump:
325 /*
326 * disable MMU stuff
327 */
328 mrc p15, 0, r0, c1, c0, 0
329 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
330 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
331 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
332 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
333 mcr p15, 0, r0, c1, c0, 0
334
335 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
336
337 mov r0, #0
338 mov pc, r9
339 #endif
340
341
342 /*
343 *************************************************************************
344 *
345 * Interrupt handling
346 *
347 *************************************************************************
348 */
349 @
350 @ IRQ stack frame.
351 @
352 #define S_FRAME_SIZE 72
353
354 #define S_OLD_R0 68
355 #define S_PSR 64
356 #define S_PC 60
357 #define S_LR 56
358 #define S_SP 52
359
360 #define S_IP 48
361 #define S_FP 44
362 #define S_R10 40
363 #define S_R9 36
364 #define S_R8 32
365 #define S_R7 28
366 #define S_R6 24
367 #define S_R5 20
368 #define S_R4 16
369 #define S_R3 12
370 #define S_R2 8
371 #define S_R1 4
372 #define S_R0 0
373
374 #define MODE_SVC 0x13
375 #define I_BIT 0x80
376
377 /*
378 * use bad_save_user_regs for abort/prefetch/undef/swi ...
379 */
380
381 .macro bad_save_user_regs
382 /* carve out a frame on current user stack */
383 sub sp, sp, #S_FRAME_SIZE
384 /* Save user registers (now in svc mode) r0-r12 */
385 stmia sp, {r0 - r12}
386
387 ldr r2, _armboot_start
388 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
389 /* set base 2 words into abort stack */
390 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
391 /* get values for "aborted" pc and cpsr (into parm regs) */
392 ldmia r2, {r2 - r3}
393 /* grab pointer to old stack */
394 add r0, sp, #S_FRAME_SIZE
395
396 add r5, sp, #S_SP
397 mov r1, lr
398 /* save sp_SVC, lr_SVC, pc, cpsr */
399 stmia r5, {r0 - r3}
400 /* save current stack into r0 (param register) */
401 mov r0, sp
402 .endm
403
404 .macro get_bad_stack
405 /* setup our mode stack (enter in banked mode) */
406 ldr r13, _armboot_start
407 /* move past malloc pool */
408 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
409 /* move to reserved a couple spots for abort stack */
410 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
411
412 /* save caller lr in position 0 of saved stack */
413 str lr, [r13]
414 /* get the spsr */
415 mrs lr, spsr
416 /* save spsr in position 1 of saved stack */
417 str lr, [r13, #4]
418
419 /* prepare SVC-Mode */
420 mov r13, #MODE_SVC
421 @ msr spsr_c, r13
422 /* switch modes, make sure moves will execute */
423 msr spsr, r13
424 /* capture return pc */
425 mov lr, pc
426 /* jump to next instruction & switch modes. */
427 movs pc, lr
428 .endm
429
430 .macro get_bad_stack_swi
431 /* space on current stack for scratch reg. */
432 sub r13, r13, #4
433 /* save R0's value. */
434 str r0, [r13]
435 /* get data regions start */
436 ldr r0, _armboot_start
437 /* move past malloc pool */
438 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN)
439 /* move past gbl and a couple spots for abort stack */
440 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
441 /* save caller lr in position 0 of saved stack */
442 str lr, [r0]
443 /* get the spsr */
444 mrs r0, spsr
445 /* save spsr in position 1 of saved stack */
446 str lr, [r0, #4]
447 /* restore r0 */
448 ldr r0, [r13]
449 /* pop stack entry */
450 add r13, r13, #4
451 .endm
452
453 /*
454 * exception handlers
455 */
456 .align 5
457 undefined_instruction:
458 get_bad_stack
459 bad_save_user_regs
460 bl do_undefined_instruction
461
462 .align 5
463 software_interrupt:
464 get_bad_stack_swi
465 bad_save_user_regs
466 bl do_software_interrupt
467
468 .align 5
469 prefetch_abort:
470 get_bad_stack
471 bad_save_user_regs
472 bl do_prefetch_abort
473
474 .align 5
475 data_abort:
476 get_bad_stack
477 bad_save_user_regs
478 bl do_data_abort
479
480 .align 5
481 not_used:
482 get_bad_stack
483 bad_save_user_regs
484 bl do_not_used
485
486 .align 5
487 irq:
488 get_bad_stack
489 bad_save_user_regs
490 bl do_irq
491
492 .align 5
493 fiq:
494 get_bad_stack
495 bad_save_user_regs
496 bl do_fiq
497 #endif /* CONFIG_NAND_SPL */