blob: 68a356d13e9a2d9069961d56286040bf4adeda39 [file] [log] [blame]
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +02001/*
2 * armboot - Startup Code for S3C6400/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
Minkyu Kang47e801b2009-11-04 16:07:59 +090038#include <asm/arch/s3c6400.h>
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +020039
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020040#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
41#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +020042#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
99_TEXT_BASE:
100 .word TEXT_BASE
101
102/*
103 * Below variable is very important because we use MMU in U-Boot.
104 * Without it, we cannot run code correctly before MMU is ON.
105 * by scsuh.
106 */
107_TEXT_PHY_BASE:
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200108 .word CONFIG_SYS_PHY_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200109
110.globl _armboot_start
111_armboot_start:
112 .word _start
113
114/*
115 * These are defined in the board-specific linker script.
116 */
117.globl _bss_start
118_bss_start:
119 .word __bss_start
120
121.globl _bss_end
122_bss_end:
123 .word _end
124
125/*
126 * the actual reset code
127 */
128
129reset:
130 /*
131 * set the cpu to SVC32 mode
132 */
133 mrs r0, cpsr
134 bic r0, r0, #0x3f
135 orr r0, r0, #0xd3
136 msr cpsr, r0
137
138/*
139 *************************************************************************
140 *
141 * CPU_init_critical registers
142 *
143 * setup important registers
144 * setup memory timing
145 *
146 *************************************************************************
147 */
148 /*
149 * we do sys-critical inits only at reboot,
150 * not when booting from ram!
151 */
152cpu_init_crit:
153 /*
154 * When booting from NAND - it has definitely been a reset, so, no need
155 * to flush caches and disable the MMU
156 */
157#ifndef CONFIG_NAND_SPL
158 /*
159 * flush v4 I/D caches
160 */
161 mov r0, #0
162 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
163 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
164
165 /*
166 * disable MMU stuff and caches
167 */
168 mrc p15, 0, r0, c1, c0, 0
169 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
170 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
171 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
172 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
173 /* Prepare to disable the MMU */
174 adr r1, mmu_disable_phys
175 /* We presume we're within the first 1024 bytes */
176 and r1, r1, #0x3fc
177 ldr r2, _TEXT_PHY_BASE
178 ldr r3, =0xfff00000
179 and r2, r2, r3
180 orr r2, r2, r1
181 b mmu_disable
182
183 .align 5
184 /* Run in a single cache-line */
185mmu_disable:
186 mcr p15, 0, r0, c1, c0, 0
187 nop
188 nop
189 mov pc, r2
190#endif
191
192mmu_disable_phys:
193 /* Peri port setup */
194 ldr r0, =0x70000000
195 orr r0, r0, #0x13
196 mcr p15,0,r0,c15,c2,4 @ 256M (0x70000000 - 0x7fffffff)
197
198 /*
199 * Go setup Memory and board specific bits prior to relocation.
200 */
201 bl lowlevel_init /* go setup pll,mux,memory */
202
203after_copy:
204#ifdef CONFIG_ENABLE_MMU
205enable_mmu:
206 /* enable domain access */
207 ldr r5, =0x0000ffff
208 mcr p15, 0, r5, c3, c0, 0 /* load domain access register */
209
210 /* Set the TTB register */
211 ldr r0, _mmu_table_base
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200212 ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200213 ldr r2, =0xfff00000
214 bic r0, r0, r2
215 orr r1, r0, r1
216 mcr p15, 0, r1, c2, c0, 0
217
218 /* Enable the MMU */
219 mrc p15, 0, r0, c1, c0, 0
220 orr r0, r0, #1 /* Set CR_M to enable MMU */
221
222 /* Prepare to enable the MMU */
223 adr r1, skip_hw_init
224 and r1, r1, #0x3fc
225 ldr r2, _TEXT_BASE
226 ldr r3, =0xfff00000
227 and r2, r2, r3
228 orr r2, r2, r1
229 b mmu_enable
230
231 .align 5
232 /* Run in a single cache-line */
233mmu_enable:
234
235 mcr p15, 0, r0, c1, c0, 0
236 nop
237 nop
238 mov pc, r2
239#endif
240
241skip_hw_init:
242 /* Set up the stack */
243stack_setup:
Seunghyeon Rheea59a23d2009-11-13 16:49:41 +0900244 ldr r0, =CONFIG_SYS_UBOOT_BASE /* base of copy in DRAM */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200245 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
246 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200247 sub sp, r0, #12 /* leave 3 words for abort-stack */
248
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200249clear_bss:
250 ldr r0, _bss_start /* find start of bss segment */
251 ldr r1, _bss_end /* stop here */
252 mov r2, #0 /* clear */
253
254clbss_l:
255 str r2, [r0] /* clear loop... */
256 add r0, r0, #4
257 cmp r0, r1
258 ble clbss_l
259
260#ifndef CONFIG_NAND_SPL
261 ldr pc, _start_armboot
262
263_start_armboot:
264 .word start_armboot
265#else
266 b nand_boot
267/* .word nand_boot*/
268#endif
269
270#ifdef CONFIG_ENABLE_MMU
271_mmu_table_base:
272 .word mmu_table
273#endif
274
275#ifndef CONFIG_NAND_SPL
276/*
277 * we assume that cache operation is done before. (eg. cleanup_before_linux())
278 * actually, we don't need to do anything about cache if not use d-cache in
279 * U-Boot. So, in this function we clean only MMU. by scsuh
280 *
281 * void theLastJump(void *kernel, int arch_num, uint boot_params);
282 */
283#ifdef CONFIG_ENABLE_MMU
284 .globl theLastJump
285theLastJump:
286 mov r9, r0
287 ldr r3, =0xfff00000
288 ldr r4, _TEXT_PHY_BASE
289 adr r5, phy_last_jump
290 bic r5, r5, r3
291 orr r5, r5, r4
292 mov pc, r5
293phy_last_jump:
294 /*
295 * disable MMU stuff
296 */
297 mrc p15, 0, r0, c1, c0, 0
298 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */
299 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */
300 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */
301 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */
302 mcr p15, 0, r0, c1, c0, 0
303
304 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
305
306 mov r0, #0
307 mov pc, r9
308#endif
309/*
310 *************************************************************************
311 *
312 * Interrupt handling
313 *
314 *************************************************************************
315 */
316@
317@ IRQ stack frame.
318@
319#define S_FRAME_SIZE 72
320
321#define S_OLD_R0 68
322#define S_PSR 64
323#define S_PC 60
324#define S_LR 56
325#define S_SP 52
326
327#define S_IP 48
328#define S_FP 44
329#define S_R10 40
330#define S_R9 36
331#define S_R8 32
332#define S_R7 28
333#define S_R6 24
334#define S_R5 20
335#define S_R4 16
336#define S_R3 12
337#define S_R2 8
338#define S_R1 4
339#define S_R0 0
340
341#define MODE_SVC 0x13
342#define I_BIT 0x80
343
344/*
345 * use bad_save_user_regs for abort/prefetch/undef/swi ...
346 */
347
348 .macro bad_save_user_regs
349 /* carve out a frame on current user stack */
350 sub sp, sp, #S_FRAME_SIZE
351 /* Save user registers (now in svc mode) r0-r12 */
352 stmia sp, {r0 - r12}
353
354 ldr r2, _armboot_start
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200355 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200356 /* set base 2 words into abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200357 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200358 /* get values for "aborted" pc and cpsr (into parm regs) */
359 ldmia r2, {r2 - r3}
360 /* grab pointer to old stack */
361 add r0, sp, #S_FRAME_SIZE
362
363 add r5, sp, #S_SP
364 mov r1, lr
365 /* save sp_SVC, lr_SVC, pc, cpsr */
366 stmia r5, {r0 - r3}
367 /* save current stack into r0 (param register) */
368 mov r0, sp
369 .endm
370
371 .macro get_bad_stack
372 /* setup our mode stack (enter in banked mode) */
373 ldr r13, _armboot_start
374 /* move past malloc pool */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200375 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200376 /* move to reserved a couple spots for abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200377 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200378
379 /* save caller lr in position 0 of saved stack */
380 str lr, [r13]
381 /* get the spsr */
382 mrs lr, spsr
383 /* save spsr in position 1 of saved stack */
384 str lr, [r13, #4]
385
386 /* prepare SVC-Mode */
387 mov r13, #MODE_SVC
388 @ msr spsr_c, r13
389 /* switch modes, make sure moves will execute */
390 msr spsr, r13
391 /* capture return pc */
392 mov lr, pc
393 /* jump to next instruction & switch modes. */
394 movs pc, lr
395 .endm
396
397 .macro get_bad_stack_swi
398 /* space on current stack for scratch reg. */
399 sub r13, r13, #4
400 /* save R0's value. */
401 str r0, [r13]
402 /* get data regions start */
403 ldr r0, _armboot_start
404 /* move past malloc pool */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200405 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200406 /* move past gbl and a couple spots for abort stack */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200407 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8)
Guennadi Liakhovetski9b077732008-08-31 00:39:46 +0200408 /* save caller lr in position 0 of saved stack */
409 str lr, [r0]
410 /* get the spsr */
411 mrs r0, spsr
412 /* save spsr in position 1 of saved stack */
413 str lr, [r0, #4]
414 /* restore r0 */
415 ldr r0, [r13]
416 /* pop stack entry */
417 add r13, r13, #4
418 .endm
419
420/*
421 * exception handlers
422 */
423 .align 5
424undefined_instruction:
425 get_bad_stack
426 bad_save_user_regs
427 bl do_undefined_instruction
428
429 .align 5
430software_interrupt:
431 get_bad_stack_swi
432 bad_save_user_regs
433 bl do_software_interrupt
434
435 .align 5
436prefetch_abort:
437 get_bad_stack
438 bad_save_user_regs
439 bl do_prefetch_abort
440
441 .align 5
442data_abort:
443 get_bad_stack
444 bad_save_user_regs
445 bl do_data_abort
446
447 .align 5
448not_used:
449 get_bad_stack
450 bad_save_user_regs
451 bl do_not_used
452
453 .align 5
454irq:
455 get_bad_stack
456 bad_save_user_regs
457 bl do_irq
458
459 .align 5
460fiq:
461 get_bad_stack
462 bad_save_user_regs
463 bl do_fiq
464#endif /* CONFIG_NAND_SPL */