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