uboot/cpu/arm720t/start.S
<<
>>
Prefs
   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