1/* 2 * armboot - Startup Code for XScale 3 * 4 * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> 5 * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> 6 * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> 7 * Copyright (C) 2001 Alex Zuepke <azu@sysgo.de> 8 * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> 9 * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> 10 * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> 11 * 12 * See file CREDITS for list of people who contributed to this 13 * project. 14 * 15 * This program is free software; you can redistribute it and/or 16 * modify it under the terms of the GNU General Public License as 17 * published by the Free Software Foundation; either version 2 of 18 * the License, or (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * GNU General Public License for more details. 24 * 25 * You should have received a copy of the GNU General Public License 26 * along with this program; if not, write to the Free Software 27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 28 * MA 02111-1307 USA 29 */ 30 31#include <config.h> 32#include <version.h> 33#include <asm/arch/pxa-regs.h> 34 35.globl _start 36_start: b reset 37 ldr pc, _undefined_instruction 38 ldr pc, _software_interrupt 39 ldr pc, _prefetch_abort 40 ldr pc, _data_abort 41 ldr pc, _not_used 42 ldr pc, _irq 43 ldr pc, _fiq 44 45_undefined_instruction: .word undefined_instruction 46_software_interrupt: .word software_interrupt 47_prefetch_abort: .word prefetch_abort 48_data_abort: .word data_abort 49_not_used: .word not_used 50_irq: .word irq 51_fiq: .word fiq 52 53 .balignl 16,0xdeadbeef 54 55 56/* 57 * Startup Code (reset vector) 58 * 59 * do important init only if we don't start from RAM! 60 * - relocate armboot to RAM 61 * - setup stack 62 * - jump to second stage 63 */ 64 65_TEXT_BASE: 66 .word TEXT_BASE 67 68.globl _armboot_start 69_armboot_start: 70 .word _start 71 72/* 73 * These are defined in the board-specific linker script. 74 */ 75.globl _bss_start 76_bss_start: 77 .word __bss_start 78 79.globl _bss_end 80_bss_end: 81 .word _end 82 83#ifdef CONFIG_USE_IRQ 84/* IRQ stack memory (calculated at run-time) */ 85.globl IRQ_STACK_START 86IRQ_STACK_START: 87 .word 0x0badc0de 88 89/* IRQ stack memory (calculated at run-time) */ 90.globl FIQ_STACK_START 91FIQ_STACK_START: 92 .word 0x0badc0de 93#endif /* CONFIG_USE_IRQ */ 94 95 96/****************************************************************************/ 97/* */ 98/* the actual reset code */ 99/* */ 100/****************************************************************************/ 101 102reset: 103 mrs r0,cpsr /* set the CPU to SVC32 mode */ 104 bic r0,r0,#0x1f /* (superviser mode, M=10011) */ 105 orr r0,r0,#0x13 106 msr cpsr,r0 107 108 /* 109 * we do sys-critical inits only at reboot, 110 * not when booting from RAM! 111 */ 112#ifndef CONFIG_SKIP_LOWLEVEL_INIT 113 bl cpu_init_crit /* we do sys-critical inits */ 114#endif /* !CONFIG_SKIP_LOWLEVEL_INIT */ 115 116#ifndef CONFIG_SKIP_RELOCATE_UBOOT 117relocate: /* relocate U-Boot to RAM */ 118 adr r0, _start /* r0 <- current position of code */ 119 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 120 cmp r0, r1 /* don't reloc during debug */ 121 beq stack_setup 122 123 ldr r2, _armboot_start 124 ldr r3, _bss_start 125 sub r2, r3, r2 /* r2 <- size of armboot */ 126 add r2, r0, r2 /* r2 <- source end address */ 127 128copy_loop: 129 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 130 stmia r1!, {r3-r10} /* copy to target address [r1] */ 131 cmp r0, r2 /* until source end address [r2] */ 132 ble copy_loop 133#endif /* !CONFIG_SKIP_RELOCATE_UBOOT */ 134 135 /* Set up the stack */ 136stack_setup: 137 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 138 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 139 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 140#ifdef CONFIG_USE_IRQ 141 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 142#endif /* CONFIG_USE_IRQ */ 143 sub sp, r0, #12 /* leave 3 words for abort-stack */ 144 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 145 146clear_bss: 147 ldr r0, _bss_start /* find start of bss segment */ 148 ldr r1, _bss_end /* stop here */ 149 mov r2, #0x00000000 /* clear */ 150 151clbss_l:str r2, [r0] /* clear loop... */ 152 add r0, r0, #4 153 cmp r0, r1 154 ble clbss_l 155 156 ldr pc, _start_armboot 157 158_start_armboot: .word start_armboot 159 160 161/****************************************************************************/ 162/* */ 163/* CPU_init_critical registers */ 164/* */ 165/* - setup important registers */ 166/* - setup memory timing */ 167/* */ 168/****************************************************************************/ 169/* mk@tbd: Fix this! */ 170#undef RCSR 171#undef ICMR 172#undef OSMR3 173#undef OSCR 174#undef OWER 175#undef OIER 176#undef CCCR 177 178/* Interrupt-Controller base address */ 179IC_BASE: .word 0x40d00000 180#define ICMR 0x04 181 182/* Reset-Controller */ 183RST_BASE: .word 0x40f00030 184#define RCSR 0x00 185 186/* Operating System Timer */ 187OSTIMER_BASE: .word 0x40a00000 188#define OSMR3 0x0C 189#define OSCR 0x10 190#define OWER 0x18 191#define OIER 0x1C 192 193/* Clock Manager Registers */ 194#ifdef CONFIG_CPU_MONAHANS 195# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO 196# error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!" 197# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */ 198# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 199# define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1 200# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */ 201#else /* !CONFIG_CPU_MONAHANS */ 202#ifdef CONFIG_SYS_CPUSPEED 203CC_BASE: .word 0x41300000 204#define CCCR 0x00 205cpuspeed: .word CONFIG_SYS_CPUSPEED 206#else /* !CONFIG_SYS_CPUSPEED */ 207#error "You have to define CONFIG_SYS_CPUSPEED!!" 208#endif /* CONFIG_SYS_CPUSPEED */ 209#endif /* CONFIG_CPU_MONAHANS */ 210 211 /* takes care the CP15 update has taken place */ 212 .macro CPWAIT reg 213 mrc p15,0,\reg,c2,c0,0 214 mov \reg,\reg 215 sub pc,pc,#4 216 .endm 217 218cpu_init_crit: 219 220 /* mask all IRQs */ 221#ifndef CONFIG_CPU_MONAHANS 222 ldr r0, IC_BASE 223 mov r1, #0x00 224 str r1, [r0, #ICMR] 225#else /* CONFIG_CPU_MONAHANS */ 226 /* Step 1 - Enable CP6 permission */ 227 mrc p15, 0, r1, c15, c1, 0 @ read CPAR 228 orr r1, r1, #0x40 229 mcr p15, 0, r1, c15, c1, 0 230 CPWAIT r1 231 232 /* Step 2 - Mask ICMR & ICMR2 */ 233 mov r1, #0 234 mcr p6, 0, r1, c1, c0, 0 @ ICMR 235 mcr p6, 0, r1, c7, c0, 0 @ ICMR2 236 237 /* turn off all clocks but the ones we will definitly require */ 238 ldr r1, =CKENA 239 ldr r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC) 240 str r2, [r1] 241 ldr r1, =CKENB 242 ldr r2, =(CKENB_6_IRQ) 243 str r2, [r1] 244#endif /* !CONFIG_CPU_MONAHANS */ 245 246 /* set clock speed */ 247#ifdef CONFIG_CPU_MONAHANS 248 ldr r0, =ACCR 249 ldr r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK)) 250 str r1, [r0] 251#else /* !CONFIG_CPU_MONAHANS */ 252#ifdef CONFIG_SYS_CPUSPEED 253 ldr r0, CC_BASE 254 ldr r1, cpuspeed 255 str r1, [r0, #CCCR] 256 mov r0, #2 257 mcr p14, 0, r0, c6, c0, 0 258 259setspeed_done: 260 261#endif /* CONFIG_SYS_CPUSPEED */ 262#endif /* CONFIG_CPU_MONAHANS */ 263 264 /* 265 * before relocating, we have to setup RAM timing 266 * because memory timing is board-dependend, you will 267 * find a lowlevel_init.S in your board directory. 268 */ 269 mov ip, lr 270 bl lowlevel_init 271 mov lr, ip 272 273 /* Memory interfaces are working. Disable MMU and enable I-cache. */ 274 /* mk: hmm, this is not in the monahans docs, leave it now but 275 * check here if it doesn't work :-) */ 276 277 ldr r0, =0x2001 /* enable access to all coproc. */ 278 mcr p15, 0, r0, c15, c1, 0 279 CPWAIT r0 280 281 mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ 282 CPWAIT r0 283 284 mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */ 285 CPWAIT r0 286 287 mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */ 288 CPWAIT r0 289 290 /* Enable the Icache */ 291/* 292 mrc p15, 0, r0, c1, c0, 0 293 orr r0, r0, #0x1800 294 mcr p15, 0, r0, c1, c0, 0 295 CPWAIT 296*/ 297 mov pc, lr 298 299 300/****************************************************************************/ 301/* */ 302/* Interrupt handling */ 303/* */ 304/****************************************************************************/ 305 306/* IRQ stack frame */ 307 308#define S_FRAME_SIZE 72 309 310#define S_OLD_R0 68 311#define S_PSR 64 312#define S_PC 60 313#define S_LR 56 314#define S_SP 52 315 316#define S_IP 48 317#define S_FP 44 318#define S_R10 40 319#define S_R9 36 320#define S_R8 32 321#define S_R7 28 322#define S_R6 24 323#define S_R5 20 324#define S_R4 16 325#define S_R3 12 326#define S_R2 8 327#define S_R1 4 328#define S_R0 0 329 330#define MODE_SVC 0x13 331 332 /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ 333 334 .macro bad_save_user_regs 335 sub sp, sp, #S_FRAME_SIZE 336 stmia sp, {r0 - r12} /* Calling r0-r12 */ 337 add r8, sp, #S_PC 338 339 ldr r2, _armboot_start 340 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 341 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 342 ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ 343 add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ 344 345 add r5, sp, #S_SP 346 mov r1, lr 347 stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ 348 mov r0, sp 349 .endm 350 351 352 /* use irq_save_user_regs / irq_restore_user_regs for */ 353 /* IRQ/FIQ handling */ 354 355 .macro irq_save_user_regs 356 sub sp, sp, #S_FRAME_SIZE 357 stmia sp, {r0 - r12} /* Calling r0-r12 */ 358 add r8, sp, #S_PC 359 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 360 str lr, [r8, #0] /* Save calling PC */ 361 mrs r6, spsr 362 str r6, [r8, #4] /* Save CPSR */ 363 str r0, [r8, #8] /* Save OLD_R0 */ 364 mov r0, sp 365 .endm 366 367 .macro irq_restore_user_regs 368 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 369 mov r0, r0 370 ldr lr, [sp, #S_PC] @ Get PC 371 add sp, sp, #S_FRAME_SIZE 372 subs pc, lr, #4 @ return & move spsr_svc into cpsr 373 .endm 374 375 .macro get_bad_stack 376 ldr r13, _armboot_start @ setup our mode stack 377 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 378 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 379 380 str lr, [r13] @ save caller lr / spsr 381 mrs lr, spsr 382 str lr, [r13, #4] 383 384 mov r13, #MODE_SVC @ prepare SVC-Mode 385 msr spsr_c, r13 386 mov lr, pc 387 movs pc, lr 388 .endm 389 390 .macro get_irq_stack @ setup IRQ stack 391 ldr sp, IRQ_STACK_START 392 .endm 393 394 .macro get_fiq_stack @ setup FIQ stack 395 ldr sp, FIQ_STACK_START 396 .endm 397 398 399/****************************************************************************/ 400/* */ 401/* exception handlers */ 402/* */ 403/****************************************************************************/ 404 405 .align 5 406undefined_instruction: 407 get_bad_stack 408 bad_save_user_regs 409 bl do_undefined_instruction 410 411 .align 5 412software_interrupt: 413 get_bad_stack 414 bad_save_user_regs 415 bl do_software_interrupt 416 417 .align 5 418prefetch_abort: 419 get_bad_stack 420 bad_save_user_regs 421 bl do_prefetch_abort 422 423 .align 5 424data_abort: 425 get_bad_stack 426 bad_save_user_regs 427 bl do_data_abort 428 429 .align 5 430not_used: 431 get_bad_stack 432 bad_save_user_regs 433 bl do_not_used 434 435#ifdef CONFIG_USE_IRQ 436 437 .align 5 438irq: 439 get_irq_stack 440 irq_save_user_regs 441 bl do_irq 442 irq_restore_user_regs 443 444 .align 5 445fiq: 446 get_fiq_stack 447 irq_save_user_regs /* someone ought to write a more */ 448 bl do_fiq /* effiction fiq_save_user_regs */ 449 irq_restore_user_regs 450 451#else /* !CONFIG_USE_IRQ */ 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 465#endif /* CONFIG_USE_IRQ */ 466 467/****************************************************************************/ 468/* */ 469/* Reset function: the PXA250 doesn't have a reset function, so we have to */ 470/* perform a watchdog timeout for a soft reset. */ 471/* */ 472/****************************************************************************/ 473 474 .align 5 475.globl reset_cpu 476 477 /* FIXME: this code is PXA250 specific. How is this handled on */ 478 /* other XScale processors? */ 479 480reset_cpu: 481 482 /* We set OWE:WME (watchdog enable) and wait until timeout happens */ 483 484 ldr r0, OSTIMER_BASE 485 ldr r1, [r0, #OWER] 486 orr r1, r1, #0x0001 /* bit0: WME */ 487 str r1, [r0, #OWER] 488 489 /* OS timer does only wrap every 1165 seconds, so we have to set */ 490 /* the match register as well. */ 491 492 ldr r1, [r0, #OSCR] /* read OS timer */ 493 add r1, r1, #0x800 /* let OSMR3 match after */ 494 add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */ 495 str r1, [r0, #OSMR3] 496 497reset_endless: 498 499 b reset_endless 500