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 * See file CREDITS for list of people who contributed to this 10 * project. 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; either version 2 of 15 * the License, or (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 25 * MA 02111-1307 USA 26 * 27 * 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com) 28 * 2007-09-21 - Added MoviNAND and OneNAND boot codes by 29 * jsgood (jsgood.yang@samsung.com) 30 * Base codes by scsuh (sc.suh) 31 */ 32 33#include <config.h> 34#include <version.h> 35#ifdef CONFIG_ENABLE_MMU 36#include <asm/proc/domain.h> 37#endif 38 39#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE) 40#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE 41#endif 42 43/* 44 ************************************************************************* 45 * 46 * Jump vector table as in table 3.1 in [1] 47 * 48 ************************************************************************* 49 */ 50 51.globl _start 52_start: b reset 53#ifndef CONFIG_NAND_SPL 54 ldr pc, _undefined_instruction 55 ldr pc, _software_interrupt 56 ldr pc, _prefetch_abort 57 ldr pc, _data_abort 58 ldr pc, _not_used 59 ldr pc, _irq 60 ldr pc, _fiq 61 62_undefined_instruction: 63 .word undefined_instruction 64_software_interrupt: 65 .word software_interrupt 66_prefetch_abort: 67 .word prefetch_abort 68_data_abort: 69 .word data_abort 70_not_used: 71 .word not_used 72_irq: 73 .word irq 74_fiq: 75 .word fiq 76_pad: 77 .word 0x12345678 /* now 16*4=64 */ 78#else 79 . = _start + 64 80#endif 81 82.global _end_vect 83_end_vect: 84 .balignl 16,0xdeadbeef 85/* 86 ************************************************************************* 87 * 88 * Startup Code (reset vector) 89 * 90 * do important init only if we don't start from memory! 91 * setup Memory and board specific bits prior to relocation. 92 * relocate armboot to ram 93 * setup stack 94 * 95 ************************************************************************* 96 */ 97 98_TEXT_BASE: 99 .word TEXT_BASE 100 101/* 102 * Below variable is very important because we use MMU in U-Boot. 103 * Without it, we cannot run code correctly before MMU is ON. 104 * by scsuh. 105 */ 106_TEXT_PHY_BASE: 107 .word CONFIG_SYS_PHY_UBOOT_BASE 108 109.globl _armboot_start 110_armboot_start: 111 .word _start 112 113/* 114 * These are defined in the board-specific linker script. 115 */ 116.globl _bss_start 117_bss_start: 118 .word __bss_start 119 120.globl _bss_end 121_bss_end: 122 .word _end 123 124/* 125 * the actual reset code 126 */ 127 128reset: 129 /* 130 * set the cpu to SVC32 mode 131 */ 132 mrs r0, cpsr 133 bic r0, r0, #0x3f 134 orr r0, r0, #0xd3 135 msr cpsr, r0 136 137/* 138 ************************************************************************* 139 * 140 * CPU_init_critical registers 141 * 142 * setup important registers 143 * setup memory timing 144 * 145 ************************************************************************* 146 */ 147 /* 148 * we do sys-critical inits only at reboot, 149 * not when booting from ram! 150 */ 151cpu_init_crit: 152 /* 153 * When booting from NAND - it has definitely been a reset, so, no need 154 * to flush caches and disable the MMU 155 */ 156#ifndef CONFIG_NAND_SPL 157 /* 158 * flush v4 I/D caches 159 */ 160 mov r0, #0 161 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 162 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 163 164 /* 165 * disable MMU stuff and caches 166 */ 167 mrc p15, 0, r0, c1, c0, 0 168 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 169 bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) 170 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 171 orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache 172 173 /* Prepare to disable the MMU */ 174 adr r2, mmu_disable_phys 175 sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - TEXT_BASE) 176 b mmu_disable 177 178 .align 5 179 /* Run in a single cache-line */ 180mmu_disable: 181 mcr p15, 0, r0, c1, c0, 0 182 nop 183 nop 184 mov pc, r2 185mmu_disable_phys: 186 187#ifdef CONFIG_DISABLE_TCM 188 /* 189 * Disable the TCMs 190 */ 191 mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */ 192 cmp r0, #0 193 beq skip_tcmdisable 194 mov r1, #0 195 mov r2, #1 196 tst r0, r2 197 mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/ 198 tst r0, r2, LSL #16 199 mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/ 200skip_tcmdisable: 201#endif 202#endif 203 204#ifdef CONFIG_PERIPORT_REMAP 205 /* Peri port setup */ 206 ldr r0, =CONFIG_PERIPORT_BASE 207 orr r0, r0, #CONFIG_PERIPORT_SIZE 208 mcr p15,0,r0,c15,c2,4 209#endif 210 211 /* 212 * Go setup Memory and board specific bits prior to relocation. 213 */ 214 bl lowlevel_init /* go setup pll,mux,memory */ 215 216#ifndef CONFIG_SKIP_RELOCATE_UBOOT 217relocate: /* relocate U-Boot to RAM */ 218 adr r0, _start /* r0 <- current position of code */ 219 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 220 cmp r0, r1 /* don't reloc during debug */ 221 beq stack_setup 222 223 ldr r2, _armboot_start 224 ldr r3, _bss_start 225 sub r2, r3, r2 /* r2 <- size of armboot */ 226 add r2, r0, r2 /* r2 <- source end address */ 227 228copy_loop: 229 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 230 stmia r1!, {r3-r10} /* copy to target address [r1] */ 231 cmp r0, r2 /* until source end addreee [r2] */ 232 ble copy_loop 233#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 234 235#ifdef CONFIG_ENABLE_MMU 236enable_mmu: 237 /* enable domain access */ 238 ldr r5, =0x0000ffff 239 mcr p15, 0, r5, c3, c0, 0 /* load domain access register */ 240 241 /* Set the TTB register */ 242 ldr r0, _mmu_table_base 243 ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE 244 ldr r2, =0xfff00000 245 bic r0, r0, r2 246 orr r1, r0, r1 247 mcr p15, 0, r1, c2, c0, 0 248 249 /* Enable the MMU */ 250 mrc p15, 0, r0, c1, c0, 0 251 orr r0, r0, #1 /* Set CR_M to enable MMU */ 252 253 /* Prepare to enable the MMU */ 254 adr r1, skip_hw_init 255 and r1, r1, #0x3fc 256 ldr r2, _TEXT_BASE 257 ldr r3, =0xfff00000 258 and r2, r2, r3 259 orr r2, r2, r1 260 b mmu_enable 261 262 .align 5 263 /* Run in a single cache-line */ 264mmu_enable: 265 266 mcr p15, 0, r0, c1, c0, 0 267 nop 268 nop 269 mov pc, r2 270skip_hw_init: 271#endif 272 273 /* Set up the stack */ 274stack_setup: 275 ldr r0, =CONFIG_SYS_UBOOT_BASE /* base of copy in DRAM */ 276 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 277 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 278 sub sp, r0, #12 /* leave 3 words for abort-stack */ 279 bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ 280 281clear_bss: 282 ldr r0, _bss_start /* find start of bss segment */ 283 ldr r1, _bss_end /* stop here */ 284 mov r2, #0 /* clear */ 285 286clbss_l: 287 str r2, [r0] /* clear loop... */ 288 add r0, r0, #4 289 cmp r0, r1 290 ble clbss_l 291 292#ifndef CONFIG_NAND_SPL 293 ldr pc, _start_armboot 294 295_start_armboot: 296 .word start_armboot 297#else 298 b nand_boot 299/* .word nand_boot*/ 300#endif 301 302#ifdef CONFIG_ENABLE_MMU 303_mmu_table_base: 304 .word mmu_table 305#endif 306 307#ifndef CONFIG_NAND_SPL 308/* 309 * we assume that cache operation is done before. (eg. cleanup_before_linux()) 310 * actually, we don't need to do anything about cache if not use d-cache in 311 * U-Boot. So, in this function we clean only MMU. by scsuh 312 * 313 * void theLastJump(void *kernel, int arch_num, uint boot_params); 314 */ 315#ifdef CONFIG_ENABLE_MMU 316 .globl theLastJump 317theLastJump: 318 mov r9, r0 319 ldr r3, =0xfff00000 320 ldr r4, _TEXT_PHY_BASE 321 adr r5, phy_last_jump 322 bic r5, r5, r3 323 orr r5, r5, r4 324 mov pc, r5 325phy_last_jump: 326 /* 327 * disable MMU stuff 328 */ 329 mrc p15, 0, r0, c1, c0, 0 330 bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (--V- --RS) */ 331 bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B--- -CAM) */ 332 orr r0, r0, #0x00000002 /* set bit 2 (A) Align */ 333 orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */ 334 mcr p15, 0, r0, c1, c0, 0 335 336 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 337 338 mov r0, #0 339 mov pc, r9 340#endif 341 342 343/* 344 ************************************************************************* 345 * 346 * Interrupt handling 347 * 348 ************************************************************************* 349 */ 350@ 351@ IRQ stack frame. 352@ 353#define S_FRAME_SIZE 72 354 355#define S_OLD_R0 68 356#define S_PSR 64 357#define S_PC 60 358#define S_LR 56 359#define S_SP 52 360 361#define S_IP 48 362#define S_FP 44 363#define S_R10 40 364#define S_R9 36 365#define S_R8 32 366#define S_R7 28 367#define S_R6 24 368#define S_R5 20 369#define S_R4 16 370#define S_R3 12 371#define S_R2 8 372#define S_R1 4 373#define S_R0 0 374 375#define MODE_SVC 0x13 376#define I_BIT 0x80 377 378/* 379 * use bad_save_user_regs for abort/prefetch/undef/swi ... 380 */ 381 382 .macro bad_save_user_regs 383 /* carve out a frame on current user stack */ 384 sub sp, sp, #S_FRAME_SIZE 385 /* Save user registers (now in svc mode) r0-r12 */ 386 stmia sp, {r0 - r12} 387 388 ldr r2, _armboot_start 389 sub r2, r2, #(CONFIG_SYS_MALLOC_LEN) 390 /* set base 2 words into abort stack */ 391 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) 392 /* get values for "aborted" pc and cpsr (into parm regs) */ 393 ldmia r2, {r2 - r3} 394 /* grab pointer to old stack */ 395 add r0, sp, #S_FRAME_SIZE 396 397 add r5, sp, #S_SP 398 mov r1, lr 399 /* save sp_SVC, lr_SVC, pc, cpsr */ 400 stmia r5, {r0 - r3} 401 /* save current stack into r0 (param register) */ 402 mov r0, sp 403 .endm 404 405 .macro get_bad_stack 406 /* setup our mode stack (enter in banked mode) */ 407 ldr r13, _armboot_start 408 /* move past malloc pool */ 409 sub r13, r13, #(CONFIG_SYS_MALLOC_LEN) 410 /* move to reserved a couple spots for abort stack */ 411 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE + 8) 412 413 /* save caller lr in position 0 of saved stack */ 414 str lr, [r13] 415 /* get the spsr */ 416 mrs lr, spsr 417 /* save spsr in position 1 of saved stack */ 418 str lr, [r13, #4] 419 420 /* prepare SVC-Mode */ 421 mov r13, #MODE_SVC 422 @ msr spsr_c, r13 423 /* switch modes, make sure moves will execute */ 424 msr spsr, r13 425 /* capture return pc */ 426 mov lr, pc 427 /* jump to next instruction & switch modes. */ 428 movs pc, lr 429 .endm 430 431 .macro get_bad_stack_swi 432 /* space on current stack for scratch reg. */ 433 sub r13, r13, #4 434 /* save R0's value. */ 435 str r0, [r13] 436 /* get data regions start */ 437 ldr r0, _armboot_start 438 /* move past malloc pool */ 439 sub r0, r0, #(CONFIG_SYS_MALLOC_LEN) 440 /* move past gbl and a couple spots for abort stack */ 441 sub r0, r0, #(CONFIG_SYS_GBL_DATA_SIZE + 8) 442 /* save caller lr in position 0 of saved stack */ 443 str lr, [r0] 444 /* get the spsr */ 445 mrs r0, spsr 446 /* save spsr in position 1 of saved stack */ 447 str lr, [r0, #4] 448 /* restore r0 */ 449 ldr r0, [r13] 450 /* pop stack entry */ 451 add r13, r13, #4 452 .endm 453 454/* 455 * exception handlers 456 */ 457 .align 5 458undefined_instruction: 459 get_bad_stack 460 bad_save_user_regs 461 bl do_undefined_instruction 462 463 .align 5 464software_interrupt: 465 get_bad_stack_swi 466 bad_save_user_regs 467 bl do_software_interrupt 468 469 .align 5 470prefetch_abort: 471 get_bad_stack 472 bad_save_user_regs 473 bl do_prefetch_abort 474 475 .align 5 476data_abort: 477 get_bad_stack 478 bad_save_user_regs 479 bl do_data_abort 480 481 .align 5 482not_used: 483 get_bad_stack 484 bad_save_user_regs 485 bl do_not_used 486 487 .align 5 488irq: 489 get_bad_stack 490 bad_save_user_regs 491 bl do_irq 492 493 .align 5 494fiq: 495 get_bad_stack 496 bad_save_user_regs 497 bl do_fiq 498#endif /* CONFIG_NAND_SPL */ 499