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#ifdef CONFIG_USE_IRQ 59/* IRQ stack memory (calculated at run-time) */ 60.globl IRQ_STACK_START 61IRQ_STACK_START: 62 .word 0x0badc0de 63 64/* IRQ stack memory (calculated at run-time) */ 65.globl FIQ_STACK_START 66FIQ_STACK_START: 67 .word 0x0badc0de 68#endif 69 70/* IRQ stack memory (calculated at run-time) + 8 bytes */ 71.globl IRQ_STACK_START_IN 72IRQ_STACK_START_IN: 73 .word 0x0badc0de 74 75/* 76 * the actual start code 77 */ 78 79start_code: 80 /* 81 * set the cpu to SVC32 mode 82 */ 83 mrs r0, cpsr 84 bic r0, r0, #0x1f 85 orr r0, r0, #0xd3 86 msr cpsr, r0 87 88#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK) 89 /* 90 * relocate exception table 91 */ 92 ldr r0, =_start 93 ldr r1, =0x0 94 mov r2, #16 95copyex: 96 subs r2, r2, #1 97 ldr r3, [r0], #4 98 str r3, [r1], #4 99 bne copyex 100#endif 101 102#ifdef CONFIG_S3C24X0 103 /* turn off the watchdog */ 104 105# if defined(CONFIG_S3C2400) 106# define pWTCON 0x15300000 107# define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ 108# define CLKDIVN 0x14800014 /* clock divisor register */ 109#else 110# define pWTCON 0x53000000 111# define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ 112# define INTSUBMSK 0x4A00001C 113# define CLKDIVN 0x4C000014 /* clock divisor register */ 114# endif 115 116 ldr r0, =pWTCON 117 mov r1, #0x0 118 str r1, [r0] 119 120 /* 121 * mask all IRQs by setting all bits in the INTMR - default 122 */ 123 mov r1, #0xffffffff 124 ldr r0, =INTMSK 125 str r1, [r0] 126# if defined(CONFIG_S3C2410) 127 ldr r1, =0x3ff 128 ldr r0, =INTSUBMSK 129 str r1, [r0] 130# endif 131 132 /* FCLK:HCLK:PCLK = 1:2:4 */ 133 /* default FCLK is 120 MHz ! */ 134 ldr r0, =CLKDIVN 135 mov r1, #3 136 str r1, [r0] 137#endif /* CONFIG_S3C24X0 */ 138 139 /* 140 * we do sys-critical inits only at reboot, 141 * not when booting from ram! 142 */ 143#ifndef CONFIG_SKIP_LOWLEVEL_INIT 144 bl cpu_init_crit 145#endif 146 147 bl _main 148 149/*------------------------------------------------------------------------------*/ 150 151 .globl c_runtime_cpu_setup 152c_runtime_cpu_setup: 153 154 mov pc, lr 155 156/* 157 ************************************************************************* 158 * 159 * CPU_init_critical registers 160 * 161 * setup important registers 162 * setup memory timing 163 * 164 ************************************************************************* 165 */ 166 167 168#ifndef CONFIG_SKIP_LOWLEVEL_INIT 169cpu_init_crit: 170 /* 171 * flush v4 I/D caches 172 */ 173 mov r0, #0 174 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 175 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 176 177 /* 178 * disable MMU stuff and caches 179 */ 180 mrc p15, 0, r0, c1, c0, 0 181 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 182 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 183 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 184 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 185 mcr p15, 0, r0, c1, c0, 0 186 187 /* 188 * before relocating, we have to setup RAM timing 189 * because memory timing is board-dependend, you will 190 * find a lowlevel_init.S in your board directory. 191 */ 192 mov ip, lr 193 194 bl lowlevel_init 195 196 mov lr, ip 197 mov pc, lr 198#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ 199 200/* 201 ************************************************************************* 202 * 203 * Interrupt handling 204 * 205 ************************************************************************* 206 */ 207 208@ 209@ IRQ stack frame. 210@ 211#define S_FRAME_SIZE 72 212 213#define S_OLD_R0 68 214#define S_PSR 64 215#define S_PC 60 216#define S_LR 56 217#define S_SP 52 218 219#define S_IP 48 220#define S_FP 44 221#define S_R10 40 222#define S_R9 36 223#define S_R8 32 224#define S_R7 28 225#define S_R6 24 226#define S_R5 20 227#define S_R4 16 228#define S_R3 12 229#define S_R2 8 230#define S_R1 4 231#define S_R0 0 232 233#define MODE_SVC 0x13 234#define I_BIT 0x80 235 236/* 237 * use bad_save_user_regs for abort/prefetch/undef/swi ... 238 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 239 */ 240 241 .macro bad_save_user_regs 242 sub sp, sp, #S_FRAME_SIZE 243 stmia sp, {r0 - r12} @ Calling r0-r12 244 ldr r2, IRQ_STACK_START_IN 245 ldmia r2, {r2 - r3} @ get pc, cpsr 246 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 247 248 add r5, sp, #S_SP 249 mov r1, lr 250 stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr 251 mov r0, sp 252 .endm 253 254 .macro irq_save_user_regs 255 sub sp, sp, #S_FRAME_SIZE 256 stmia sp, {r0 - r12} @ Calling r0-r12 257 add r7, sp, #S_PC 258 stmdb r7, {sp, lr}^ @ Calling SP, LR 259 str lr, [r7, #0] @ Save calling PC 260 mrs r6, spsr 261 str r6, [r7, #4] @ Save CPSR 262 str r0, [r7, #8] @ Save OLD_R0 263 mov r0, sp 264 .endm 265 266 .macro irq_restore_user_regs 267 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 268 mov r0, r0 269 ldr lr, [sp, #S_PC] @ Get PC 270 add sp, sp, #S_FRAME_SIZE 271 /* return & move spsr_svc into cpsr */ 272 subs pc, lr, #4 273 .endm 274 275 .macro get_bad_stack 276 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 277 278 str lr, [r13] @ save caller lr / spsr 279 mrs lr, spsr 280 str lr, [r13, #4] 281 282 mov r13, #MODE_SVC @ prepare SVC-Mode 283 @ msr spsr_c, r13 284 msr spsr, r13 285 mov lr, pc 286 movs pc, lr 287 .endm 288 289 .macro get_irq_stack @ setup IRQ stack 290 ldr sp, IRQ_STACK_START 291 .endm 292 293 .macro get_fiq_stack @ setup FIQ stack 294 ldr sp, FIQ_STACK_START 295 .endm 296 297/* 298 * exception handlers 299 */ 300 .align 5 301undefined_instruction: 302 get_bad_stack 303 bad_save_user_regs 304 bl do_undefined_instruction 305 306 .align 5 307software_interrupt: 308 get_bad_stack 309 bad_save_user_regs 310 bl do_software_interrupt 311 312 .align 5 313prefetch_abort: 314 get_bad_stack 315 bad_save_user_regs 316 bl do_prefetch_abort 317 318 .align 5 319data_abort: 320 get_bad_stack 321 bad_save_user_regs 322 bl do_data_abort 323 324 .align 5 325not_used: 326 get_bad_stack 327 bad_save_user_regs 328 bl do_not_used 329 330#ifdef CONFIG_USE_IRQ 331 332 .align 5 333irq: 334 get_irq_stack 335 irq_save_user_regs 336 bl do_irq 337 irq_restore_user_regs 338 339 .align 5 340fiq: 341 get_fiq_stack 342 /* someone ought to write a more effiction fiq_save_user_regs */ 343 irq_save_user_regs 344 bl do_fiq 345 irq_restore_user_regs 346 347#else 348 349 .align 5 350irq: 351 get_bad_stack 352 bad_save_user_regs 353 bl do_irq 354 355 .align 5 356fiq: 357 get_bad_stack 358 bad_save_user_regs 359 bl do_fiq 360 361#endif 362