1/* 2 * armboot - Startup Code for ARM920 CPU-core 3 * 4 * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> 5 * Copyright (c) 2002 Alex Züpke <azu@sysgo.de> 6 * Copyright (c) 2002 Gary Jennejohn <garyj@denx.de> 7 * 8 * SPDX-License-Identifier: GPL-2.0+ 9 */ 10 11#include <asm-offsets.h> 12#include <common.h> 13#include <config.h> 14 15/* 16 ************************************************************************* 17 * 18 * Jump vector table as in table 3.1 in [1] 19 * 20 ************************************************************************* 21 */ 22 23 24.globl _start 25_start: b start_code 26 ldr pc, _undefined_instruction 27 ldr pc, _software_interrupt 28 ldr pc, _prefetch_abort 29 ldr pc, _data_abort 30 ldr pc, _not_used 31 ldr pc, _irq 32 ldr pc, _fiq 33 34_undefined_instruction: .word undefined_instruction 35_software_interrupt: .word software_interrupt 36_prefetch_abort: .word prefetch_abort 37_data_abort: .word data_abort 38_not_used: .word not_used 39_irq: .word irq 40_fiq: .word fiq 41 42 .balignl 16,0xdeadbeef 43 44 45/* 46 ************************************************************************* 47 * 48 * Startup Code (called from the ARM reset exception vector) 49 * 50 * do important init only if we don't start from memory! 51 * relocate armboot to ram 52 * setup stack 53 * jump to second stage 54 * 55 ************************************************************************* 56 */ 57 58.globl _TEXT_BASE 59_TEXT_BASE: 60#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_TEXT_BASE) 61 .word CONFIG_SPL_TEXT_BASE 62#else 63 .word CONFIG_SYS_TEXT_BASE 64#endif 65 66/* 67 * These are defined in the board-specific linker script. 68 * Subtracting _start from them lets the linker put their 69 * relative position in the executable instead of leaving 70 * them null. 71 */ 72.globl _bss_start_ofs 73_bss_start_ofs: 74 .word __bss_start - _start 75 76.globl _bss_end_ofs 77_bss_end_ofs: 78 .word __bss_end - _start 79 80.globl _end_ofs 81_end_ofs: 82 .word _end - _start 83 84#ifdef CONFIG_USE_IRQ 85/* IRQ stack memory (calculated at run-time) */ 86.globl IRQ_STACK_START 87IRQ_STACK_START: 88 .word 0x0badc0de 89 90/* IRQ stack memory (calculated at run-time) */ 91.globl FIQ_STACK_START 92FIQ_STACK_START: 93 .word 0x0badc0de 94#endif 95 96/* IRQ stack memory (calculated at run-time) + 8 bytes */ 97.globl IRQ_STACK_START_IN 98IRQ_STACK_START_IN: 99 .word 0x0badc0de 100 101/* 102 * the actual start code 103 */ 104 105start_code: 106 /* 107 * set the cpu to SVC32 mode 108 */ 109 mrs r0, cpsr 110 bic r0, r0, #0x1f 111 orr r0, r0, #0xd3 112 msr cpsr, r0 113 114#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) 115 /* 116 * relocate exception table 117 */ 118 ldr r0, =_start 119 ldr r1, =0x0 120 mov r2, #16 121copyex: 122 subs r2, r2, #1 123 ldr r3, [r0], #4 124 str r3, [r1], #4 125 bne copyex 126#endif 127 128#ifdef CONFIG_S3C24X0 129 /* turn off the watchdog */ 130 131# if defined(CONFIG_S3C2400) 132# define pWTCON 0x15300000 133# define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ 134# define CLKDIVN 0x14800014 /* clock divisor register */ 135#else 136# define pWTCON 0x53000000 137# define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ 138# define INTSUBMSK 0x4A00001C 139# define CLKDIVN 0x4C000014 /* clock divisor register */ 140# endif 141 142 ldr r0, =pWTCON 143 mov r1, #0x0 144 str r1, [r0] 145 146 /* 147 * mask all IRQs by setting all bits in the INTMR - default 148 */ 149 mov r1, #0xffffffff 150 ldr r0, =INTMSK 151 str r1, [r0] 152# if defined(CONFIG_S3C2410) 153 ldr r1, =0x3ff 154 ldr r0, =INTSUBMSK 155 str r1, [r0] 156# endif 157 158 /* FCLK:HCLK:PCLK = 1:2:4 */ 159 /* default FCLK is 120 MHz ! */ 160 ldr r0, =CLKDIVN 161 mov r1, #3 162 str r1, [r0] 163#endif /* CONFIG_S3C24X0 */ 164 165 /* 166 * we do sys-critical inits only at reboot, 167 * not when booting from ram! 168 */ 169#ifndef CONFIG_SKIP_LOWLEVEL_INIT 170 bl cpu_init_crit 171#endif 172 173 bl _main 174 175/*------------------------------------------------------------------------------*/ 176 177 .globl c_runtime_cpu_setup 178c_runtime_cpu_setup: 179 180 mov pc, lr 181 182/* 183 ************************************************************************* 184 * 185 * CPU_init_critical registers 186 * 187 * setup important registers 188 * setup memory timing 189 * 190 ************************************************************************* 191 */ 192 193 194#ifndef CONFIG_SKIP_LOWLEVEL_INIT 195cpu_init_crit: 196 /* 197 * flush v4 I/D caches 198 */ 199 mov r0, #0 200 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 201 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 202 203 /* 204 * disable MMU stuff and caches 205 */ 206 mrc p15, 0, r0, c1, c0, 0 207 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 208 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 209 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 210 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 211 mcr p15, 0, r0, c1, c0, 0 212 213 /* 214 * before relocating, we have to setup RAM timing 215 * because memory timing is board-dependend, you will 216 * find a lowlevel_init.S in your board directory. 217 */ 218 mov ip, lr 219 220 bl lowlevel_init 221 222 mov lr, ip 223 mov pc, lr 224#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 225 226/* 227 ************************************************************************* 228 * 229 * Interrupt handling 230 * 231 ************************************************************************* 232 */ 233 234@ 235@ IRQ stack frame. 236@ 237#define S_FRAME_SIZE 72 238 239#define S_OLD_R0 68 240#define S_PSR 64 241#define S_PC 60 242#define S_LR 56 243#define S_SP 52 244 245#define S_IP 48 246#define S_FP 44 247#define S_R10 40 248#define S_R9 36 249#define S_R8 32 250#define S_R7 28 251#define S_R6 24 252#define S_R5 20 253#define S_R4 16 254#define S_R3 12 255#define S_R2 8 256#define S_R1 4 257#define S_R0 0 258 259#define MODE_SVC 0x13 260#define I_BIT 0x80 261 262/* 263 * use bad_save_user_regs for abort/prefetch/undef/swi ... 264 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 265 */ 266 267 .macro bad_save_user_regs 268 sub sp, sp, #S_FRAME_SIZE 269 stmia sp, {r0 - r12} @ Calling r0-r12 270 ldr r2, IRQ_STACK_START_IN 271 ldmia r2, {r2 - r3} @ get pc, cpsr 272 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 273 274 add r5, sp, #S_SP 275 mov r1, lr 276 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 277 mov r0, sp 278 .endm 279 280 .macro irq_save_user_regs 281 sub sp, sp, #S_FRAME_SIZE 282 stmia sp, {r0 - r12} @ Calling r0-r12 283 add r7, sp, #S_PC 284 stmdb r7, {sp, lr}^ @ Calling SP, LR 285 str lr, [r7, #0] @ Save calling PC 286 mrs r6, spsr 287 str r6, [r7, #4] @ Save CPSR 288 str r0, [r7, #8] @ Save OLD_R0 289 mov r0, sp 290 .endm 291 292 .macro irq_restore_user_regs 293 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 294 mov r0, r0 295 ldr lr, [sp, #S_PC] @ Get PC 296 add sp, sp, #S_FRAME_SIZE 297 /* return & move spsr_svc into cpsr */ 298 subs pc, lr, #4 299 .endm 300 301 .macro get_bad_stack 302 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 303 304 str lr, [r13] @ save caller lr / spsr 305 mrs lr, spsr 306 str lr, [r13, #4] 307 308 mov r13, #MODE_SVC @ prepare SVC-Mode 309 @ msr spsr_c, r13 310 msr spsr, r13 311 mov lr, pc 312 movs pc, lr 313 .endm 314 315 .macro get_irq_stack @ setup IRQ stack 316 ldr sp, IRQ_STACK_START 317 .endm 318 319 .macro get_fiq_stack @ setup FIQ stack 320 ldr sp, FIQ_STACK_START 321 .endm 322 323/* 324 * exception handlers 325 */ 326 .align 5 327undefined_instruction: 328 get_bad_stack 329 bad_save_user_regs 330 bl do_undefined_instruction 331 332 .align 5 333software_interrupt: 334 get_bad_stack 335 bad_save_user_regs 336 bl do_software_interrupt 337 338 .align 5 339prefetch_abort: 340 get_bad_stack 341 bad_save_user_regs 342 bl do_prefetch_abort 343 344 .align 5 345data_abort: 346 get_bad_stack 347 bad_save_user_regs 348 bl do_data_abort 349 350 .align 5 351not_used: 352 get_bad_stack 353 bad_save_user_regs 354 bl do_not_used 355 356#ifdef CONFIG_USE_IRQ 357 358 .align 5 359irq: 360 get_irq_stack 361 irq_save_user_regs 362 bl do_irq 363 irq_restore_user_regs 364 365 .align 5 366fiq: 367 get_fiq_stack 368 /* someone ought to write a more effiction fiq_save_user_regs */ 369 irq_save_user_regs 370 bl do_fiq 371 irq_restore_user_regs 372 373#else 374 375 .align 5 376irq: 377 get_bad_stack 378 bad_save_user_regs 379 bl do_irq 380 381 .align 5 382fiq: 383 get_bad_stack 384 bad_save_user_regs 385 bl do_fiq 386 387#endif 388