1/* 2 * armboot - Startup Code for ARM926EJS CPU-core 3 * 4 * Copyright (c) 2003 Texas Instruments 5 * 6 * ----- Adapted for OMAP1610 OMAP730 from ARM925t code ------ 7 * 8 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 9 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 10 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 11 * Copyright (c) 2003 Richard Woodruff <r-woodruff2@ti.com> 12 * Copyright (c) 2003 Kshitij <kshitij@ti.com> 13 * Copyright (c) 2010 Albert Aribaud <albert.u.boot@aribaud.net> 14 * 15 * SPDX-License-Identifier: GPL-2.0+ 16 */ 17 18#include <asm-offsets.h> 19#include <config.h> 20#include <version.h> 21 22/* 23 ************************************************************************* 24 * 25 * Jump vector table as in table 3.1 in [1] 26 * 27 ************************************************************************* 28 */ 29 30 31.globl _start 32_start: 33 b reset 34 ldr pc, _undefined_instruction 35 ldr pc, _software_interrupt 36 ldr pc, _prefetch_abort 37 ldr pc, _data_abort 38 ldr pc, _not_used 39 ldr pc, _irq 40 ldr pc, _fiq 41 42_undefined_instruction: 43 .word undefined_instruction 44_software_interrupt: 45 .word software_interrupt 46_prefetch_abort: 47 .word prefetch_abort 48_data_abort: 49 .word data_abort 50_not_used: 51 .word not_used 52_irq: 53 .word irq 54_fiq: 55 .word fiq 56 57 .balignl 16,0xdeadbeef 58 59_vectors_end: 60 61/* 62 ************************************************************************* 63 * 64 * Startup Code (reset vector) 65 * 66 * do important init only if we don't start from memory! 67 * setup Memory and board specific bits prior to relocation. 68 * relocate armboot to ram 69 * setup stack 70 * 71 ************************************************************************* 72 */ 73 74.globl _TEXT_BASE 75_TEXT_BASE: 76#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE) 77 .word CONFIG_SPL_TEXT_BASE 78#else 79 .word CONFIG_SYS_TEXT_BASE 80#endif 81 82/* 83 * These are defined in the board-specific linker script. 84 * Subtracting _start from them lets the linker put their 85 * relative position in the executable instead of leaving 86 * them null. 87 */ 88.globl _bss_start_ofs 89_bss_start_ofs: 90 .word __bss_start - _start 91 92.globl _bss_end_ofs 93_bss_end_ofs: 94 .word __bss_end - _start 95 96.globl _end_ofs 97_end_ofs: 98 .word _end - _start 99 100#ifdef CONFIG_USE_IRQ 101/* IRQ stack memory (calculated at run-time) */ 102.globl IRQ_STACK_START 103IRQ_STACK_START: 104 .word 0x0badc0de 105 106/* IRQ stack memory (calculated at run-time) */ 107.globl FIQ_STACK_START 108FIQ_STACK_START: 109 .word 0x0badc0de 110#endif 111 112/* IRQ stack memory (calculated at run-time) + 8 bytes */ 113.globl IRQ_STACK_START_IN 114IRQ_STACK_START_IN: 115 .word 0x0badc0de 116 117/* 118 * the actual reset code 119 */ 120 121reset: 122 /* 123 * set the cpu to SVC32 mode 124 */ 125 mrs r0,cpsr 126 bic r0,r0,#0x1f 127 orr r0,r0,#0xd3 128 msr cpsr,r0 129 130 /* 131 * we do sys-critical inits only at reboot, 132 * not when booting from ram! 133 */ 134#ifndef CONFIG_SKIP_LOWLEVEL_INIT 135 bl cpu_init_crit 136#endif 137 138 bl _main 139 140/*------------------------------------------------------------------------------*/ 141 142 .globl c_runtime_cpu_setup 143c_runtime_cpu_setup: 144 145 mov pc, lr 146 147/* 148 ************************************************************************* 149 * 150 * CPU_init_critical registers 151 * 152 * setup important registers 153 * setup memory timing 154 * 155 ************************************************************************* 156 */ 157 158 159#ifndef CONFIG_SKIP_LOWLEVEL_INIT 160cpu_init_crit: 161 /* 162 * flush v4 I/D caches 163 */ 164 mov r0, #0 165 mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ 166 mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ 167 168 /* 169 * disable MMU stuff and caches 170 */ 171 mrc p15, 0, r0, c1, c0, 0 172 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ 173 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ 174 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ 175 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ 176 mcr p15, 0, r0, c1, c0, 0 177 178 /* 179 * Go setup Memory and board specific bits prior to relocation. 180 */ 181 mov ip, lr /* perserve link reg across call */ 182 bl lowlevel_init /* go setup memory */ 183 mov lr, ip /* restore link */ 184 mov pc, lr /* back to my caller */ 185#endif 186/* 187 ************************************************************************* 188 * 189 * Interrupt handling 190 * 191 ************************************************************************* 192 */ 193 194@ 195@ IRQ stack frame. 196@ 197#define S_FRAME_SIZE 72 198 199#define S_OLD_R0 68 200#define S_PSR 64 201#define S_PC 60 202#define S_LR 56 203#define S_SP 52 204 205#define S_IP 48 206#define S_FP 44 207#define S_R10 40 208#define S_R9 36 209#define S_R8 32 210#define S_R7 28 211#define S_R6 24 212#define S_R5 20 213#define S_R4 16 214#define S_R3 12 215#define S_R2 8 216#define S_R1 4 217#define S_R0 0 218 219#define MODE_SVC 0x13 220#define I_BIT 0x80 221 222/* 223 * use bad_save_user_regs for abort/prefetch/undef/swi ... 224 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 225 */ 226 227 .macro bad_save_user_regs 228 @ carve out a frame on current user stack 229 sub sp, sp, #S_FRAME_SIZE 230 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 231 232 ldr r2, IRQ_STACK_START_IN 233 @ get values for "aborted" pc and cpsr (into parm regs) 234 ldmia r2, {r2 - r3} 235 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 236 add r5, sp, #S_SP 237 mov r1, lr 238 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 239 mov r0, sp @ save current stack into r0 (param register) 240 .endm 241 242 .macro irq_save_user_regs 243 sub sp, sp, #S_FRAME_SIZE 244 stmia sp, {r0 - r12} @ Calling r0-r12 245 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 246 add r8, sp, #S_PC 247 stmdb r8, {sp, lr}^ @ Calling SP, LR 248 str lr, [r8, #0] @ Save calling PC 249 mrs r6, spsr 250 str r6, [r8, #4] @ Save CPSR 251 str r0, [r8, #8] @ Save OLD_R0 252 mov r0, sp 253 .endm 254 255 .macro irq_restore_user_regs 256 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 257 mov r0, r0 258 ldr lr, [sp, #S_PC] @ Get PC 259 add sp, sp, #S_FRAME_SIZE 260 subs pc, lr, #4 @ return & move spsr_svc into cpsr 261 .endm 262 263 .macro get_bad_stack 264 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 265 266 str lr, [r13] @ save caller lr in position 0 of saved stack 267 mrs lr, spsr @ get the spsr 268 str lr, [r13, #4] @ save spsr in position 1 of saved stack 269 mov r13, #MODE_SVC @ prepare SVC-Mode 270 @ msr spsr_c, r13 271 msr spsr, r13 @ switch modes, make sure moves will execute 272 mov lr, pc @ capture return pc 273 movs pc, lr @ jump to next instruction & switch modes. 274 .endm 275 276 .macro get_irq_stack @ setup IRQ stack 277 ldr sp, IRQ_STACK_START 278 .endm 279 280 .macro get_fiq_stack @ setup FIQ stack 281 ldr sp, FIQ_STACK_START 282 .endm 283 284/* 285 * exception handlers 286 */ 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 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 350# ifdef CONFIG_INTEGRATOR 351 352 /* Satisfied by general board level routine */ 353 354#else 355 356 .align 5 357.globl reset_cpu 358reset_cpu: 359 360 ldr r1, rstctl1 /* get clkm1 reset ctl */ 361 mov r3, #0x0 362 strh r3, [r1] /* clear it */ 363 mov r3, #0x8 364 strh r3, [r1] /* force dsp+arm reset */ 365_loop_forever: 366 b _loop_forever 367 368rstctl1: 369 .word 0xfffece10 370 371#endif /* #ifdef CONFIG_INTEGRATOR */ 372