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/* 60 ************************************************************************* 61 * 62 * Startup Code (reset vector) 63 * 64 * do important init only if we don't start from memory! 65 * setup Memory and board specific bits prior to relocation. 66 * relocate armboot to ram 67 * setup stack 68 * 69 ************************************************************************* 70 */ 71 72#ifdef CONFIG_USE_IRQ 73/* IRQ stack memory (calculated at run-time) */ 74.globl IRQ_STACK_START 75IRQ_STACK_START: 76 .word 0x0badc0de 77 78/* IRQ stack memory (calculated at run-time) */ 79.globl FIQ_STACK_START 80FIQ_STACK_START: 81 .word 0x0badc0de 82#endif 83 84/* IRQ stack memory (calculated at run-time) + 8 bytes */ 85.globl IRQ_STACK_START_IN 86IRQ_STACK_START_IN: 87 .word 0x0badc0de 88 89/* 90 * the actual reset code 91 */ 92 93reset: 94 /* 95 * set the cpu to SVC32 mode 96 */ 97 mrs r0,cpsr 98 bic r0,r0,#0x1f 99 orr r0,r0,#0xd3 100 msr cpsr,r0 101 102 /* 103 * we do sys-critical inits only at reboot, 104 * not when booting from ram! 105 */ 106#ifndef CONFIG_SKIP_LOWLEVEL_INIT 107 bl cpu_init_crit 108#endif 109 110 bl _main 111 112/*------------------------------------------------------------------------------*/ 113 114 .globl c_runtime_cpu_setup 115c_runtime_cpu_setup: 116 117 mov pc, lr 118 119/* 120 ************************************************************************* 121 * 122 * CPU_init_critical registers 123 * 124 * setup important registers 125 * setup memory timing 126 * 127 ************************************************************************* 128 */ 129 130 131#ifndef CONFIG_SKIP_LOWLEVEL_INIT 132cpu_init_crit: 133 /* 134 * flush v4 I/D caches 135 */ 136 mov r0, #0 137 mcr p15, 0, r0, c7, c5, 0 /* flush v4 I-cache */ 138 mcr p15, 0, r0, c7, c6, 0 /* flush v4 D-cache */ 139 140 /* 141 * disable MMU stuff and caches 142 */ 143 mrc p15, 0, r0, c1, c0, 0 144 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ 145 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ 146 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ 147 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ 148 mcr p15, 0, r0, c1, c0, 0 149 150 /* 151 * Go setup Memory and board specific bits prior to relocation. 152 */ 153 mov ip, lr /* perserve link reg across call */ 154 bl lowlevel_init /* go setup memory */ 155 mov lr, ip /* restore link */ 156 mov pc, lr /* back to my caller */ 157#endif 158/* 159 ************************************************************************* 160 * 161 * Interrupt handling 162 * 163 ************************************************************************* 164 */ 165 166@ 167@ IRQ stack frame. 168@ 169#define S_FRAME_SIZE 72 170 171#define S_OLD_R0 68 172#define S_PSR 64 173#define S_PC 60 174#define S_LR 56 175#define S_SP 52 176 177#define S_IP 48 178#define S_FP 44 179#define S_R10 40 180#define S_R9 36 181#define S_R8 32 182#define S_R7 28 183#define S_R6 24 184#define S_R5 20 185#define S_R4 16 186#define S_R3 12 187#define S_R2 8 188#define S_R1 4 189#define S_R0 0 190 191#define MODE_SVC 0x13 192#define I_BIT 0x80 193 194/* 195 * use bad_save_user_regs for abort/prefetch/undef/swi ... 196 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 197 */ 198 199 .macro bad_save_user_regs 200 @ carve out a frame on current user stack 201 sub sp, sp, #S_FRAME_SIZE 202 stmia sp, {r0 - r12} @ Save user registers (now in svc mode) r0-r12 203 204 ldr r2, IRQ_STACK_START_IN 205 @ get values for "aborted" pc and cpsr (into parm regs) 206 ldmia r2, {r2 - r3} 207 add r0, sp, #S_FRAME_SIZE @ grab pointer to old stack 208 add r5, sp, #S_SP 209 mov r1, lr 210 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 211 mov r0, sp @ save current stack into r0 (param register) 212 .endm 213 214 .macro irq_save_user_regs 215 sub sp, sp, #S_FRAME_SIZE 216 stmia sp, {r0 - r12} @ Calling r0-r12 217 @ !!!! R8 NEEDS to be saved !!!! a reserved stack spot would be good. 218 add r8, sp, #S_PC 219 stmdb r8, {sp, lr}^ @ Calling SP, LR 220 str lr, [r8, #0] @ Save calling PC 221 mrs r6, spsr 222 str r6, [r8, #4] @ Save CPSR 223 str r0, [r8, #8] @ Save OLD_R0 224 mov r0, sp 225 .endm 226 227 .macro irq_restore_user_regs 228 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 229 mov r0, r0 230 ldr lr, [sp, #S_PC] @ Get PC 231 add sp, sp, #S_FRAME_SIZE 232 subs pc, lr, #4 @ return & move spsr_svc into cpsr 233 .endm 234 235 .macro get_bad_stack 236 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 237 238 str lr, [r13] @ save caller lr in position 0 of saved stack 239 mrs lr, spsr @ get the spsr 240 str lr, [r13, #4] @ save spsr in position 1 of saved stack 241 mov r13, #MODE_SVC @ prepare SVC-Mode 242 @ msr spsr_c, r13 243 msr spsr, r13 @ switch modes, make sure moves will execute 244 mov lr, pc @ capture return pc 245 movs pc, lr @ jump to next instruction & switch modes. 246 .endm 247 248 .macro get_irq_stack @ setup IRQ stack 249 ldr sp, IRQ_STACK_START 250 .endm 251 252 .macro get_fiq_stack @ setup FIQ stack 253 ldr sp, FIQ_STACK_START 254 .endm 255 256/* 257 * exception handlers 258 */ 259 .align 5 260undefined_instruction: 261 get_bad_stack 262 bad_save_user_regs 263 bl do_undefined_instruction 264 265 .align 5 266software_interrupt: 267 get_bad_stack 268 bad_save_user_regs 269 bl do_software_interrupt 270 271 .align 5 272prefetch_abort: 273 get_bad_stack 274 bad_save_user_regs 275 bl do_prefetch_abort 276 277 .align 5 278data_abort: 279 get_bad_stack 280 bad_save_user_regs 281 bl do_data_abort 282 283 .align 5 284not_used: 285 get_bad_stack 286 bad_save_user_regs 287 bl do_not_used 288 289#ifdef CONFIG_USE_IRQ 290 291 .align 5 292irq: 293 get_irq_stack 294 irq_save_user_regs 295 bl do_irq 296 irq_restore_user_regs 297 298 .align 5 299fiq: 300 get_fiq_stack 301 /* someone ought to write a more effiction fiq_save_user_regs */ 302 irq_save_user_regs 303 bl do_fiq 304 irq_restore_user_regs 305 306#else 307 308 .align 5 309irq: 310 get_bad_stack 311 bad_save_user_regs 312 bl do_irq 313 314 .align 5 315fiq: 316 get_bad_stack 317 bad_save_user_regs 318 bl do_fiq 319 320#endif 321