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