2 * armboot - Startup Code for ARM920 CPU-core
4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de>
5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de>
6 * Copyright (c) 2002 Gary Jennejohn <gj@denx.de>
8 * See file CREDITS for list of people who contributed to this
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33 *************************************************************************
35 * Jump vector table as in table 3.1 in [1]
37 *************************************************************************
43 ldr pc, _undefined_instruction
44 ldr pc, _software_interrupt
45 ldr pc, _prefetch_abort
51 _undefined_instruction: .word undefined_instruction
52 _software_interrupt: .word software_interrupt
53 _prefetch_abort: .word prefetch_abort
54 _data_abort: .word data_abort
55 _not_used: .word not_used
59 .balignl 16,0xdeadbeef
63 *************************************************************************
65 * Startup Code (reset vector)
67 * do important init only if we don't start from memory!
68 * relocate armboot to ram
70 * jump to second stage
72 *************************************************************************
83 * These are defined in the board-specific linker script.
94 /* IRQ stack memory (calculated at run-time) */
95 .globl IRQ_STACK_START
99 /* IRQ stack memory (calculated at run-time) */
100 .globl FIQ_STACK_START
107 * the actual reset code
112 * set the cpu to SVC32 mode
119 * if board has a red led use it to show U-Boot is running
124 #ifdef CONFIG_AT91RM9200
125 #ifdef CONFIG_BOOTBINFUNC
126 /* code based on entry.S from ATMEL */
127 #define AT91C_BASE_CKGR 0xFFFFFC20
129 /* Get the CKGR Base Address */
130 ldr r1, =AT91C_BASE_CKGR
132 /* Main oscillator Enable register APMC_MOR : Enable main oscillator , OSCOUNT = 0xFF */
133 /* ldr r0, = AT91C_CKGR_MOSCEN:OR:AT91C_CKGR_OSCOUNT */
135 str r0, [r1, #CKGR_MOR]
136 /* Add loop to compensate Main Oscillator startup time */
143 /* Insure word alignment */
148 * This does a lot more than just set up the memory, which
149 * is why it's called lowlevelinit
151 bl lowlevelinit /* in memsetup.S */
153 /* ------------------------------------
154 * Read/modify/write CP15 control register
155 * -------------------------------------
156 * read cp15 control register (cp15 r1) in r0
157 * ------------------------------------
159 mrc p15, 0, r0, c1, c0, 0
160 /* Reset bit :Little Endian end fast bus mode */
162 /* Set bit :Asynchronous clock mode, Not Fast Bus */
166 /* write r0 in cp15 control register (cp15 r1) */
167 mcr p15, 0, r0, c1, c0, 0
168 #endif /* CONFIG_BOOTBINFUNC */
170 * relocate exeception table
182 /* turn off the watchdog */
183 #if defined(CONFIG_S3C2400)
184 # define pWTCON 0x15300000
185 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */
186 # define CLKDIVN 0x14800014 /* clock divisor register */
187 #elif defined(CONFIG_S3C2410)
188 # define pWTCON 0x53000000
189 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
190 # define INTSUBMSK 0x4A00001C
191 # define CLKDIVN 0x4C000014 /* clock divisor register */
194 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
200 * mask all IRQs by setting all bits in the INTMR - default
205 # if defined(CONFIG_S3C2410)
211 /* FCLK:HCLK:PCLK = 1:2:4 */
212 /* default FCLK is 120 MHz ! */
216 #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
219 * we do sys-critical inits only at reboot,
220 * not when booting from ram!
222 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
226 #ifdef CONFIG_AT91RM9200
227 #ifdef CONFIG_BOOTBINFUNC
228 relocate: /* relocate U-Boot to RAM */
229 adr r0, _start /* r0 <- current position of code */
230 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
231 cmp r0, r1 /* don't reloc during debug */
234 ldr r2, _armboot_start
236 sub r2, r3, r2 /* r2 <- size of armboot */
237 add r2, r0, r2 /* r2 <- source end address */
240 ldmia r0!, {r3-r10} /* copy from source address [r0] */
241 stmia r1!, {r3-r10} /* copy to target address [r1] */
242 cmp r0, r2 /* until source end addreee [r2] */
244 #endif /* CONFIG_BOOTBINFUNC */
246 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
247 relocate: /* relocate U-Boot to RAM */
248 adr r0, _start /* r0 <- current position of code */
249 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
250 cmp r0, r1 /* don't reloc during debug */
253 ldr r2, _armboot_start
255 sub r2, r3, r2 /* r2 <- size of armboot */
256 add r2, r0, r2 /* r2 <- source end address */
259 ldmia r0!, {r3-r10} /* copy from source address [r0] */
260 stmia r1!, {r3-r10} /* copy to target address [r1] */
261 cmp r0, r2 /* until source end addreee [r2] */
263 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
265 /* Set up the stack */
267 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
268 sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
269 sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
270 #ifdef CONFIG_USE_IRQ
271 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
273 sub sp, r0, #12 /* leave 3 words for abort-stack */
276 ldr r0, _bss_start /* find start of bss segment */
277 ldr r1, _bss_end /* stop here */
278 mov r2, #0x00000000 /* clear */
280 clbss_l:str r2, [r0] /* clear loop... */
286 /* try doing this stuff after the relocation */
292 * mask all IRQs by setting all bits in the INTMR - default
298 /* FCLK:HCLK:PCLK = 1:2:4 */
299 /* default FCLK is 120 MHz ! */
303 /* END stuff after relocation */
306 ldr pc, _start_armboot
308 _start_armboot: .word start_armboot
312 *************************************************************************
314 * CPU_init_critical registers
316 * setup important registers
317 * setup memory timing
319 *************************************************************************
323 #ifndef CONFIG_SKIP_LOWLEVEL_INIT
326 * flush v4 I/D caches
329 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
330 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
333 * disable MMU stuff and caches
335 mrc p15, 0, r0, c1, c0, 0
336 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
337 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
338 orr r0, r0, #0x00000002 @ set bit 2 (A) Align
339 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
340 mcr p15, 0, r0, c1, c0, 0
343 * before relocating, we have to setup RAM timing
344 * because memory timing is board-dependend, you will
345 * find a lowlevel_init.S in your board directory.
348 #if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) || defined(CONFIG_AT91RM9200DF)
355 #endif /* CONFIG_SKIP_LOWLEVEL_INIT */
358 *************************************************************************
362 *************************************************************************
368 #define S_FRAME_SIZE 72
390 #define MODE_SVC 0x13
394 * use bad_save_user_regs for abort/prefetch/undef/swi ...
395 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
398 .macro bad_save_user_regs
399 sub sp, sp, #S_FRAME_SIZE
400 stmia sp, {r0 - r12} @ Calling r0-r12
401 ldr r2, _armboot_start
402 sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
403 sub r2, r2, #(CFG_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
404 ldmia r2, {r2 - r3} @ get pc, cpsr
405 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC
409 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
413 .macro irq_save_user_regs
414 sub sp, sp, #S_FRAME_SIZE
415 stmia sp, {r0 - r12} @ Calling r0-r12
417 stmdb r8, {sp, lr}^ @ Calling SP, LR
418 str lr, [r8, #0] @ Save calling PC
420 str r6, [r8, #4] @ Save CPSR
421 str r0, [r8, #8] @ Save OLD_R0
425 .macro irq_restore_user_regs
426 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
428 ldr lr, [sp, #S_PC] @ Get PC
429 add sp, sp, #S_FRAME_SIZE
430 subs pc, lr, #4 @ return & move spsr_svc into cpsr
434 ldr r13, _armboot_start @ setup our mode stack
435 sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
436 sub r13, r13, #(CFG_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
438 str lr, [r13] @ save caller lr / spsr
442 mov r13, #MODE_SVC @ prepare SVC-Mode
449 .macro get_irq_stack @ setup IRQ stack
450 ldr sp, IRQ_STACK_START
453 .macro get_fiq_stack @ setup FIQ stack
454 ldr sp, FIQ_STACK_START
461 undefined_instruction:
464 bl do_undefined_instruction
470 bl do_software_interrupt
490 #ifdef CONFIG_USE_IRQ
497 irq_restore_user_regs
502 /* someone ought to write a more effiction fiq_save_user_regs */
505 irq_restore_user_regs