1 /* vi: set ts=8 sw=8 noet: */
3 * u-boot - Startup Code for XScale IXP
5 * Copyright (C) 2003 Kyle Harris <kharris@nexus-tech.net>
7 * Based on startup code example contained in the
8 * Intel IXP4xx Programmer's Guide and past u-boot Start.S
11 * See file CREDITS for list of people who contributed to this
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of
17 * the License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 #include <asm-offsets.h>
33 #include <asm/arch/ixp425.h>
35 #define MMU_Control_M 0x001 /* Enable MMU */
36 #define MMU_Control_A 0x002 /* Enable address alignment faults */
37 #define MMU_Control_C 0x004 /* Enable cache */
38 #define MMU_Control_W 0x008 /* Enable write-buffer */
39 #define MMU_Control_P 0x010 /* Compatability: 32 bit code */
40 #define MMU_Control_D 0x020 /* Compatability: 32 bit data */
41 #define MMU_Control_L 0x040 /* Compatability: */
42 #define MMU_Control_B 0x080 /* Enable Big-Endian */
43 #define MMU_Control_S 0x100 /* Enable system protection */
44 #define MMU_Control_R 0x200 /* Enable ROM protection */
45 #define MMU_Control_I 0x1000 /* Enable Instruction cache */
46 #define MMU_Control_X 0x2000 /* Set interrupt vectors at 0xFFFF0000 */
47 #define MMU_Control_Init (MMU_Control_P|MMU_Control_D|MMU_Control_L)
54 .macro DELAY_FOR cycles, reg0
60 /* wait for coprocessor write complete */
62 mrc p15,0,\reg,c2,c0,0
69 ldr pc, _undefined_instruction
70 ldr pc, _software_interrupt
71 ldr pc, _prefetch_abort
77 _undefined_instruction: .word undefined_instruction
78 _software_interrupt: .word software_interrupt
79 _prefetch_abort: .word prefetch_abort
80 _data_abort: .word data_abort
81 _not_used: .word not_used
85 .balignl 16,0xdeadbeef
89 * Startup Code (reset vector)
91 * do important init only if we don't start from memory!
92 * - relocate armboot to ram
94 * - jump to second stage
99 .word CONFIG_SYS_TEXT_BASE
101 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
102 .globl _armboot_start
108 * These are defined in the board-specific linker script.
118 #ifdef CONFIG_USE_IRQ
119 /* IRQ stack memory (calculated at run-time) */
120 .globl IRQ_STACK_START
124 /* IRQ stack memory (calculated at run-time) */
125 .globl FIQ_STACK_START
130 #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
131 /* IRQ stack memory (calculated at run-time) + 8 bytes */
132 .globl IRQ_STACK_START_IN
136 .globl _datarel_start
138 .word __datarel_start
140 .globl _datarelrolocal_start
141 _datarelrolocal_start:
142 .word __datarelrolocal_start
144 .globl _datarellocal_start
146 .word __datarellocal_start
148 .globl _datarelro_start
150 .word __datarelro_start
161 * the actual reset code
165 /* disable mmu, set big-endian */
167 mcr p15, 0, r0, c1, c0, 0
170 /* invalidate I & D caches & BTB */
171 mcr p15, 0, r0, c7, c7, 0
174 /* invalidate I & Data TLB */
175 mcr p15, 0, r0, c8, c7, 0
178 /* drain write and fill buffers */
179 mcr p15, 0, r0, c7, c10, 4
182 /* disable write buffer coalescing */
183 mrc p15, 0, r0, c1, c0, 1
185 mcr p15, 0, r0, c1, c0, 1
188 /* set EXP CS0 to the optimum timing */
189 ldr r1, =CONFIG_SYS_EXP_CS0
190 ldr r2, =IXP425_EXP_CS0
193 /* make sure flash is visible at 0 */
195 ldr r2, =IXP425_EXP_CFG0
197 orr r1, r1, #0x80000000
200 mov r1, #CONFIG_SYS_SDR_CONFIG
201 ldr r2, =IXP425_SDR_CONFIG
204 /* disable refresh cycles */
206 ldr r3, =IXP425_SDR_REFRESH
209 /* send nop command */
211 ldr r4, =IXP425_SDR_IR
215 /* set SDRAM internal refresh val */
216 ldr r1, =CONFIG_SYS_SDRAM_REFRESH_CNT
220 /* send precharge-all command to close all open banks */
225 /* provide 8 auto-refresh cycles */
233 /* set mode register in sdram */
234 mov r1, #CONFIG_SYS_SDR_MODE_CONFIG
238 /* send normal operation command */
246 add r2, r0, #CONFIG_SYS_MONITOR_LEN
256 /* invalidate I & D caches & BTB */
257 mcr p15, 0, r0, c7, c7, 0
260 /* invalidate I & Data TLB */
261 mcr p15, 0, r0, c8, c7, 0
264 /* drain write and fill buffers */
265 mcr p15, 0, r0, c7, c10, 4
268 /* move flash to 0x50000000 */
269 ldr r2, =IXP425_EXP_CFG0
271 bic r1, r1, #0x80000000
281 /* invalidate I & Data TLB */
282 mcr p15, 0, r0, c8, c7, 0
286 mrc p15, 0, r0, c1, c0, 0
287 orr r0, r0, #MMU_Control_I
288 mcr p15, 0, r0, c1, c0, 0
291 mrs r0,cpsr /* set the cpu to SVC32 mode */
292 bic r0,r0,#0x1f /* (superviser mode, M=10011) */
296 /* Set stackpointer in internal RAM to call board_init_f */
298 ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
302 /*------------------------------------------------------------------------------*/
305 * void relocate_code (addr_sp, gd, addr_moni)
307 * This "function" does not return, instead it continues in RAM
308 * after relocating the monitor code.
313 mov r4, r0 /* save addr_sp */
314 mov r5, r1 /* save addr of gd */
315 mov r6, r2 /* save addr of destination */
316 mov r7, r2 /* save addr of destination */
318 /* Set up the stack */
325 sub r2, r3, r2 /* r2 <- size of armboot */
326 add r2, r0, r2 /* r2 <- source end address */
330 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
332 ldmia r0!, {r9-r10} /* copy from source address [r0] */
333 stmia r6!, {r9-r10} /* copy to target address [r1] */
334 cmp r0, r2 /* until source end address [r2] */
337 #ifndef CONFIG_PRELOADER
338 /* fix got entries */
339 ldr r1, _TEXT_BASE /* Text base */
340 mov r0, r7 /* reloc addr */
341 ldr r2, _got_start /* addr in Flash */
342 ldr r3, _got_end /* addr in Flash */
357 #endif /* #ifndef CONFIG_SKIP_RELOCATE_UBOOT */
360 #ifndef CONFIG_PRELOADER
363 ldr r3, _TEXT_BASE /* Text base */
364 mov r4, r7 /* reloc addr */
369 mov r2, #0x00000000 /* clear */
371 clbss_l:str r2, [r0] /* clear loop... */
381 * We are done. Do not return, instead branch to second part of board
382 * initialization, now running from RAM.
385 ldr r2, _board_init_r
387 add r2, r2, r7 /* position from board_init_r in RAM */
388 /* setup parameters for board_init_r */
389 mov r0, r5 /* gd_t */
390 mov r1, r7 /* dest_addr */
395 _board_init_r: .word board_init_r
397 #else /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
398 /****************************************************************************/
400 /* the actual reset code */
402 /****************************************************************************/
405 /* disable mmu, set big-endian */
407 mcr p15, 0, r0, c1, c0, 0
410 /* invalidate I & D caches & BTB */
411 mcr p15, 0, r0, c7, c7, 0
414 /* invalidate I & Data TLB */
415 mcr p15, 0, r0, c8, c7, 0
418 /* drain write and fill buffers */
419 mcr p15, 0, r0, c7, c10, 4
422 /* disable write buffer coalescing */
423 mrc p15, 0, r0, c1, c0, 1
425 mcr p15, 0, r0, c1, c0, 1
428 /* set EXP CS0 to the optimum timing */
429 ldr r1, =CONFIG_SYS_EXP_CS0
430 ldr r2, =IXP425_EXP_CS0
433 /* make sure flash is visible at 0 */
435 ldr r2, =IXP425_EXP_CFG0
437 orr r1, r1, #0x80000000
440 mov r1, #CONFIG_SYS_SDR_CONFIG
441 ldr r2, =IXP425_SDR_CONFIG
444 /* disable refresh cycles */
446 ldr r3, =IXP425_SDR_REFRESH
449 /* send nop command */
451 ldr r4, =IXP425_SDR_IR
455 /* set SDRAM internal refresh val */
456 ldr r1, =CONFIG_SYS_SDRAM_REFRESH_CNT
460 /* send precharge-all command to close all open banks */
465 /* provide 8 auto-refresh cycles */
473 /* set mode register in sdram */
474 mov r1, #CONFIG_SYS_SDR_MODE_CONFIG
478 /* send normal operation command */
486 add r2, r0, #CONFIG_SYS_MONITOR_LEN
496 /* invalidate I & D caches & BTB */
497 mcr p15, 0, r0, c7, c7, 0
500 /* invalidate I & Data TLB */
501 mcr p15, 0, r0, c8, c7, 0
504 /* drain write and fill buffers */
505 mcr p15, 0, r0, c7, c10, 4
508 /* move flash to 0x50000000 */
509 ldr r2, =IXP425_EXP_CFG0
511 bic r1, r1, #0x80000000
521 /* invalidate I & Data TLB */
522 mcr p15, 0, r0, c8, c7, 0
526 mrc p15, 0, r0, c1, c0, 0
527 orr r0, r0, #MMU_Control_I
528 mcr p15, 0, r0, c1, c0, 0
531 mrs r0,cpsr /* set the cpu to SVC32 mode */
532 bic r0,r0,#0x1f /* (superviser mode, M=10011) */
536 #ifndef CONFIG_SKIP_RELOCATE_UBOOT
537 relocate: /* relocate U-Boot to RAM */
538 adr r0, _start /* r0 <- current position of code */
539 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
540 cmp r0, r1 /* don't reloc during debug */
543 ldr r2, _armboot_start
545 sub r2, r3, r2 /* r2 <- size of armboot */
546 add r2, r0, r2 /* r2 <- source end address */
549 ldmia r0!, {r3-r10} /* copy from source address [r0] */
550 stmia r1!, {r3-r10} /* copy to target address [r1] */
551 cmp r0, r2 /* until source end address [r2] */
553 #endif /* CONFIG_SKIP_RELOCATE_UBOOT */
555 /* Set up the stack */
557 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */
558 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */
559 sub r0, r0, #GENERATED_GBL_DATA_SIZE /* bdinfo */
560 #ifdef CONFIG_USE_IRQ
561 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
563 sub sp, r0, #12 /* leave 3 words for abort-stack */
564 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
567 ldr r0, _bss_start /* find start of bss segment */
568 ldr r1, _bss_end /* stop here */
569 mov r2, #0x00000000 /* clear */
571 clbss_l:str r2, [r0] /* clear loop... */
576 ldr pc, _start_armboot
578 _start_armboot: .word start_armboot
579 #endif /* #if !defined(CONFIG_SYS_ARM_WITHOUT_RELOC) */
582 /****************************************************************************/
584 /* Interrupt handling */
586 /****************************************************************************/
588 /* IRQ stack frame */
590 #define S_FRAME_SIZE 72
612 #define MODE_SVC 0x13
614 /* use bad_save_user_regs for abort/prefetch/undef/swi ... */
616 .macro bad_save_user_regs
617 sub sp, sp, #S_FRAME_SIZE
618 stmia sp, {r0 - r12} /* Calling r0-r12 */
621 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
622 ldr r2, _armboot_start
623 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
624 sub r2, r2, #(GENERATED_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
626 ldr r2, IRQ_STACK_START_IN
628 ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */
629 add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */
633 stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */
638 /* use irq_save_user_regs / irq_restore_user_regs for */
639 /* IRQ/FIQ handling */
641 .macro irq_save_user_regs
642 sub sp, sp, #S_FRAME_SIZE
643 stmia sp, {r0 - r12} /* Calling r0-r12 */
645 stmdb r8, {sp, lr}^ /* Calling SP, LR */
646 str lr, [r8, #0] /* Save calling PC */
648 str r6, [r8, #4] /* Save CPSR */
649 str r0, [r8, #8] /* Save OLD_R0 */
653 .macro irq_restore_user_regs
654 ldmia sp, {r0 - lr}^ @ Calling r0 - lr
656 ldr lr, [sp, #S_PC] @ Get PC
657 add sp, sp, #S_FRAME_SIZE
658 subs pc, lr, #4 @ return & move spsr_svc into cpsr
662 #if defined(CONFIG_SYS_ARM_WITHOUT_RELOC)
663 ldr r13, _armboot_start @ setup our mode stack
664 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN)
665 sub r13, r13, #(GENERATED_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack
667 ldr r13, IRQ_STACK_START_IN @ setup our mode stack
670 str lr, [r13] @ save caller lr / spsr
674 mov r13, #MODE_SVC @ prepare SVC-Mode
680 .macro get_irq_stack @ setup IRQ stack
681 ldr sp, IRQ_STACK_START
684 .macro get_fiq_stack @ setup FIQ stack
685 ldr sp, FIQ_STACK_START
689 /****************************************************************************/
691 /* exception handlers */
693 /****************************************************************************/
696 undefined_instruction:
699 bl do_undefined_instruction
705 bl do_software_interrupt
725 #ifdef CONFIG_USE_IRQ
732 irq_restore_user_regs
737 irq_save_user_regs /* someone ought to write a more */
738 bl do_fiq /* effiction fiq_save_user_regs */
739 irq_restore_user_regs
757 /****************************************************************************/
759 /* Reset function: Use Watchdog to reset */
761 /****************************************************************************/
783 #ifdef CONFIG_USE_IRQ
785 .LC0: .word loops_per_jiffy
796 ldr r2, [r2] @ max = 0x0fffffff
797 mov r0, r0, lsr #11 @ max = 0x00003fff
798 mov r2, r2, lsr #11 @ max = 0x0003ffff
799 mul r0, r2, r0 @ max = 2^32-1
807 #endif /* CONFIG_USE_IRQ */