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 r0, r0, #12 /* leave 3 words for abort-stack */ 144 bic sp, r0, #7 /* NOTE: stack MUST be aligned to */ 145 /* 8 bytes in case we want to use */ 146 /* 64bit datatypes (eg. VSPRINTF64) */ 147 148clear_bss: 149 ldr r0, _bss_start /* find start of bss segment */ 150 ldr r1, _bss_end /* stop here */ 151 mov r2, #0x00000000 /* clear */ 152 153clbss_l:str r2, [r0] /* clear loop... */ 154 add r0, r0, #4 155 cmp r0, r1 156 ble clbss_l 157 158 ldr pc, _start_armboot 159 160_start_armboot: .word start_armboot 161 162 163/****************************************************************************/ 164/* */ 165/* CPU_init_critical registers */ 166/* */ 167/* - setup important registers */ 168/* - setup memory timing */ 169/* */ 170/****************************************************************************/ 171/* mk@tbd: Fix this! */ 172#undef RCSR 173#undef ICMR 174#undef OSMR3 175#undef OSCR 176#undef OWER 177#undef OIER 178#undef CCCR 179 180/* Interrupt-Controller base address */ 181IC_BASE: .word 0x40d00000 182#define ICMR 0x04 183 184/* Reset-Controller */ 185RST_BASE: .word 0x40f00030 186#define RCSR 0x00 187 188/* Operating System Timer */ 189OSTIMER_BASE: .word 0x40a00000 190#define OSMR3 0x0C 191#define OSCR 0x10 192#define OWER 0x18 193#define OIER 0x1C 194 195/* Clock Manager Registers */ 196#ifdef CONFIG_CPU_MONAHANS 197# ifndef CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO 198# error "You have to define CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO!!" 199# endif /* !CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO */ 200# ifndef CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 201# define CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO 0x1 202# endif /* !CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO */ 203#else /* !CONFIG_CPU_MONAHANS */ 204#ifdef CONFIG_SYS_CPUSPEED 205CC_BASE: .word 0x41300000 206#define CCCR 0x00 207cpuspeed: .word CONFIG_SYS_CPUSPEED 208#else /* !CONFIG_SYS_CPUSPEED */ 209#error "You have to define CONFIG_SYS_CPUSPEED!!" 210#endif /* CONFIG_SYS_CPUSPEED */ 211#endif /* CONFIG_CPU_MONAHANS */ 212 213 /* takes care the CP15 update has taken place */ 214 .macro CPWAIT reg 215 mrc p15,0,\reg,c2,c0,0 216 mov \reg,\reg 217 sub pc,pc,#4 218 .endm 219 220cpu_init_crit: 221 222 /* mask all IRQs */ 223#ifndef CONFIG_CPU_MONAHANS 224 ldr r0, IC_BASE 225 mov r1, #0x00 226 str r1, [r0, #ICMR] 227#else /* CONFIG_CPU_MONAHANS */ 228 /* Step 1 - Enable CP6 permission */ 229 mrc p15, 0, r1, c15, c1, 0 @ read CPAR 230 orr r1, r1, #0x40 231 mcr p15, 0, r1, c15, c1, 0 232 CPWAIT r1 233 234 /* Step 2 - Mask ICMR & ICMR2 */ 235 mov r1, #0 236 mcr p6, 0, r1, c1, c0, 0 @ ICMR 237 mcr p6, 0, r1, c7, c0, 0 @ ICMR2 238 239 /* turn off all clocks but the ones we will definitly require */ 240 ldr r1, =CKENA 241 ldr r2, =(CKENA_22_FFUART | CKENA_10_SRAM | CKENA_9_SMC | CKENA_8_DMC) 242 str r2, [r1] 243 ldr r1, =CKENB 244 ldr r2, =(CKENB_6_IRQ) 245 str r2, [r1] 246#endif /* !CONFIG_CPU_MONAHANS */ 247 248 /* set clock speed */ 249#ifdef CONFIG_CPU_MONAHANS 250 ldr r0, =ACCR 251 ldr r1, =(((CONFIG_SYS_MONAHANS_TURBO_RUN_MODE_RATIO<<8) & ACCR_XN_MASK) | (CONFIG_SYS_MONAHANS_RUN_MODE_OSC_RATIO & ACCR_XL_MASK)) 252 str r1, [r0] 253#else /* !CONFIG_CPU_MONAHANS */ 254#ifdef CONFIG_SYS_CPUSPEED 255 ldr r0, CC_BASE 256 ldr r1, cpuspeed 257 str r1, [r0, #CCCR] 258 mov r0, #2 259 mcr p14, 0, r0, c6, c0, 0 260 261setspeed_done: 262 263#endif /* CONFIG_SYS_CPUSPEED */ 264#endif /* CONFIG_CPU_MONAHANS */ 265 266 /* 267 * before relocating, we have to setup RAM timing 268 * because memory timing is board-dependend, you will 269 * find a lowlevel_init.S in your board directory. 270 */ 271 mov ip, lr 272 bl lowlevel_init 273 mov lr, ip 274 275 /* Memory interfaces are working. Disable MMU and enable I-cache. */ 276 /* mk: hmm, this is not in the monahans docs, leave it now but 277 * check here if it doesn't work :-) */ 278 279 ldr r0, =0x2001 /* enable access to all coproc. */ 280 mcr p15, 0, r0, c15, c1, 0 281 CPWAIT r0 282 283 mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ 284 CPWAIT r0 285 286 mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */ 287 CPWAIT r0 288 289 mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */ 290 CPWAIT r0 291 292 /* Enable the Icache */ 293/* 294 mrc p15, 0, r0, c1, c0, 0 295 orr r0, r0, #0x1800 296 mcr p15, 0, r0, c1, c0, 0 297 CPWAIT 298*/ 299 mov pc, lr 300 301 302/****************************************************************************/ 303/* */ 304/* Interrupt handling */ 305/* */ 306/****************************************************************************/ 307 308/* IRQ stack frame */ 309 310#define S_FRAME_SIZE 72 311 312#define S_OLD_R0 68 313#define S_PSR 64 314#define S_PC 60 315#define S_LR 56 316#define S_SP 52 317 318#define S_IP 48 319#define S_FP 44 320#define S_R10 40 321#define S_R9 36 322#define S_R8 32 323#define S_R7 28 324#define S_R6 24 325#define S_R5 20 326#define S_R4 16 327#define S_R3 12 328#define S_R2 8 329#define S_R1 4 330#define S_R0 0 331 332#define MODE_SVC 0x13 333 334 /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ 335 336 .macro bad_save_user_regs 337 sub sp, sp, #S_FRAME_SIZE 338 stmia sp, {r0 - r12} /* Calling r0-r12 */ 339 add r8, sp, #S_PC 340 341 ldr r2, _armboot_start 342 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 343 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 344 ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ 345 add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ 346 347 add r5, sp, #S_SP 348 mov r1, lr 349 stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ 350 mov r0, sp 351 .endm 352 353 354 /* use irq_save_user_regs / irq_restore_user_regs for */ 355 /* IRQ/FIQ handling */ 356 357 .macro irq_save_user_regs 358 sub sp, sp, #S_FRAME_SIZE 359 stmia sp, {r0 - r12} /* Calling r0-r12 */ 360 add r8, sp, #S_PC 361 stmdb r8, {sp, lr}^ /* Calling SP, LR */ 362 str lr, [r8, #0] /* Save calling PC */ 363 mrs r6, spsr 364 str r6, [r8, #4] /* Save CPSR */ 365 str r0, [r8, #8] /* Save OLD_R0 */ 366 mov r0, sp 367 .endm 368 369 .macro irq_restore_user_regs 370 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 371 mov r0, r0 372 ldr lr, [sp, #S_PC] @ Get PC 373 add sp, sp, #S_FRAME_SIZE 374 subs pc, lr, #4 @ return & move spsr_svc into cpsr 375 .endm 376 377 .macro get_bad_stack 378 ldr r13, _armboot_start @ setup our mode stack 379 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 380 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 381 382 str lr, [r13] @ save caller lr / spsr 383 mrs lr, spsr 384 str lr, [r13, #4] 385 386 mov r13, #MODE_SVC @ prepare SVC-Mode 387 msr spsr_c, r13 388 mov lr, pc 389 movs pc, lr 390 .endm 391 392 .macro get_irq_stack @ setup IRQ stack 393 ldr sp, IRQ_STACK_START 394 .endm 395 396 .macro get_fiq_stack @ setup FIQ stack 397 ldr sp, FIQ_STACK_START 398 .endm 399 400 401/****************************************************************************/ 402/* */ 403/* exception handlers */ 404/* */ 405/****************************************************************************/ 406 407 .align 5 408undefined_instruction: 409 get_bad_stack 410 bad_save_user_regs 411 bl do_undefined_instruction 412 413 .align 5 414software_interrupt: 415 get_bad_stack 416 bad_save_user_regs 417 bl do_software_interrupt 418 419 .align 5 420prefetch_abort: 421 get_bad_stack 422 bad_save_user_regs 423 bl do_prefetch_abort 424 425 .align 5 426data_abort: 427 get_bad_stack 428 bad_save_user_regs 429 bl do_data_abort 430 431 .align 5 432not_used: 433 get_bad_stack 434 bad_save_user_regs 435 bl do_not_used 436 437#ifdef CONFIG_USE_IRQ 438 439 .align 5 440irq: 441 get_irq_stack 442 irq_save_user_regs 443 bl do_irq 444 irq_restore_user_regs 445 446 .align 5 447fiq: 448 get_fiq_stack 449 irq_save_user_regs /* someone ought to write a more */ 450 bl do_fiq /* effiction fiq_save_user_regs */ 451 irq_restore_user_regs 452 453#else /* !CONFIG_USE_IRQ */ 454 455 .align 5 456irq: 457 get_bad_stack 458 bad_save_user_regs 459 bl do_irq 460 461 .align 5 462fiq: 463 get_bad_stack 464 bad_save_user_regs 465 bl do_fiq 466 467#endif /* CONFIG_USE_IRQ */ 468 469/****************************************************************************/ 470/* */ 471/* Reset function: the PXA250 doesn't have a reset function, so we have to */ 472/* perform a watchdog timeout for a soft reset. */ 473/* */ 474/****************************************************************************/ 475 476 .align 5 477.globl reset_cpu 478 479 /* FIXME: this code is PXA250 specific. How is this handled on */ 480 /* other XScale processors? */ 481 482reset_cpu: 483 484 /* We set OWE:WME (watchdog enable) and wait until timeout happens */ 485 486 ldr r0, OSTIMER_BASE 487 ldr r1, [r0, #OWER] 488 orr r1, r1, #0x0001 /* bit0: WME */ 489 str r1, [r0, #OWER] 490 491 /* OS timer does only wrap every 1165 seconds, so we have to set */ 492 /* the match register as well. */ 493 494 ldr r1, [r0, #OSCR] /* read OS timer */ 495 add r1, r1, #0x800 /* let OSMR3 match after */ 496 add r1, r1, #0x800 /* 4096*(1/3.6864MHz)=1ms */ 497 str r1, [r0, #OSMR3] 498 499reset_endless: 500 501 b reset_endless 502