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