1/* 2 * armboot - Startup Code for ARM720 CPU-core 3 * 4 * Copyright (c) 2001 Marius Gr�ger <mag@sysgo.de> 5 * Copyright (c) 2002 Alex Z�pke <azu@sysgo.de> 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 27#include <config.h> 28#include <version.h> 29#include <asm/hardware.h> 30 31/* 32 ************************************************************************* 33 * 34 * Jump vector table as in table 3.1 in [1] 35 * 36 ************************************************************************* 37 */ 38 39 40.globl _start 41_start: b reset 42 ldr pc, _undefined_instruction 43 ldr pc, _software_interrupt 44 ldr pc, _prefetch_abort 45 ldr pc, _data_abort 46#ifdef CONFIG_LPC2292 47 .word 0xB4405F76 /* 2's complement of the checksum of the vectors */ 48#else 49 ldr pc, _not_used 50#endif 51 ldr pc, _irq 52 ldr pc, _fiq 53 54_undefined_instruction: .word undefined_instruction 55_software_interrupt: .word software_interrupt 56_prefetch_abort: .word prefetch_abort 57_data_abort: .word data_abort 58_not_used: .word not_used 59_irq: .word irq 60_fiq: .word fiq 61 62 .balignl 16,0xdeadbeef 63 64 65/* 66 ************************************************************************* 67 * 68 * Startup Code (reset vector) 69 * 70 * do important init only if we don't start from RAM! 71 * relocate armboot to ram 72 * setup stack 73 * jump to second stage 74 * 75 ************************************************************************* 76 */ 77 78_TEXT_BASE: 79 .word TEXT_BASE 80 81.globl _armboot_start 82_armboot_start: 83 .word _start 84 85/* 86 * These are defined in the board-specific linker script. 87 */ 88.globl _bss_start 89_bss_start: 90 .word __bss_start 91 92.globl _bss_end 93_bss_end: 94 .word _end 95 96#ifdef CONFIG_USE_IRQ 97/* IRQ stack memory (calculated at run-time) */ 98.globl IRQ_STACK_START 99IRQ_STACK_START: 100 .word 0x0badc0de 101 102/* IRQ stack memory (calculated at run-time) */ 103.globl FIQ_STACK_START 104FIQ_STACK_START: 105 .word 0x0badc0de 106#endif 107 108 109/* 110 * the actual reset code 111 */ 112 113reset: 114 /* 115 * set the cpu to SVC32 mode 116 */ 117 mrs r0,cpsr 118 bic r0,r0,#0x1f 119 orr r0,r0,#0x13 120 msr cpsr,r0 121 122 /* 123 * we do sys-critical inits only at reboot, 124 * not when booting from ram! 125 */ 126#ifndef CONFIG_SKIP_LOWLEVEL_INIT 127 bl cpu_init_crit 128#endif 129 130#ifdef CONFIG_LPC2292 131 bl lowlevel_init 132#endif 133 134#ifndef CONFIG_SKIP_RELOCATE_UBOOT 135relocate: /* relocate U-Boot to RAM */ 136 adr r0, _start /* r0 <- current position of code */ 137 ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ 138 cmp r0, r1 /* don't reloc during debug */ 139 beq stack_setup 140 141#if TEXT_BASE 142#ifndef CONFIG_LPC2292 /* already done in lowlevel_init */ 143 ldr r2, =0x0 /* Relocate the exception vectors */ 144 cmp r1, r2 /* and associated data to address */ 145 ldmneia r0!, {r3-r10} /* 0x0. Do nothing if TEXT_BASE is */ 146 stmneia r2!, {r3-r10} /* 0x0. Copy the first 15 words. */ 147 ldmneia r0, {r3-r9} 148 stmneia r2, {r3-r9} 149 adrne r0, _start /* restore r0 */ 150#endif /* !CONFIG_LPC2292 */ 151#endif 152 153 ldr r2, _armboot_start 154 ldr r3, _bss_start 155 sub r2, r3, r2 /* r2 <- size of armboot */ 156 add r2, r0, r2 /* r2 <- source end address */ 157 158copy_loop: 159 ldmia r0!, {r3-r10} /* copy from source address [r0] */ 160 stmia r1!, {r3-r10} /* copy to target address [r1] */ 161 cmp r0, r2 /* until source end addreee [r2] */ 162 ble copy_loop 163 164#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ 165 166 /* Set up the stack */ 167stack_setup: 168 ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */ 169 sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */ 170 sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */ 171#ifdef CONFIG_USE_IRQ 172 sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) 173#endif 174 sub sp, r0, #12 /* leave 3 words for abort-stack */ 175 176clear_bss: 177 ldr r0, _bss_start /* find start of bss segment */ 178 ldr r1, _bss_end /* stop here */ 179 mov r2, #0x00000000 /* clear */ 180 181clbss_l:str r2, [r0] /* clear loop... */ 182 add r0, r0, #4 183 cmp r0, r1 184 ble clbss_l 185 186 ldr pc, _start_armboot 187 188_start_armboot: .word start_armboot 189 190/* 191 ************************************************************************* 192 * 193 * CPU_init_critical registers 194 * 195 * setup important registers 196 * setup memory timing 197 * 198 ************************************************************************* 199 */ 200 201#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) 202 203/* Interupt-Controller base addresses */ 204INTMR1: .word 0x80000280 @ 32 bit size 205INTMR2: .word 0x80001280 @ 16 bit size 206INTMR3: .word 0x80002280 @ 8 bit size 207 208/* SYSCONs */ 209SYSCON1: .word 0x80000100 210SYSCON2: .word 0x80001100 211SYSCON3: .word 0x80002200 212 213#define CLKCTL 0x6 /* mask */ 214#define CLKCTL_18 0x0 /* 18.432 MHz */ 215#define CLKCTL_36 0x2 /* 36.864 MHz */ 216#define CLKCTL_49 0x4 /* 49.152 MHz */ 217#define CLKCTL_73 0x6 /* 73.728 MHz */ 218 219#elif defined(CONFIG_LPC2292) 220PLLCFG_ADR: .word PLLCFG 221PLLFEED_ADR: .word PLLFEED 222PLLCON_ADR: .word PLLCON 223PLLSTAT_ADR: .word PLLSTAT 224VPBDIV_ADR: .word VPBDIV 225MEMMAP_ADR: .word MEMMAP 226 227#endif 228 229cpu_init_crit: 230#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) 231 232 /* 233 * mask all IRQs by clearing all bits in the INTMRs 234 */ 235 mov r1, #0x00 236 ldr r0, INTMR1 237 str r1, [r0] 238 ldr r0, INTMR2 239 str r1, [r0] 240 ldr r0, INTMR3 241 str r1, [r0] 242 243 /* 244 * flush v4 I/D caches 245 */ 246 mov r0, #0 247 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ 248 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ 249 250 /* 251 * disable MMU stuff and caches 252 */ 253 mrc p15,0,r0,c1,c0 254 bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) 255 bic r0, r0, #0x0000008f @ clear bits 7, 3:0 (B--- WCAM) 256 orr r0, r0, #0x00000002 @ set bit 2 (A) Align 257 mcr p15,0,r0,c1,c0 258#elif defined(CONFIG_NETARM) 259 /* 260 * prior to software reset : need to set pin PORTC4 to be *HRESET 261 */ 262 ldr r0, =NETARM_GEN_MODULE_BASE 263 ldr r1, =(NETARM_GEN_PORT_MODE(0x10) | \ 264 NETARM_GEN_PORT_DIR(0x10)) 265 str r1, [r0, #+NETARM_GEN_PORTC] 266 /* 267 * software reset : see HW Ref. Guide 8.2.4 : Software Service register 268 * for an explanation of this process 269 */ 270 ldr r0, =NETARM_GEN_MODULE_BASE 271 ldr r1, =NETARM_GEN_SW_SVC_RESETA 272 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] 273 ldr r1, =NETARM_GEN_SW_SVC_RESETB 274 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] 275 ldr r1, =NETARM_GEN_SW_SVC_RESETA 276 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] 277 ldr r1, =NETARM_GEN_SW_SVC_RESETB 278 str r1, [r0, #+NETARM_GEN_SOFTWARE_SERVICE] 279 /* 280 * setup PLL and System Config 281 */ 282 ldr r0, =NETARM_GEN_MODULE_BASE 283 284 ldr r1, =( NETARM_GEN_SYS_CFG_LENDIAN | \ 285 NETARM_GEN_SYS_CFG_BUSFULL | \ 286 NETARM_GEN_SYS_CFG_USER_EN | \ 287 NETARM_GEN_SYS_CFG_ALIGN_ABORT | \ 288 NETARM_GEN_SYS_CFG_BUSARB_INT | \ 289 NETARM_GEN_SYS_CFG_BUSMON_EN ) 290 291 str r1, [r0, #+NETARM_GEN_SYSTEM_CONTROL] 292 293#ifndef CONFIG_NETARM_PLL_BYPASS 294 ldr r1, =( NETARM_GEN_PLL_CTL_PLLCNT(NETARM_PLL_COUNT_VAL) | \ 295 NETARM_GEN_PLL_CTL_POLTST_DEF | \ 296 NETARM_GEN_PLL_CTL_INDIV(1) | \ 297 NETARM_GEN_PLL_CTL_ICP_DEF | \ 298 NETARM_GEN_PLL_CTL_OUTDIV(2) ) 299 str r1, [r0, #+NETARM_GEN_PLL_CONTROL] 300#endif 301 302 /* 303 * mask all IRQs by clearing all bits in the INTMRs 304 */ 305 mov r1, #0 306 ldr r0, =NETARM_GEN_MODULE_BASE 307 str r1, [r0, #+NETARM_GEN_INTR_ENABLE] 308 309#elif defined(CONFIG_S3C4510B) 310 311 /* 312 * Mask off all IRQ sources 313 */ 314 ldr r1, =REG_INTMASK 315 ldr r0, =0x3FFFFF 316 str r0, [r1] 317 318 /* 319 * Disable Cache 320 */ 321 ldr r0, =REG_SYSCFG 322 ldr r1, =0x83ffffa0 /* cache-disabled */ 323 str r1, [r0] 324 325#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 326 /* No specific initialisation for IntegratorAP/CM720T as yet */ 327#elif defined(CONFIG_LPC2292) 328 /* Set-up PLL */ 329 mov r3, #0xAA 330 mov r4, #0x55 331 /* First disconnect and disable the PLL */ 332 ldr r0, PLLCON_ADR 333 mov r1, #0x00 334 str r1, [r0] 335 ldr r0, PLLFEED_ADR /* start feed sequence */ 336 str r3, [r0] 337 str r4, [r0] /* feed sequence done */ 338 /* Set new M and P values */ 339 ldr r0, PLLCFG_ADR 340 mov r1, #0x23 /* M=4 and P=2 */ 341 str r1, [r0] 342 ldr r0, PLLFEED_ADR /* start feed sequence */ 343 str r3, [r0] 344 str r4, [r0] /* feed sequence done */ 345 /* Then enable the PLL */ 346 ldr r0, PLLCON_ADR 347 mov r1, #0x01 /* PLL enable bit */ 348 str r1, [r0] 349 ldr r0, PLLFEED_ADR /* start feed sequence */ 350 str r3, [r0] 351 str r4, [r0] /* feed sequence done */ 352 /* Wait for the lock */ 353 ldr r0, PLLSTAT_ADR 354 mov r1, #0x400 /* lock bit */ 355lock_loop: 356 ldr r2, [r0] 357 and r2, r1, r2 358 cmp r2, #0 359 beq lock_loop 360 /* And finally connect the PLL */ 361 ldr r0, PLLCON_ADR 362 mov r1, #0x03 /* PLL enable bit and connect bit */ 363 str r1, [r0] 364 ldr r0, PLLFEED_ADR /* start feed sequence */ 365 str r3, [r0] 366 str r4, [r0] /* feed sequence done */ 367 /* Set-up VPBDIV register */ 368 ldr r0, VPBDIV_ADR 369 mov r1, #0x01 /* VPB clock is same as process clock */ 370 str r1, [r0] 371#else 372#error No cpu_init_crit() defined for current CPU type 373#endif 374 375#ifdef CONFIG_ARM7_REVD 376 /* set clock speed */ 377 /* !!! we run @ 36 MHz due to a hardware flaw in Rev. D processors */ 378 /* !!! not doing DRAM refresh properly! */ 379 ldr r0, SYSCON3 380 ldr r1, [r0] 381 bic r1, r1, #CLKCTL 382 orr r1, r1, #CLKCTL_36 383 str r1, [r0] 384#endif 385 386#ifndef CONFIG_LPC2292 387 mov ip, lr 388 /* 389 * before relocating, we have to setup RAM timing 390 * because memory timing is board-dependent, you will 391 * find a lowlevel_init.S in your board directory. 392 */ 393 bl lowlevel_init 394 mov lr, ip 395#endif 396 397 mov pc, lr 398 399 400/* 401 ************************************************************************* 402 * 403 * Interrupt handling 404 * 405 ************************************************************************* 406 */ 407 408@ 409@ IRQ stack frame. 410@ 411#define S_FRAME_SIZE 72 412 413#define S_OLD_R0 68 414#define S_PSR 64 415#define S_PC 60 416#define S_LR 56 417#define S_SP 52 418 419#define S_IP 48 420#define S_FP 44 421#define S_R10 40 422#define S_R9 36 423#define S_R8 32 424#define S_R7 28 425#define S_R6 24 426#define S_R5 20 427#define S_R4 16 428#define S_R3 12 429#define S_R2 8 430#define S_R1 4 431#define S_R0 0 432 433#define MODE_SVC 0x13 434#define I_BIT 0x80 435 436/* 437 * use bad_save_user_regs for abort/prefetch/undef/swi ... 438 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 439 */ 440 441 .macro bad_save_user_regs 442 sub sp, sp, #S_FRAME_SIZE 443 stmia sp, {r0 - r12} @ Calling r0-r12 444 add r8, sp, #S_PC 445 446 ldr r2, _armboot_start 447 sub r2, r2, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 448 sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack 449 ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 450 add r0, sp, #S_FRAME_SIZE @ restore sp_SVC 451 452 add r5, sp, #S_SP 453 mov r1, lr 454 stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r 455 mov r0, sp 456 .endm 457 458 .macro irq_save_user_regs 459 sub sp, sp, #S_FRAME_SIZE 460 stmia sp, {r0 - r12} @ Calling r0-r12 461 add r8, sp, #S_PC 462 stmdb r8, {sp, lr}^ @ Calling SP, LR 463 str lr, [r8, #0] @ Save calling PC 464 mrs r6, spsr 465 str r6, [r8, #4] @ Save CPSR 466 str r0, [r8, #8] @ Save OLD_R0 467 mov r0, sp 468 .endm 469 470 .macro irq_restore_user_regs 471 ldmia sp, {r0 - lr}^ @ Calling r0 - lr 472 mov r0, r0 473 ldr lr, [sp, #S_PC] @ Get PC 474 add sp, sp, #S_FRAME_SIZE 475 subs pc, lr, #4 @ return & move spsr_svc into cpsr 476 .endm 477 478 .macro get_bad_stack 479 ldr r13, _armboot_start @ setup our mode stack 480 sub r13, r13, #(CONFIG_STACKSIZE+CONFIG_SYS_MALLOC_LEN) 481 sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abort stack 482 483 str lr, [r13] @ save caller lr / spsr 484 mrs lr, spsr 485 str lr, [r13, #4] 486 487 mov r13, #MODE_SVC @ prepare SVC-Mode 488 msr spsr_c, r13 489 mov lr, pc 490 movs pc, lr 491 .endm 492 493 .macro get_irq_stack @ setup IRQ stack 494 ldr sp, IRQ_STACK_START 495 .endm 496 497 .macro get_fiq_stack @ setup FIQ stack 498 ldr sp, FIQ_STACK_START 499 .endm 500 501/* 502 * exception handlers 503 */ 504 .align 5 505undefined_instruction: 506 get_bad_stack 507 bad_save_user_regs 508 bl do_undefined_instruction 509 510 .align 5 511software_interrupt: 512 get_bad_stack 513 bad_save_user_regs 514 bl do_software_interrupt 515 516 .align 5 517prefetch_abort: 518 get_bad_stack 519 bad_save_user_regs 520 bl do_prefetch_abort 521 522 .align 5 523data_abort: 524 get_bad_stack 525 bad_save_user_regs 526 bl do_data_abort 527 528 .align 5 529not_used: 530 get_bad_stack 531 bad_save_user_regs 532 bl do_not_used 533 534#ifdef CONFIG_USE_IRQ 535 536 .align 5 537irq: 538 get_irq_stack 539 irq_save_user_regs 540 bl do_irq 541 irq_restore_user_regs 542 543 .align 5 544fiq: 545 get_fiq_stack 546 /* someone ought to write a more effiction fiq_save_user_regs */ 547 irq_save_user_regs 548 bl do_fiq 549 irq_restore_user_regs 550 551#else 552 553 .align 5 554irq: 555 get_bad_stack 556 bad_save_user_regs 557 bl do_irq 558 559 .align 5 560fiq: 561 get_bad_stack 562 bad_save_user_regs 563 bl do_fiq 564 565#endif 566 567#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO) 568 .align 5 569.globl reset_cpu 570reset_cpu: 571 mov ip, #0 572 mcr p15, 0, ip, c7, c7, 0 @ invalidate cache 573 mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4) 574 mrc p15, 0, ip, c1, c0, 0 @ get ctrl register 575 bic ip, ip, #0x000f @ ............wcam 576 bic ip, ip, #0x2100 @ ..v....s........ 577 mcr p15, 0, ip, c1, c0, 0 @ ctrl register 578 mov pc, r0 579#elif defined(CONFIG_NETARM) 580 .align 5 581.globl reset_cpu 582reset_cpu: 583 ldr r1, =NETARM_MEM_MODULE_BASE 584 ldr r0, [r1, #+NETARM_MEM_CS0_BASE_ADDR] 585 ldr r1, =0xFFFFF000 586 and r0, r1, r0 587 ldr r1, =(relocate-TEXT_BASE) 588 add r0, r1, r0 589 ldr r4, =NETARM_GEN_MODULE_BASE 590 ldr r1, =NETARM_GEN_SW_SVC_RESETA 591 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] 592 ldr r1, =NETARM_GEN_SW_SVC_RESETB 593 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] 594 ldr r1, =NETARM_GEN_SW_SVC_RESETA 595 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] 596 ldr r1, =NETARM_GEN_SW_SVC_RESETB 597 str r1, [r4, #+NETARM_GEN_SOFTWARE_SERVICE] 598 mov pc, r0 599#elif defined(CONFIG_S3C4510B) 600/* Nothing done here as reseting the CPU is board specific, depending 601 * on external peripherals such as watchdog timers, etc. */ 602#elif defined(CONFIG_INTEGRATOR) && defined(CONFIG_ARCH_INTEGRATOR) 603 /* No specific reset actions for IntegratorAP/CM720T as yet */ 604#elif defined(CONFIG_LPC2292) 605 .align 5 606.globl reset_cpu 607reset_cpu: 608 mov pc, r0 609#else 610#error No reset_cpu() defined for current CPU type 611#endif 612