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