]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/arm/cpu/arm1176/start.S
Merge branch 'master' of git://git.denx.de/u-boot-imx
[people/ms/u-boot.git] / arch / arm / cpu / arm1176 / start.S
CommitLineData
9b07773f 1/*
678e008c 2 * armboot - Startup Code for ARM1176 CPU-core
9b07773f
GL
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
25ddd1fb 33#include <asm-offsets.h>
9b07773f
GL
34#include <config.h>
35#include <version.h>
36#ifdef CONFIG_ENABLE_MMU
37#include <asm/proc/domain.h>
38#endif
9b07773f 39
6d0f6bcf
JCPV
40#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
41#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE
9b07773f
GL
42#endif
43
44/*
45 *************************************************************************
46 *
47 * Jump vector table as in table 3.1 in [1]
48 *
49 *************************************************************************
50 */
51
52.globl _start
53_start: b reset
54#ifndef CONFIG_NAND_SPL
55 ldr pc, _undefined_instruction
56 ldr pc, _software_interrupt
57 ldr pc, _prefetch_abort
58 ldr pc, _data_abort
59 ldr pc, _not_used
60 ldr pc, _irq
61 ldr pc, _fiq
62
63_undefined_instruction:
64 .word undefined_instruction
65_software_interrupt:
66 .word software_interrupt
67_prefetch_abort:
68 .word prefetch_abort
69_data_abort:
70 .word data_abort
71_not_used:
72 .word not_used
73_irq:
74 .word irq
75_fiq:
76 .word fiq
77_pad:
78 .word 0x12345678 /* now 16*4=64 */
79#else
80 . = _start + 64
81#endif
82
83.global _end_vect
84_end_vect:
85 .balignl 16,0xdeadbeef
86/*
87 *************************************************************************
88 *
89 * Startup Code (reset vector)
90 *
91 * do important init only if we don't start from memory!
92 * setup Memory and board specific bits prior to relocation.
93 * relocate armboot to ram
94 * setup stack
95 *
96 *************************************************************************
97 */
98
a51dd67a 99.globl _TEXT_BASE
9b07773f 100_TEXT_BASE:
14d0a02a 101 .word CONFIG_SYS_TEXT_BASE
9b07773f
GL
102
103/*
104 * Below variable is very important because we use MMU in U-Boot.
105 * Without it, we cannot run code correctly before MMU is ON.
106 * by scsuh.
107 */
108_TEXT_PHY_BASE:
6d0f6bcf 109 .word CONFIG_SYS_PHY_UBOOT_BASE
9b07773f 110
9b07773f
GL
111/*
112 * These are defined in the board-specific linker script.
ea34c9d6
DA
113 * Subtracting _start from them lets the linker put their
114 * relative position in the executable instead of leaving
115 * them null.
9b07773f 116 */
9b07773f 117
ea34c9d6
DA
118.globl _bss_start_ofs
119_bss_start_ofs:
120 .word __bss_start - _start
9b07773f 121
ea34c9d6
DA
122.globl _bss_end_ofs
123_bss_end_ofs:
124 .word _end - _start
a51dd67a 125
ea34c9d6
DA
126/* IRQ stack memory (calculated at run-time) + 8 bytes */
127.globl IRQ_STACK_START_IN
128IRQ_STACK_START_IN:
129 .word 0x0badc0de
a51dd67a
HS
130
131/*
132 * the actual reset code
133 */
134
135reset:
136 /*
137 * set the cpu to SVC32 mode
138 */
139 mrs r0, cpsr
140 bic r0, r0, #0x3f
141 orr r0, r0, #0xd3
142 msr cpsr, r0
143
144/*
145 *************************************************************************
146 *
147 * CPU_init_critical registers
148 *
149 * setup important registers
150 * setup memory timing
151 *
152 *************************************************************************
153 */
154 /*
155 * we do sys-critical inits only at reboot,
156 * not when booting from ram!
157 */
158cpu_init_crit:
159 /*
160 * When booting from NAND - it has definitely been a reset, so, no need
161 * to flush caches and disable the MMU
162 */
163#ifndef CONFIG_NAND_SPL
164 /*
165 * flush v4 I/D caches
166 */
167 mov r0, #0
168 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
169 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
170
171 /*
172 * disable MMU stuff and caches
173 */
174 mrc p15, 0, r0, c1, c0, 0
175 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
176 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
177 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
178 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
179
180 /* Prepare to disable the MMU */
181 adr r2, mmu_disable_phys
14d0a02a 182 sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE)
a51dd67a
HS
183 b mmu_disable
184
185 .align 5
186 /* Run in a single cache-line */
187mmu_disable:
188 mcr p15, 0, r0, c1, c0, 0
189 nop
190 nop
191 mov pc, r2
192mmu_disable_phys:
193
194#ifdef CONFIG_DISABLE_TCM
195 /*
196 * Disable the TCMs
197 */
198 mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */
199 cmp r0, #0
200 beq skip_tcmdisable
201 mov r1, #0
202 mov r2, #1
203 tst r0, r2
204 mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/
205 tst r0, r2, LSL #16
206 mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/
207skip_tcmdisable:
208#endif
209#endif
210
211#ifdef CONFIG_PERIPORT_REMAP
212 /* Peri port setup */
213 ldr r0, =CONFIG_PERIPORT_BASE
214 orr r0, r0, #CONFIG_PERIPORT_SIZE
215 mcr p15,0,r0,c15,c2,4
216#endif
217
218 /*
219 * Go setup Memory and board specific bits prior to relocation.
220 */
221 bl lowlevel_init /* go setup pll,mux,memory */
222
223/* Set stackpointer in internal RAM to call board_init_f */
224call_board_init_f:
225 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
296cae73 226 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
a51dd67a
HS
227 ldr r0,=0x00000000
228 bl board_init_f
229
230/*------------------------------------------------------------------------------*/
231
232/*
233 * void relocate_code (addr_sp, gd, addr_moni)
234 *
235 * This "function" does not return, instead it continues in RAM
236 * after relocating the monitor code.
237 *
238 */
239 .globl relocate_code
240relocate_code:
241 mov r4, r0 /* save addr_sp */
242 mov r5, r1 /* save addr of gd */
243 mov r6, r2 /* save addr of destination */
a51dd67a
HS
244
245 /* Set up the stack */
246stack_setup:
247 mov sp, r4
248
249 adr r0, _start
a1a47d3c
AB
250 cmp r0, r6
251 beq clear_bss /* skip relocation */
a78fb68f 252 mov r1, r6 /* r1 <- scratch for copy_loop */
a51dd67a 253 ldr r2, _TEXT_BASE
ea34c9d6
DA
254 ldr r3, _bss_start_ofs
255 add r2, r0, r3 /* r2 <- source end address */
a51dd67a 256
a51dd67a
HS
257copy_loop:
258 ldmia r0!, {r9-r10} /* copy from source address [r0] */
a78fb68f 259 stmia r1!, {r9-r10} /* copy to target address [r1] */
da90d4ce
AA
260 cmp r0, r2 /* until source end address [r2] */
261 blo copy_loop
a51dd67a
HS
262
263#ifndef CONFIG_PRELOADER
ea34c9d6
DA
264 /*
265 * fix .rel.dyn relocations
266 */
267 ldr r0, _TEXT_BASE /* r0 <- Text base */
a78fb68f 268 sub r9, r6, r0 /* r9 <- relocation offset */
ea34c9d6
DA
269 ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
270 add r10, r10, r0 /* r10 <- sym table in FLASH */
271 ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
272 add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
273 ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
274 add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
a51dd67a 275fixloop:
e42a7dff
AA
276 ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
277 add r0, r0, r9 /* r0 <- location to fix up in RAM */
ea34c9d6 278 ldr r1, [r2, #4]
1f52d89f
AB
279 and r7, r1, #0xff
280 cmp r7, #23 /* relative fixup? */
ea34c9d6 281 beq fixrel
1f52d89f 282 cmp r7, #2 /* absolute fixup? */
ea34c9d6
DA
283 beq fixabs
284 /* ignore unknown type of fixup */
285 b fixnext
286fixabs:
287 /* absolute fix: set location to (offset) symbol value */
288 mov r1, r1, LSR #4 /* r1 <- symbol index in .dynsym */
289 add r1, r10, r1 /* r1 <- address of symbol in table */
290 ldr r1, [r1, #4] /* r1 <- symbol value */
e42a7dff 291 add r1, r9 /* r1 <- relocated sym addr */
ea34c9d6
DA
292 b fixnext
293fixrel:
294 /* relative fix: increase location by offset */
295 ldr r1, [r0]
296 add r1, r1, r9
297fixnext:
298 str r1, [r0]
e42a7dff 299 add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
a51dd67a 300 cmp r2, r3
ea34c9d6 301 blo fixloop
a51dd67a 302#endif
a51dd67a
HS
303
304#ifdef CONFIG_ENABLE_MMU
305enable_mmu:
306 /* enable domain access */
307 ldr r5, =0x0000ffff
308 mcr p15, 0, r5, c3, c0, 0 /* load domain access register */
309
310 /* Set the TTB register */
311 ldr r0, _mmu_table_base
312 ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
313 ldr r2, =0xfff00000
314 bic r0, r0, r2
315 orr r1, r0, r1
316 mcr p15, 0, r1, c2, c0, 0
317
318 /* Enable the MMU */
319 mrc p15, 0, r0, c1, c0, 0
320 orr r0, r0, #1 /* Set CR_M to enable MMU */
321
322 /* Prepare to enable the MMU */
323 adr r1, skip_hw_init
324 and r1, r1, #0x3fc
325 ldr r2, _TEXT_BASE
326 ldr r3, =0xfff00000
327 and r2, r2, r3
328 orr r2, r2, r1
329 b mmu_enable
330
331 .align 5
332 /* Run in a single cache-line */
333mmu_enable:
334
335 mcr p15, 0, r0, c1, c0, 0
336 nop
337 nop
338 mov pc, r2
339skip_hw_init:
340#endif
341
342clear_bss:
343#ifndef CONFIG_PRELOADER
ea34c9d6
DA
344 ldr r0, _bss_start_ofs
345 ldr r1, _bss_end_ofs
a51dd67a 346 ldr r3, _TEXT_BASE /* Text base */
a78fb68f 347 mov r4, r6 /* reloc addr */
a51dd67a 348 add r0, r0, r4
a51dd67a
HS
349 add r1, r1, r4
350 mov r2, #0x00000000 /* clear */
351
352clbss_l:str r2, [r0] /* clear loop... */
353 add r0, r0, #4
354 cmp r0, r1
355 bne clbss_l
356
357 bl coloured_LED_init
358 bl red_LED_on
359#endif
360
361/*
362 * We are done. Do not return, instead branch to second part of board
363 * initialization, now running from RAM.
364 */
365#ifdef CONFIG_NAND_SPL
366 ldr pc, _nand_boot
367
368_nand_boot: .word nand_boot
369#else
ea34c9d6
DA
370 ldr r0, _board_init_r_ofs
371 adr r1, _start
372 add lr, r0, r1
ea34c9d6 373 add lr, lr, r9
a51dd67a
HS
374 /* setup parameters for board_init_r */
375 mov r0, r5 /* gd_t */
a78fb68f 376 mov r1, r6 /* dest_addr */
a51dd67a 377 /* jump to it ... */
a51dd67a
HS
378 mov pc, lr
379
ea34c9d6
DA
380_board_init_r_ofs:
381 .word board_init_r - _start
a51dd67a
HS
382#endif
383
e42a7dff
AA
384_rel_dyn_start_ofs:
385 .word __rel_dyn_start - _start
386_rel_dyn_end_ofs:
387 .word __rel_dyn_end - _start
388_dynsym_start_ofs:
389 .word __dynsym_start - _start
390
9b07773f
GL
391#ifdef CONFIG_ENABLE_MMU
392_mmu_table_base:
393 .word mmu_table
394#endif
395
396#ifndef CONFIG_NAND_SPL
397/*
398 * we assume that cache operation is done before. (eg. cleanup_before_linux())
399 * actually, we don't need to do anything about cache if not use d-cache in
400 * U-Boot. So, in this function we clean only MMU. by scsuh
401 *
402 * void theLastJump(void *kernel, int arch_num, uint boot_params);
403 */
404#ifdef CONFIG_ENABLE_MMU
405 .globl theLastJump
406theLastJump:
407 mov r9, r0
408 ldr r3, =0xfff00000
409 ldr r4, _TEXT_PHY_BASE
410 adr r5, phy_last_jump
411 bic r5, r5, r3
412 orr r5, r5, r4
413 mov pc, r5
414phy_last_jump:
415 /*
416 * disable MMU stuff
417 */
418 mrc p15, 0, r0, c1, c0, 0
419 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
420 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
421 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
422 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
423 mcr p15, 0, r0, c1, c0, 0
424
425 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
426
427 mov r0, #0
428 mov pc, r9
429#endif
678e008c
CC
430
431
9b07773f
GL
432/*
433 *************************************************************************
434 *
435 * Interrupt handling
436 *
437 *************************************************************************
438 */
439@
440@ IRQ stack frame.
441@
442#define S_FRAME_SIZE 72
443
444#define S_OLD_R0 68
445#define S_PSR 64
446#define S_PC 60
447#define S_LR 56
448#define S_SP 52
449
450#define S_IP 48
451#define S_FP 44
452#define S_R10 40
453#define S_R9 36
454#define S_R8 32
455#define S_R7 28
456#define S_R6 24
457#define S_R5 20
458#define S_R4 16
459#define S_R3 12
460#define S_R2 8
461#define S_R1 4
462#define S_R0 0
463
464#define MODE_SVC 0x13
465#define I_BIT 0x80
466
467/*
468 * use bad_save_user_regs for abort/prefetch/undef/swi ...
469 */
470
471 .macro bad_save_user_regs
472 /* carve out a frame on current user stack */
473 sub sp, sp, #S_FRAME_SIZE
474 /* Save user registers (now in svc mode) r0-r12 */
475 stmia sp, {r0 - r12}
476
a51dd67a 477 ldr r2, IRQ_STACK_START_IN
9b07773f
GL
478 /* get values for "aborted" pc and cpsr (into parm regs) */
479 ldmia r2, {r2 - r3}
480 /* grab pointer to old stack */
481 add r0, sp, #S_FRAME_SIZE
482
483 add r5, sp, #S_SP
484 mov r1, lr
485 /* save sp_SVC, lr_SVC, pc, cpsr */
486 stmia r5, {r0 - r3}
487 /* save current stack into r0 (param register) */
488 mov r0, sp
489 .endm
490
491 .macro get_bad_stack
a51dd67a 492 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
9b07773f
GL
493
494 /* save caller lr in position 0 of saved stack */
495 str lr, [r13]
496 /* get the spsr */
497 mrs lr, spsr
498 /* save spsr in position 1 of saved stack */
499 str lr, [r13, #4]
500
501 /* prepare SVC-Mode */
502 mov r13, #MODE_SVC
503 @ msr spsr_c, r13
504 /* switch modes, make sure moves will execute */
505 msr spsr, r13
506 /* capture return pc */
507 mov lr, pc
508 /* jump to next instruction & switch modes. */
509 movs pc, lr
510 .endm
511
512 .macro get_bad_stack_swi
513 /* space on current stack for scratch reg. */
514 sub r13, r13, #4
515 /* save R0's value. */
516 str r0, [r13]
a51dd67a 517 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
9b07773f
GL
518 /* save caller lr in position 0 of saved stack */
519 str lr, [r0]
520 /* get the spsr */
521 mrs r0, spsr
522 /* save spsr in position 1 of saved stack */
523 str lr, [r0, #4]
524 /* restore r0 */
525 ldr r0, [r13]
526 /* pop stack entry */
527 add r13, r13, #4
528 .endm
529
530/*
531 * exception handlers
532 */
533 .align 5
534undefined_instruction:
535 get_bad_stack
536 bad_save_user_regs
537 bl do_undefined_instruction
538
539 .align 5
540software_interrupt:
541 get_bad_stack_swi
542 bad_save_user_regs
543 bl do_software_interrupt
544
545 .align 5
546prefetch_abort:
547 get_bad_stack
548 bad_save_user_regs
549 bl do_prefetch_abort
550
551 .align 5
552data_abort:
553 get_bad_stack
554 bad_save_user_regs
555 bl do_data_abort
556
557 .align 5
558not_used:
559 get_bad_stack
560 bad_save_user_regs
561 bl do_not_used
562
563 .align 5
564irq:
565 get_bad_stack
566 bad_save_user_regs
567 bl do_irq
568
569 .align 5
570fiq:
571 get_bad_stack
572 bad_save_user_regs
573 bl do_fiq
574#endif /* CONFIG_NAND_SPL */