blob: f98a7aa35528e979f2456f2a3301138440e628a8 [file] [log] [blame]
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +02001/*
Cyril Chemparathy678e0082010-06-07 14:13:27 -04002 * armboot - Startup Code for ARM1176 CPU-core
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +02003 *
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
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +020038
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020039#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
40#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +020041#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:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200107 .word CONFIG_SYS_PHY_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200108
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
128reset:
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 */
151cpu_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
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400172
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200173 /* Prepare to disable the MMU */
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400174 adr r2, mmu_disable_phys
175 sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - TEXT_BASE)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200176 b mmu_disable
177
178 .align 5
179 /* Run in a single cache-line */
180mmu_disable:
181 mcr p15, 0, r0, c1, c0, 0
182 nop
183 nop
184 mov pc, r2
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400185mmu_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*/
200skip_tcmdisable:
201#endif
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200202#endif
203
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400204#ifdef CONFIG_PERIPORT_REMAP
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200205 /* Peri port setup */
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400206 ldr r0, =CONFIG_PERIPORT_BASE
207 orr r0, r0, #CONFIG_PERIPORT_SIZE
208 mcr p15,0,r0,c15,c2,4
Joonyoung Shim7b921592010-02-08 22:00:52 +0900209#endif
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200210
211 /*
212 * Go setup Memory and board specific bits prior to relocation.
213 */
214 bl lowlevel_init /* go setup pll,mux,memory */
215
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400216#ifndef CONFIG_SKIP_RELOCATE_UBOOT
217relocate: /* 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
228copy_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
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200235#ifdef CONFIG_ENABLE_MMU
236enable_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
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200243 ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200244 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 */
264mmu_enable:
265
266 mcr p15, 0, r0, c1, c0, 0
267 nop
268 nop
269 mov pc, r2
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400270skip_hw_init:
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200271#endif
272
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200273 /* Set up the stack */
274stack_setup:
Seunghyeon Rheea59a23d2009-11-13 16:49:41 +0900275 ldr r0, =CONFIG_SYS_UBOOT_BASE /* base of copy in DRAM */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200276 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
277 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200278 sub sp, r0, #12 /* leave 3 words for abort-stack */
Vitaly Kuzmichev1a27f7d2010-06-15 22:18:11 +0400279 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200280
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200281clear_bss:
282 ldr r0, _bss_start /* find start of bss segment */
283 ldr r1, _bss_end /* stop here */
284 mov r2, #0 /* clear */
285
286clbss_l:
287 str r2, [r0] /* clear loop... */
288 add r0, r0, #4
289 cmp r0, r1
290 ble clbss_l
291
292#ifndef CONFIG_NAND_SPL
293 ldr pc, _start_armboot
294
295_start_armboot:
296 .word start_armboot
297#else
298 b nand_boot
299/* .word nand_boot*/
300#endif
301
302#ifdef CONFIG_ENABLE_MMU
303_mmu_table_base:
304 .word mmu_table
305#endif
306
307#ifndef CONFIG_NAND_SPL
308/*
309 * we assume that cache operation is done before. (eg. cleanup_before_linux())
310 * actually, we don't need to do anything about cache if not use d-cache in
311 * U-Boot. So, in this function we clean only MMU. by scsuh
312 *
313 * void theLastJump(void *kernel, int arch_num, uint boot_params);
314 */
315#ifdef CONFIG_ENABLE_MMU
316 .globl theLastJump
317theLastJump:
318 mov r9, r0
319 ldr r3, =0xfff00000
320 ldr r4, _TEXT_PHY_BASE
321 adr r5, phy_last_jump
322 bic r5, r5, r3
323 orr r5, r5, r4
324 mov pc, r5
325phy_last_jump:
326 /*
327 * disable MMU stuff
328 */
329 mrc p15, 0, r0, c1, c0, 0
330 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
331 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
332 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
333 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
334 mcr p15, 0, r0, c1, c0, 0
335
336 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
337
338 mov r0, #0
339 mov pc, r9
340#endif
Cyril Chemparathy678e0082010-06-07 14:13:27 -0400341
342
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200343/*
344 *************************************************************************
345 *
346 * Interrupt handling
347 *
348 *************************************************************************
349 */
350@
351@ IRQ stack frame.
352@
353#define S_FRAME_SIZE 72
354
355#define S_OLD_R0 68
356#define S_PSR 64
357#define S_PC 60
358#define S_LR 56
359#define S_SP 52
360
361#define S_IP 48
362#define S_FP 44
363#define S_R10 40
364#define S_R9 36
365#define S_R8 32
366#define S_R7 28
367#define S_R6 24
368#define S_R5 20
369#define S_R4 16
370#define S_R3 12
371#define S_R2 8
372#define S_R1 4
373#define S_R0 0
374
375#define MODE_SVC 0x13
376#define I_BIT 0x80
377
378/*
379 * use bad_save_user_regs for abort/prefetch/undef/swi ...
380 */
381
382 .macro bad_save_user_regs
383 /* carve out a frame on current user stack */
384 sub sp, sp, #S_FRAME_SIZE
385 /* Save user registers (now in svc mode) r0-r12 */
386 stmia sp, {r0 - r12}
387
388 ldr r2, _armboot_start
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200389 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200390 /* set base 2 words into abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200391 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200392 /* get values for "aborted" pc and cpsr (into parm regs) */
393 ldmia r2, {r2 - r3}
394 /* grab pointer to old stack */
395 add r0, sp, #S_FRAME_SIZE
396
397 add r5, sp, #S_SP
398 mov r1, lr
399 /* save sp_SVC, lr_SVC, pc, cpsr */
400 stmia r5, {r0 - r3}
401 /* save current stack into r0 (param register) */
402 mov r0, sp
403 .endm
404
405 .macro get_bad_stack
406 /* setup our mode stack (enter in banked mode) */
407 ldr r13, _armboot_start
408 /* move past malloc pool */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200409 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200410 /* move to reserved a couple spots for abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200411 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200412
413 /* save caller lr in position 0 of saved stack */
414 str lr, [r13]
415 /* get the spsr */
416 mrs lr, spsr
417 /* save spsr in position 1 of saved stack */
418 str lr, [r13, #4]
419
420 /* prepare SVC-Mode */
421 mov r13, #MODE_SVC
422 @ msr spsr_c, r13
423 /* switch modes, make sure moves will execute */
424 msr spsr, r13
425 /* capture return pc */
426 mov lr, pc
427 /* jump to next instruction & switch modes. */
428 movs pc, lr
429 .endm
430
431 .macro get_bad_stack_swi
432 /* space on current stack for scratch reg. */
433 sub r13, r13, #4
434 /* save R0's value. */
435 str r0, [r13]
436 /* get data regions start */
437 ldr r0, _armboot_start
438 /* move past malloc pool */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200439 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200440 /* move past gbl and a couple spots for abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200441 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200442 /* save caller lr in position 0 of saved stack */
443 str lr, [r0]
444 /* get the spsr */
445 mrs r0, spsr
446 /* save spsr in position 1 of saved stack */
447 str lr, [r0, #4]
448 /* restore r0 */
449 ldr r0, [r13]
450 /* pop stack entry */
451 add r13, r13, #4
452 .endm
453
454/*
455 * exception handlers
456 */
457 .align 5
458undefined_instruction:
459 get_bad_stack
460 bad_save_user_regs
461 bl do_undefined_instruction
462
463 .align 5
464software_interrupt:
465 get_bad_stack_swi
466 bad_save_user_regs
467 bl do_software_interrupt
468
469 .align 5
470prefetch_abort:
471 get_bad_stack
472 bad_save_user_regs
473 bl do_prefetch_abort
474
475 .align 5
476data_abort:
477 get_bad_stack
478 bad_save_user_regs
479 bl do_data_abort
480
481 .align 5
482not_used:
483 get_bad_stack
484 bad_save_user_regs
485 bl do_not_used
486
487 .align 5
488irq:
489 get_bad_stack
490 bad_save_user_regs
491 bl do_irq
492
493 .align 5
494fiq:
495 get_bad_stack
496 bad_save_user_regs
497 bl do_fiq
498#endif /* CONFIG_NAND_SPL */