1/* 2 * armboot - Startup Code for XScale CPU-core 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) 2001 Marius Groger <mag@sysgo.de> 9 * Copyright (C) 2002 Alex Zupke <azu@sysgo.de> 10 * Copyright (C) 2002 Gary Jennejohn <garyj@denx.de> 11 * Copyright (C) 2002 Kyle Harris <kharris@nexus-tech.net> 12 * Copyright (C) 2003 Kai-Uwe Bloem <kai-uwe.bloem@auerswald.de> 13 * Copyright (C) 2003 Kshitij <kshitij@ti.com> 14 * Copyright (C) 2003 Richard Woodruff <r-woodruff2@ti.com> 15 * Copyright (C) 2003 Robert Schwebel <r.schwebel@pengutronix.de> 16 * Copyright (C) 2004 Texas Instruments <r-woodruff2@ti.com> 17 * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com> 18 * 19 * SPDX-License-Identifier: GPL-2.0+ 20 */ 21 22#include <asm-offsets.h> 23#include <config.h> 24#include <version.h> 25 26.globl _start 27_start: b reset 28#ifdef CONFIG_SPL_BUILD 29 ldr pc, _hang 30 ldr pc, _hang 31 ldr pc, _hang 32 ldr pc, _hang 33 ldr pc, _hang 34 ldr pc, _hang 35 ldr pc, _hang 36 37_hang: 38 .word do_hang 39 .word 0x12345678 40 .word 0x12345678 41 .word 0x12345678 42 .word 0x12345678 43 .word 0x12345678 44 .word 0x12345678 45 .word 0x12345678 /* now 16*4=64 */ 46#else 47 ldr pc, _undefined_instruction 48 ldr pc, _software_interrupt 49 ldr pc, _prefetch_abort 50 ldr pc, _data_abort 51 ldr pc, _not_used 52 ldr pc, _irq 53 ldr pc, _fiq 54 55_undefined_instruction: .word undefined_instruction 56_software_interrupt: .word software_interrupt 57_prefetch_abort: .word prefetch_abort 58_data_abort: .word data_abort 59_not_used: .word not_used 60_irq: .word irq 61_fiq: .word fiq 62_pad: .word 0x12345678 /* now 16*4=64 */ 63#endif /* CONFIG_SPL_BUILD */ 64 65 .balignl 16,0xdeadbeef 66/* 67 ************************************************************************* 68 * 69 * Startup Code (reset vector) 70 * 71 * do important init only if we don't start from memory! 72 * setup Memory and board specific bits prior to relocation. 73 * relocate armboot to ram 74 * setup stack 75 * 76 ************************************************************************* 77 */ 78 79#ifdef CONFIG_USE_IRQ 80/* IRQ stack memory (calculated at run-time) */ 81.globl IRQ_STACK_START 82IRQ_STACK_START: 83 .word 0x0badc0de 84 85/* IRQ stack memory (calculated at run-time) */ 86.globl FIQ_STACK_START 87FIQ_STACK_START: 88 .word 0x0badc0de 89#endif 90 91/* IRQ stack memory (calculated at run-time) + 8 bytes */ 92.globl IRQ_STACK_START_IN 93IRQ_STACK_START_IN: 94 .word 0x0badc0de 95 96/* 97 * the actual reset code 98 */ 99 100reset: 101 /* 102 * set the cpu to SVC32 mode 103 */ 104 mrs r0,cpsr 105 bic r0,r0,#0x1f 106 orr r0,r0,#0xd3 107 msr cpsr,r0 108 109#ifndef CONFIG_SKIP_LOWLEVEL_INIT 110 bl cpu_init_crit 111#endif 112 113#ifdef CONFIG_CPU_PXA25X 114 bl lock_cache_for_stack 115#endif 116 117 bl _main 118 119/*------------------------------------------------------------------------------*/ 120 121 .globl c_runtime_cpu_setup 122c_runtime_cpu_setup: 123 124#ifdef CONFIG_CPU_PXA25X 125 /* 126 * Unlock (actually, disable) the cache now that board_init_f 127 * is done. We could do this earlier but we would need to add 128 * a new C runtime hook, whereas c_runtime_cpu_setup already 129 * exists. 130 * As this routine is just a call to cpu_init_crit, let us 131 * tail-optimize and do a simple branch here. 132 */ 133 b cpu_init_crit 134#else 135 bx lr 136#endif 137 138/* 139 ************************************************************************* 140 * 141 * CPU_init_critical registers 142 * 143 * setup important registers 144 * setup memory timing 145 * 146 ************************************************************************* 147 */ 148#if !defined(CONFIG_SKIP_LOWLEVEL_INIT) || defined(CONFIG_CPU_PXA25X) 149cpu_init_crit: 150 /* 151 * flush v4 I/D caches 152 */ 153 mov r0, #0 154 mcr p15, 0, r0, c7, c7, 0 /* Invalidate I+D+BTB caches */ 155 mcr p15, 0, r0, c8, c7, 0 /* Invalidate Unified TLB */ 156 157 /* 158 * disable MMU stuff and caches 159 */ 160 mrc p15, 0, r0, c1, c0, 0 161 bic r0, r0, #0x00003300 @ clear bits 13:12, 9:8 (--VI --RS) 162 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 163 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 164 mcr p15, 0, r0, c1, c0, 0 165 166 mov pc, lr /* back to my caller */ 167#endif /* !CONFIG_SKIP_LOWLEVEL_INIT || CONFIG_CPU_PXA25X */ 168 169#ifndef CONFIG_SPL_BUILD 170/* 171 ************************************************************************* 172 * 173 * Interrupt handling 174 * 175 ************************************************************************* 176 */ 177@ 178@ IRQ stack frame. 179@ 180#define S_FRAME_SIZE 72 181 182#define S_OLD_R0 68 183#define S_PSR 64 184#define S_PC 60 185#define S_LR 56 186#define S_SP 52 187 188#define S_IP 48 189#define S_FP 44 190#define S_R10 40 191#define S_R9 36 192#define S_R8 32 193#define S_R7 28 194#define S_R6 24 195#define S_R5 20 196#define S_R4 16 197#define S_R3 12 198#define S_R2 8 199#define S_R1 4 200#define S_R0 0 201 202#define MODE_SVC 0x13 203#define I_BIT 0x80 204 205/* 206 * use bad_save_user_regs for abort/prefetch/undef/swi ... 207 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 208 */ 209 210 .macro bad_save_user_regs 211 sub sp, sp, #S_FRAME_SIZE @ carve out a frame on current user stack 212 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 213 214 ldr r2, IRQ_STACK_START_IN @ set base 2 words into abort stack 215 ldmia r2, {r2 - r3} @ get values for "aborted" pc and cpsr (into parm regs) 216 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 217 218 add r5, sp, #S_SP 219 mov r1, lr 220 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 221 mov r0, sp @ save current stack into r0 (param register) 222 .endm 223 224 .macro irq_save_user_regs 225 sub sp, sp, #S_FRAME_SIZE 226 stmia sp, {r0 - r12} @ Calling r0-r12 227 add r8, sp, #S_PC @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 228 stmdb r8, {sp, lr}^ @ Calling SP, LR 229 str lr, [r8, #0] @ Save calling PC 230 mrs r6, spsr 231 str r6, [r8, #4] @ Save CPSR 232 str r0, [r8, #8] @ Save OLD_R0 233 mov r0, sp 234 .endm 235 236 .macro irq_restore_user_regs 237 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 238 mov r0, r0 239 ldr lr, [sp, #S_PC] @ Get PC 240 add sp, sp, #S_FRAME_SIZE 241 subs pc, lr, #4 @ return & move spsr_svc into cpsr 242 .endm 243 244 .macro get_bad_stack 245 ldr r13, IRQ_STACK_START_IN @ setup our mode stack (enter in banked mode) 246 247 str lr, [r13] @ save caller lr in position 0 of saved stack 248 mrs lr, spsr @ get the spsr 249 str lr, [r13, #4] @ save spsr in position 1 of saved stack 250 251 mov r13, #MODE_SVC @ prepare SVC-Mode 252 @ msr spsr_c, r13 253 msr spsr, r13 @ switch modes, make sure moves will execute 254 mov lr, pc @ capture return pc 255 movs pc, lr @ jump to next instruction & switch modes. 256 .endm 257 258 .macro get_bad_stack_swi 259 sub r13, r13, #4 @ space on current stack for scratch reg. 260 str r0, [r13] @ save R0's value. 261 ldr r0, IRQ_STACK_START_IN @ get data regions start 262 str lr, [r0] @ save caller lr in position 0 of saved stack 263 mrs lr, spsr @ get the spsr 264 str lr, [r0, #4] @ save spsr in position 1 of saved stack 265 ldr lr, [r0] @ restore lr 266 ldr r0, [r13] @ restore r0 267 add r13, r13, #4 @ pop stack entry 268 .endm 269 270 .macro get_irq_stack @ setup IRQ stack 271 ldr sp, IRQ_STACK_START 272 .endm 273 274 .macro get_fiq_stack @ setup FIQ stack 275 ldr sp, FIQ_STACK_START 276 .endm 277#endif /* CONFIG_SPL_BUILD */ 278 279/* 280 * exception handlers 281 */ 282#ifdef CONFIG_SPL_BUILD 283 .align 5 284do_hang: 285 bl hang /* hang and never return */ 286#else /* !CONFIG_SPL_BUILD */ 287 .align 5 288undefined_instruction: 289 get_bad_stack 290 bad_save_user_regs 291 bl do_undefined_instruction 292 293 .align 5 294software_interrupt: 295 get_bad_stack_swi 296 bad_save_user_regs 297 bl do_software_interrupt 298 299 .align 5 300prefetch_abort: 301 get_bad_stack 302 bad_save_user_regs 303 bl do_prefetch_abort 304 305 .align 5 306data_abort: 307 get_bad_stack 308 bad_save_user_regs 309 bl do_data_abort 310 311 .align 5 312not_used: 313 get_bad_stack 314 bad_save_user_regs 315 bl do_not_used 316 317#ifdef CONFIG_USE_IRQ 318 319 .align 5 320irq: 321 get_irq_stack 322 irq_save_user_regs 323 bl do_irq 324 irq_restore_user_regs 325 326 .align 5 327fiq: 328 get_fiq_stack 329 /* someone ought to write a more effiction fiq_save_user_regs */ 330 irq_save_user_regs 331 bl do_fiq 332 irq_restore_user_regs 333 334#else 335 336 .align 5 337irq: 338 get_bad_stack 339 bad_save_user_regs 340 bl do_irq 341 342 .align 5 343fiq: 344 get_bad_stack 345 bad_save_user_regs 346 bl do_fiq 347 348#endif 349 .align 5 350#endif /* CONFIG_SPL_BUILD */ 351 352 353/* 354 * Enable MMU to use DCache as DRAM. 355 * 356 * This is useful on PXA25x and PXA26x in early bootstages, where there is no 357 * other possible memory available to hold stack. 358 */ 359#ifdef CONFIG_CPU_PXA25X 360.macro CPWAIT reg 361 mrc p15, 0, \reg, c2, c0, 0 362 mov \reg, \reg 363 sub pc, pc, #4 364.endm 365lock_cache_for_stack: 366 /* Domain access -- enable for all CPs */ 367 ldr r0, =0x0000ffff 368 mcr p15, 0, r0, c3, c0, 0 369 370 /* Point TTBR to MMU table */ 371 ldr r0, =mmutable 372 mcr p15, 0, r0, c2, c0, 0 373 374 /* Kick in MMU, ICache, DCache, BTB */ 375 mrc p15, 0, r0, c1, c0, 0 376 bic r0, #0x1b00 377 bic r0, #0x0087 378 orr r0, #0x1800 379 orr r0, #0x0005 380 mcr p15, 0, r0, c1, c0, 0 381 CPWAIT r0 382 383 /* Unlock Icache, Dcache */ 384 mcr p15, 0, r0, c9, c1, 1 385 mcr p15, 0, r0, c9, c2, 1 386 387 /* Flush Icache, Dcache, BTB */ 388 mcr p15, 0, r0, c7, c7, 0 389 390 /* Unlock I-TLB, D-TLB */ 391 mcr p15, 0, r0, c10, c4, 1 392 mcr p15, 0, r0, c10, c8, 1 393 394 /* Flush TLB */ 395 mcr p15, 0, r0, c8, c7, 0 396 397 /* Allocate 4096 bytes of Dcache as RAM */ 398 399 /* Drain pending loads and stores */ 400 mcr p15, 0, r0, c7, c10, 4 401 402 mov r4, #0x00 403 mov r5, #0x00 404 mov r2, #0x01 405 mcr p15, 0, r0, c9, c2, 0 406 CPWAIT r0 407 408 /* 128 lines reserved (128 x 32bytes = 4096 bytes total) */ 409 mov r0, #128 410 ldr r1, =0xfffff000 411 412alloc: 413 mcr p15, 0, r1, c7, c2, 5 414 /* Drain pending loads and stores */ 415 mcr p15, 0, r0, c7, c10, 4 416 strd r4, [r1], #8 417 strd r4, [r1], #8 418 strd r4, [r1], #8 419 strd r4, [r1], #8 420 subs r0, #0x01 421 bne alloc 422 /* Drain pending loads and stores */ 423 mcr p15, 0, r0, c7, c10, 4 424 mov r2, #0x00 425 mcr p15, 0, r2, c9, c2, 0 426 CPWAIT r0 427 428 mov pc, lr 429 430.section .mmutable, "a" 431mmutable: 432 .align 14 433 /* 0x00000000 - 0xffe00000 : 1:1, uncached mapping */ 434 .set __base, 0 435 .rept 0xfff 436 .word (__base << 20) | 0xc12 437 .set __base, __base + 1 438 .endr 439 440 /* 0xfff00000 : 1:1, cached mapping */ 441 .word (0xfff << 20) | 0x1c1e 442#endif /* CONFIG_CPU_PXA25X */ 443