1/* 2 * armboot - Startup Code for ARM1176 CPU-core 3 * 4 * Copyright (c) 2007 Samsung Electronics 5 * 6 * Copyright (C) 2008 7 * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> 8 * 9 * SPDX-License-Identifier: GPL-2.0+ 10 * 11 * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com) 12 * 2007-09-21 - Added MoviNAND and OneNAND boot codes by 13 * jsgood (jsgood.yang@samsung.com) 14 * Base codes by scsuh (sc.suh) 15 */ 16 17#include <asm-offsets.h> 18#include <config.h> 19#include <version.h> 20 21#ifndef CONFIG_SYS_PHY_UBOOT_BASE 22#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE 23#endif 24 25/* 26 ************************************************************************* 27 * 28 * Jump vector table as in table 3.1 in [1] 29 * 30 ************************************************************************* 31 */ 32 33.globl _start 34_start: b reset 35#ifndef CONFIG_SPL_BUILD 36 ldr pc, _undefined_instruction 37 ldr pc, _software_interrupt 38 ldr pc, _prefetch_abort 39 ldr pc, _data_abort 40 ldr pc, _not_used 41 ldr pc, _irq 42 ldr pc, _fiq 43 44_undefined_instruction: 45 .word undefined_instruction 46_software_interrupt: 47 .word software_interrupt 48_prefetch_abort: 49 .word prefetch_abort 50_data_abort: 51 .word data_abort 52_not_used: 53 .word not_used 54_irq: 55 .word irq 56_fiq: 57 .word fiq 58_pad: 59 .word 0x12345678 /* now 16*4=64 */ 60#else 61 . = _start + 64 62#endif 63 64 .balignl 16,0xdeadbeef 65/* 66 ************************************************************************* 67 * 68 * Startup Code (reset vector) 69 * 70 * do important init only if we don't start from memory! 71 * setup Memory and board specific bits prior to relocation. 72 * relocate armboot to ram 73 * setup stack 74 * 75 ************************************************************************* 76 */ 77 78/* IRQ stack memory (calculated at run-time) + 8 bytes */ 79.globl IRQ_STACK_START_IN 80IRQ_STACK_START_IN: 81 .word 0x0badc0de 82 83/* 84 * the actual reset code 85 */ 86 87reset: 88 /* 89 * set the cpu to SVC32 mode 90 */ 91 mrs r0, cpsr 92 bic r0, r0, #0x3f 93 orr r0, r0, #0xd3 94 msr cpsr, r0 95 96/* 97 ************************************************************************* 98 * 99 * CPU_init_critical registers 100 * 101 * setup important registers 102 * setup memory timing 103 * 104 ************************************************************************* 105 */ 106 /* 107 * we do sys-critical inits only at reboot, 108 * not when booting from ram! 109 */ 110cpu_init_crit: 111 /* 112 * When booting from NAND - it has definitely been a reset, so, no need 113 * to flush caches and disable the MMU 114 */ 115#ifndef CONFIG_SPL_BUILD 116 /* 117 * flush v4 I/D caches 118 */ 119 mov r0, #0 120 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 121 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 122 123 /* 124 * disable MMU stuff and caches 125 */ 126 mrc p15, 0, r0, c1, c0, 0 127 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 128 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 129 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 130 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 131 132 /* Prepare to disable the MMU */ 133 adr r2, mmu_disable_phys 134 sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE) 135 b mmu_disable 136 137 .align 5 138 /* Run in a single cache-line */ 139mmu_disable: 140 mcr p15, 0, r0, c1, c0, 0 141 nop 142 nop 143 mov pc, r2 144mmu_disable_phys: 145 146#ifdef CONFIG_DISABLE_TCM 147 /* 148 * Disable the TCMs 149 */ 150 mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */ 151 cmp r0, #0 152 beq skip_tcmdisable 153 mov r1, #0 154 mov r2, #1 155 tst r0, r2 156 mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/ 157 tst r0, r2, LSL #16 158 mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/ 159skip_tcmdisable: 160#endif 161#endif 162 163#ifdef CONFIG_PERIPORT_REMAP 164 /* Peri port setup */ 165 ldr r0, =CONFIG_PERIPORT_BASE 166 orr r0, r0, #CONFIG_PERIPORT_SIZE 167 mcr p15,0,r0,c15,c2,4 168#endif 169 170 /* 171 * Go setup Memory and board specific bits prior to relocation. 172 */ 173 bl lowlevel_init /* go setup pll,mux,memory */ 174 175 bl _main 176 177/*------------------------------------------------------------------------------*/ 178 179 .globl c_runtime_cpu_setup 180c_runtime_cpu_setup: 181 182 mov pc, lr 183 184#ifndef CONFIG_SPL_BUILD 185/* 186 ************************************************************************* 187 * 188 * Interrupt handling 189 * 190 ************************************************************************* 191 */ 192@ 193@ IRQ stack frame. 194@ 195#define S_FRAME_SIZE 72 196 197#define S_OLD_R0 68 198#define S_PSR 64 199#define S_PC 60 200#define S_LR 56 201#define S_SP 52 202 203#define S_IP 48 204#define S_FP 44 205#define S_R10 40 206#define S_R9 36 207#define S_R8 32 208#define S_R7 28 209#define S_R6 24 210#define S_R5 20 211#define S_R4 16 212#define S_R3 12 213#define S_R2 8 214#define S_R1 4 215#define S_R0 0 216 217#define MODE_SVC 0x13 218#define I_BIT 0x80 219 220/* 221 * use bad_save_user_regs for abort/prefetch/undef/swi ... 222 */ 223 224 .macro bad_save_user_regs 225 /* carve out a frame on current user stack */ 226 sub sp, sp, #S_FRAME_SIZE 227 /* Save user registers (now in svc mode) r0-r12 */ 228 stmia sp, {r0 - r12} 229 230 ldr r2, IRQ_STACK_START_IN 231 /* get values for "aborted" pc and cpsr (into parm regs) */ 232 ldmia r2, {r2 - r3} 233 /* grab pointer to old stack */ 234 add r0, sp, #S_FRAME_SIZE 235 236 add r5, sp, #S_SP 237 mov r1, lr 238 /* save sp_SVC, lr_SVC, pc, cpsr */ 239 stmia r5, {r0 - r3} 240 /* save current stack into r0 (param register) */ 241 mov r0, sp 242 .endm 243 244 .macro get_bad_stack 245 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 246 247 /* save caller lr in position 0 of saved stack */ 248 str lr, [r13] 249 /* get the spsr */ 250 mrs lr, spsr 251 /* save spsr in position 1 of saved stack */ 252 str lr, [r13, #4] 253 254 /* prepare SVC-Mode */ 255 mov r13, #MODE_SVC 256 @ msr spsr_c, r13 257 /* switch modes, make sure moves will execute */ 258 msr spsr, r13 259 /* capture return pc */ 260 mov lr, pc 261 /* jump to next instruction & switch modes. */ 262 movs pc, lr 263 .endm 264 265 .macro get_bad_stack_swi 266 /* space on current stack for scratch reg. */ 267 sub r13, r13, #4 268 /* save R0's value. */ 269 str r0, [r13] 270 ldr r13, IRQ_STACK_START_IN @ setup our mode stack 271 /* save caller lr in position 0 of saved stack */ 272 str lr, [r0] 273 /* get the spsr */ 274 mrs lr, spsr 275 /* save spsr in position 1 of saved stack */ 276 str lr, [r0, #4] 277 /* restore lr */ 278 ldr lr, [r0] 279 /* restore r0 */ 280 ldr r0, [r13] 281 /* pop stack entry */ 282 add r13, r13, #4 283 .endm 284 285/* 286 * exception handlers 287 */ 288 .align 5 289undefined_instruction: 290 get_bad_stack 291 bad_save_user_regs 292 bl do_undefined_instruction 293 294 .align 5 295software_interrupt: 296 get_bad_stack_swi 297 bad_save_user_regs 298 bl do_software_interrupt 299 300 .align 5 301prefetch_abort: 302 get_bad_stack 303 bad_save_user_regs 304 bl do_prefetch_abort 305 306 .align 5 307data_abort: 308 get_bad_stack 309 bad_save_user_regs 310 bl do_data_abort 311 312 .align 5 313not_used: 314 get_bad_stack 315 bad_save_user_regs 316 bl do_not_used 317 318 .align 5 319irq: 320 get_bad_stack 321 bad_save_user_regs 322 bl do_irq 323 324 .align 5 325fiq: 326 get_bad_stack 327 bad_save_user_regs 328 bl do_fiq 329#endif /* CONFIG_SPL_BUILD */ 330