(七)u-boot2013.01.01 for s5pv210:《u-boot启动流程》

时间:2023-02-13 19:32:05

转载请注明地址:http://blog.csdn.net/zsy2020314/article/details/9824035

1.关于启动流程

1.1 启动阶段分为3个,bl0,bl1,bl2。下面只是就功能方面对它们做说明,实际设计的时候,也许会对其具体功能做出调整,也就是说,这几个阶段的划分是就功能而言的,不能看得太死。

      bl0:出厂的时候就固化在irom中一段代码,主要负责拷贝8kb的bl1到s5pv210的一个96kb大小内部sram(Internal SRAM)中运行。值得注意的是s5pv210的Internal SRAM支持的bl1的大小可以达到16kb,容量的扩增是为了适应bootloder变得越来复杂而做的。虽然如此,但目前我们制作出来的bl1的大小仍然可以保持在8kb以内,同样能满足需求。

      bl1:u-boot的前8kb代码(s5pv210也支持16kb大小,原因上一点提过了),除了初始化系统时钟和一些基本的硬件外,主要负责完成代码的搬运工作(我设计成搬运bl1+bl2,而不仅仅是bl2),也就是将完整的u-boot代码(bl1+bl2)从nand flash或者mmcSD等的存储器中读取到内存中,然后跳转到内存中运行u-boot。

      bl2:完成全面的硬件初始化和加载OS到内存中,接着运行OS。

上述几个阶段的流程描述在s5pv210_irom_application手册中有详细描述。见下图1:

(七)u-boot2013.01.01 for s5pv210:《u-boot启动流程》

                                                                                           图1

1.2 首先把启动部分的代码分为3部分,以start.S为主,另外还有lowlevel_init.S,mem_setup.S,ctr0.S。

      其中lowlevel_init.S主要是一部分硬件的初始化,尤其是系统时钟和DRAM的初始化。如果u-boot一旦被搬运到内存中运行,那么是必须要跳过时钟和DRAM的初始化的,因为这在搬运之前已经做过了。并且如果代码在内存中运行的时侯你却去初始化DRAM,那必然导致崩溃!

     mem_setup.S:DRAM初始化代码和MMU相关代码放在这个文件中。

     ctr0.S:u-boot自带的代码文件,存放汇编函数main。

1.3 启动代码相关的几个文件在u-boot中的路径

    start.S:            /arch/arm/cpu/armv7/start.S (需要自己修改)

    lowlevel_init.S:/board/samsung/zsy210/ lowlevel_init.S  (需要自己修改)

    mem_setup.S:   /board/samsung/zsy210/ mem_setup.S   (u-boot没有,需要自己添加)

    ctr0.S:            /arch/arm/lib/ctr0.S  (u-boot自带,一般不需要修改)


2. 启动过程原理

      必须要明白的一点是,当代码从存储介质(nand flash,SD,norflash,onenand等)中搬运到了DRAM中后随即会跳转到内存中运行u-boot,接着会有一个重定位(relocate_code)的过程,relocate_code子函数在start.S中,而给relocate_code子函数传参数的是crt0.S中的main子函数。当判断到当前u-boot在内存的低地址处,那么relocate_code就会工作,把u-boot代码从低地址处再搬运到内存地址的顶端,然后跳转到新的位置去继续运行u-boot。而搬运的目标地址是在board_init_f()函数(此函数在/arch/arm/lib/board.c中)中计算出来的,见图2。

(七)u-boot2013.01.01 for s5pv210:《u-boot启动流程》

                                                                                        图2


       下面,以start.S为主线,画出了其程序流程图,图中同样也表现出启动的整个流程和启动代码文件间的组织关系。所以后面直接贴出start.S的完整代码,大家结合流程图相信都可以看明白,至于逐句汇编的分析不是本文的重点。见图3.

(七)u-boot2013.01.01 for s5pv210:《u-boot启动流程》

                                                                                    图3


3. start.S   lowlevel_init.S  mem_setup.S  crt0.S的完整代码。


start.S的完整代码:

/*
* armboot - Startup Code for OMAP3530/ARM Cortex CPU-core
*
* Copyright (c) 2004Texas Instruments <r-woodruff2@ti.com>
*
* Copyright (c) 2001Marius Gröger <mag@sysgo.de>
* Copyright (c) 2002Alex Züpke <azu@sysgo.de>
* Copyright (c) 2002Gary Jennejohn <garyj@denx.de>
* Copyright (c) 2003Richard Woodruff <r-woodruff2@ti.com>
* Copyright (c) 2003Kshitij <kshitij@ti.com>
* Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <asm-offsets.h>
#include <config.h>
#include <version.h>
#include <asm/system.h>
#include <linux/linkage.h>
#include <s5pv210.h>

#ifndef CONFIG_ENABLE_MMU
#ifndef CONFIG_PHY_UBOOT_BASE
#define CONFIG_PHY_UBOOT_BASECONFIG_UBOOT_BASE
#endif /* CONFIG_PHY_UBOOT_BASE */
#endif /* CONFIG_ENABLE_MMU */


.globl _start
_start: breset
ldrpc, _undefined_instruction
ldrpc, _software_interrupt
ldrpc, _prefetch_abort
ldrpc, _data_abort
ldrpc, _not_used
ldrpc, _irq
ldrpc, _fiq
#ifdef CONFIG_SPL_BUILD
_undefined_instruction: .word _undefined_instruction
_software_interrupt:.word _software_interrupt
_prefetch_abort:.word _prefetch_abort
_data_abort:.word _data_abort
_not_used:.word _not_used
_irq:.word _irq
_fiq:.word _fiq
_pad:.word 0x12345678 /* now 16*4=64 */
#else
_undefined_instruction: .word undefined_instruction
_software_interrupt:.word software_interrupt
_prefetch_abort:.word prefetch_abort
_data_abort:.word data_abort
_not_used:.word not_used
_irq:.word irq
_fiq:.word fiq
_pad:.word 0x12345678 /* now 16*4=64 */
#endif/* CONFIG_SPL_BUILD */

.global _end_vect
_end_vect:

.balignl 16,0xdeadbeef
/*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*************************************************************************/

.globl _TEXT_BASE
_TEXT_BASE:
.wordCONFIG_SYS_TEXT_BASE
/*
* Below variable is very important because we use MMU in U-Boot.
* Without it, we cannot run code correctly before MMU is ON.
* by scsuh.
*/
.globl _TEXT_PHY_BASE
_TEXT_PHY_BASE:
.wordCONFIG_PHY_UBOOT_BASE

/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start

.global_image_copy_end_ofs
_image_copy_end_ofs:
.word __image_copy_end - _start

.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end__ - _start

.globl _end_ofs
_end_ofs:
.word _end - _start

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif

/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word0x0badc0de

/*
* the actual reset code
*/

reset:
blsave_boot_params

/*
* set the cpu to SVC32 mode and IRQ & FIQ disable
*/
msrcpsr_c, #0xd3@ I & F disable, Mode: 0x13 - SVC

/*
* Setup vector:
* (OMAP4 spl TEXT_BASE is not 32 byte aligned.
* Continue to use ROM code vector only in OMAP4 spl)
*/
#if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))
/* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */
mrcp15, 0, r0, c1, c0, 0@ Read CP15 SCTRL Register
bicr0, #CR_V@ V = 0
mcrp15, 0, r0, c1, c0, 0@ Write CP15 SCTRL Register

/* Set vector address in CP15 VBAR register */
ldrr0, =_start
mcrp15, 0, r0, c12, c0, 0@Set VBAR
#endif
/***************************** zsy add 2013-3-14 *****************************/
#ifndef CONFIG_EVT1
bldisable_l2cache

movr0, #0x0@
movr1, #0x0@ i
movr3, #0x0
movr4, #0x0
lp1:
movr2, #0x0@ j
lp2:
movr3, r1, LSL #29@ r3 = r1(i) <<29
movr4, r2, LSL #6@ r4 = r2(j) <<6
orrr4, r4, #0x2@ r3 = (i<<29)|(j<<6)|(1<<1)
orrr3, r3, r4
movr0, r3@ r0 = r3
blCoInvalidateDCacheIndex
addr2, #0x1@ r2(j)++
cmpr2, #1024@ r2 < 1024
bnelp2@ jump to lp2
addr1, #0x1@ r1(i)++
cmpr1, #8@ r1(i) < 8
bnelp1@ jump to lp1

blset_l2cache_auxctrl

blenable_l2cache
#endif

bldisable_l2cache

blset_l2cache_auxctrl_cycle

blenable_l2cache

blzsy210_iic_pm_open

/************************** end of zsy add 2013-3-14 ****************************/
/* the mask ROM code should have PLL and others stable */
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
blcpu_init_cp15
blcpu_init_crit
#endif
/*************************** zsy add 2013-3-14 ********************************/
/* 读取启动模式信息 */
ldrr0, =PRO_ID_BASE
ldrr1, [r0,#OMR_OFFSET]
bicr2, r1, #0xffffffc1

/* NAND BOOT */
cmpr2, #0x0@ 512B 4-cycle
moveqr3, #BOOT_NAND

cmpr2, #0x2@ 2KB 5-cycle
moveqr3, #BOOT_NAND

cmpr2, #0x4@ 4KB 5-cycle8-bit ECC
moveqr3, #BOOT_NAND

cmpr2, #0x6@ 4KB 5-cycle16-bit ECC
moveqr3, #BOOT_NAND

cmpr2, #0x8@ OneNAND Mux
moveqr3, #BOOT_ONENAND

/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD

/* NOR BOOT */
cmp r2, #0x14
moveq r3, #BOOT_NOR

/* Uart BOOTONG failed */
cmpr2, #(0x1<<4)
moveqr3, #BOOT_SEC_DEV

ldrr0, =INF_REG_BASE
strr3, [r0, #INF_REG3_OFFSET]

ldrr0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldrr1, =0x00005301 /* PS_HOLD output high*/
strr1, [r0]

/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
ldrsp, =(CONFIG_SYS_INIT_SP_ADDR)
bicsp, sp, #7 /* 8-byte alignment for ABI compliance */
ldrr0,=0x00000000

ldrr1, =0xff000fff
bicr2, pc, r1/* r0 <- current base addr of code */
ldrr3, _TEXT_BASE/* r1 <- original base addr in ram */
bicr3, r3, r1/* r0 <- current base addr of code */
cmp r2, r3 /* compare r0, r1 */
beq run_in_ram/* r0 == r1 then skip sdram init */

#if defined(CONFIG_EVT1)
/* If BL1 was copied from SD/MMC CH2 */
ldrr0, =0xD0037488
ldrr1, [r0]
ldrr2, =0xEB200000
cmpr1, r2
beqmmcsd_boot
#endif

ldrr0, =INF_REG_BASE
ldrr1, [r0, #INF_REG3_OFFSET]
cmpr1, #BOOT_NAND/* 0x0 => boot device is nand */
beqnand_boot
cmpr1, #BOOT_ONENAND/* 0x1 => boot device is onenand */
beqonenand_boot
cmpr1, #BOOT_MMCSD
beqmmcsd_boot
cmpr1, #BOOT_NOR
beqnor_boot
cmpr1, #BOOT_SEC_DEV
beqmmcsd_boot

nand_boot:
bl ledon_1
blboard_init_f_nand

mmcsd_boot:
bl ledon_1
blboard_init_f_movi

nor_boot:
bl ledon
onenand_boot:
bl ledon

/*************************************************************************
*
* after_copy
*
*************************************************************************/
run_in_ram:

#if defined(CONFIG_ENABLE_MMU)
enable_mmu:
/* enable domain access */
ldrr5, =0x0000ffff
mcrp15, 0, r5, c3, c0, 0@load domain access register

/* Set the TTB register */
ldrr0, _mmu_table_base
ldrr1, =CONFIG_PHY_UBOOT_BASE
ldrr2, =0xfff00000
bicr0, r0, r2
orrr1, r0, r1
mcrp15, 0, r1, c2, c0, 0

/* Enable the MMU */
mmu_on:
mrcp15, 0, r0, c1, c0, 0
orrr0, r0, #1
mcrp15, 0, r0, c1, c0, 0
nop
nop
nop
nop
#endif
bl ledon_2
bl _main
/************************** end of zsy add 2013-3-14 ****************************/
/*------------------------------------------------------------------------------*/

#ifndef CONFIG_SPL_BUILD
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
ENTRY(relocate_code)
movr4, r0/* save addr_sp */
movr5, r1/* save addr of gd */
movr6, r2/* save addr of destination */

adrr0, _start
cmpr0, r6
moveqr9, #0/* no relocation. relocation offset(r9) = 0 */
beqrelocate_done/* skip relocation */
movr1, r6/* r1 <- scratch for copy_loop */
ldrr3, _image_copy_end_ofs
addr2, r0, r3/* r2 <- source end address */

copy_loop:
ldmiar0!, {r9-r10}/* copy from source address [r0] */
stmiar1!, {r9-r10}/* copy to target address [r1] */
cmpr0, r2/* until source end address [r2] */
blocopy_loop

/*
* fix .rel.dyn relocations
*/
ldrr0, _TEXT_BASE/* r0 <- Text base */
subr9, r6, r0/* r9 <- relocation offset */
ldrr10, _dynsym_start_ofs/* r10 <- sym table ofs */
addr10, r10, r0/* r10 <- sym table in FLASH */
ldrr2, _rel_dyn_start_ofs/* r2 <- rel dyn start ofs */
addr2, r2, r0/* r2 <- rel dyn start in FLASH */
ldrr3, _rel_dyn_end_ofs/* r3 <- rel dyn end ofs */
addr3, r3, r0/* r3 <- rel dyn end in FLASH */
fixloop:
ldrr0, [r2]/* r0 <- location to fix up, IN FLASH! */
addr0, r0, r9/* r0 <- location to fix up in RAM */
ldrr1, [r2, #4]
andr7, r1, #0xff
cmpr7, #23/* relative fixup? */
beqfixrel
cmpr7, #2/* absolute fixup? */
beqfixabs
/* ignore unknown type of fixup */
bfixnext
fixabs:
/* absolute fix: set location to (offset) symbol value */
movr1, r1, LSR #4/* r1 <- symbol index in .dynsym */
addr1, r10, r1/* r1 <- address of symbol in table */
ldrr1, [r1, #4]/* r1 <- symbol value */
addr1, r1, r9/* r1 <- relocated sym addr */
bfixnext
fixrel:
/* relative fix: increase location by offset */
ldrr1, [r0]
addr1, r1, r9
fixnext:
strr1, [r0]
addr2, r2, #8/* each rel.dyn entry is 8 bytes */
cmpr2, r3
blofixloop

relocate_done:

bxlr

_rel_dyn_start_ofs:
.word __rel_dyn_start - _start
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start
_dynsym_start_ofs:
.word __dynsym_start - _start
ENDPROC(relocate_code)

#endif

ENTRY(c_runtime_cpu_setup)
/*
* If I-cache is enabled invalidate it
*/
#ifndef CONFIG_SYS_ICACHE_OFF
mcrp15, 0, r0, c7, c5, 0@ invalidate icache
mcr p15, 0, r0, c7, c10, 4@ DSB
mcr p15, 0, r0, c7, c5, 4@ ISB
#endif
/*
* Move vector table
*/
#if !defined(CONFIG_TEGRA20)
/* Set vector address in CP15 VBAR register */
ldr r0, =_start
add r0, r0, r9
mcr p15, 0, r0, c12, c0, 0 @Set VBAR
#endif /* !Tegra20 */

bxlr

ENDPROC(c_runtime_cpu_setup)

/*************************************************************************
*
* void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3)
*__attribute__((weak));
*
* Stack pointer is not yet initialized at this moment
* Don't save anything to stack even if compiled with -O0
*
*************************************************************************/
ENTRY(save_boot_params)
bxlr@ back to my caller
ENDPROC(save_boot_params)
.weaksave_boot_params

/*************************************************************************
*
* cpu_init_cp15
*
* Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless
* CONFIG_SYS_ICACHE_OFF is defined.
*
*************************************************************************/
ENTRY(cpu_init_cp15)

/*
* Invalidate L1 I/D
*/
movr0, #0 @ set up for MCR
mcrp15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcrp15, 0, r0, c7, c5, 0 @ invalidate icache

/*
* disable MMU stuff and caches
*/
mrcp15, 0, r0, c1, c0, 0
bicr0, r0, #0x00002000 @ clear bits 13 (--V-)
bicr0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orrr0, r0, #0x00000002 @ set bit 1 (--A-) Align
orrr0, r0, #0x00000800 @ set bit 12 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0

movpc, lr@ back to my caller
ENDPROC(cpu_init_cp15)

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
/*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************/
ENTRY(cpu_init_crit)
/*
* Jump to board specific initialization...
* The Mask ROM will have already initialized
* basic memory. Go here to bump up clock rate and handle
* wake up conditions.
*/
blowlevel_init@ go setup pll,mux,memory
ENDPROC(cpu_init_crit)
#endif

/*************************************************************************
*
* zsy210_iic_pm_open
*
*************************************************************************/
ENTRY(zsy210_iic_pm_open)
/*电源管理,保持供电*/
#ifdef CONFIG_ZSY210_IIC_PM_CHIP
/* PS_HOLD(GPJ2_5) 设置为高点平 */
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x00100000
strr1, [r0, #GPJ2CON_OFFSET]

ldrr1, =0x0400
strr1, [r0, #GPJ2PUD_OFFSET]

ldrr1, =0x20
strr1, [r0, #GPJ2DAT_OFFSET]
#endif /* CONFIG_ZSY210_IIC_PM_CHIP */
movpc, lr@ back to my caller
ENDPROC(zsy210_iic_pm_open)


#if defined(CONFIG_ENABLE_MMU)
_mmu_table_base:
.word mmu_table
#endif


/*
* we assume that cache operation is done before. (eg. cleanup_before_linux())
* actually, we don't need to do anything about cache if not use d-cache in U-Boot
* So, in this function we clean only MMU. by scsuh
*
* voidtheLastJump(void *kernel, int arch_num, uint boot_params);
*/
#if defined(CONFIG_ENABLE_MMU)
.globl theLastJump
theLastJump:
movr9, r0
ldrr3, =0xfff00000
ldrr4, _TEXT_PHY_BASE
adrr5, phy_last_jump
bicr5, r5, r3
orrr5, r5, r4
movpc, r5
phy_last_jump:
/*
* disable MMU stuff
*/
mrcp15, 0, r0, c1, c0, 0
bicr0, r0, #0x00002300/* clear bits 13, 9:8 (--V- --RS) */
bicr0, r0, #0x00000087/* clear bits 7, 2:0 (B--- -CAM) */
orrr0, r0, #0x00000002/* set bit 2 (A) Align */
orrr0, r0, #0x00001000/* set bit 12 (I) I-Cache */
mcrp15, 0, r0, c1, c0, 0

mcrp15, 0, r0, c8, c7, 0/* flush v4 TLB */

movr0, #0
movpc, r9
#endif



#ifndef CONFIG_SPL_BUILD
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE72

#define S_OLD_R068
#define S_PSR64
#define S_PC60
#define S_LR56
#define S_SP52

#define S_IP48
#define S_FP44
#define S_R1040
#define S_R936
#define S_R832
#define S_R728
#define S_R624
#define S_R520
#define S_R416
#define S_R312
#define S_R28
#define S_R14
#define S_R00

#define MODE_SVC 0x13
#define I_BIT 0x80

/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/

.macrobad_save_user_regs
subsp, sp, #S_FRAME_SIZE@ carve out a frame on current
@ user stack
stmiasp, {r0 - r12}@ Save user registers (now in
@ svc mode) r0-r12
ldrr2, IRQ_STACK_START_IN@ set base 2 words into abort
@ stack
ldmiar2, {r2 - r3}@ get values for "aborted" pc
@ and cpsr (into parm regs)
addr0, sp, #S_FRAME_SIZE@ grab pointer to old stack

addr5, sp, #S_SP
movr1, lr
stmiar5, {r0 - r3}@ save sp_SVC, lr_SVC, pc, cpsr
movr0, sp@ save current stack into r0
@ (param register)
.endm

.macroirq_save_user_regs
subsp, sp, #S_FRAME_SIZE
stmiasp, {r0 - r12}@ Calling r0-r12
addr8, sp, #S_PC@ !! R8 NEEDS to be saved !!
@ a reserved stack spot would
@ be good.
stmdbr8, {sp, lr}^@ Calling SP, LR
strlr, [r8, #0]@ Save calling PC
mrsr6, spsr
strr6, [r8, #4]@ Save CPSR
strr0, [r8, #8]@ Save OLD_R0
movr0, sp
.endm

.macroirq_restore_user_regs
ldmiasp, {r0 - lr}^@ Calling r0 - lr
movr0, r0
ldrlr, [sp, #S_PC]@ Get PC
addsp, sp, #S_FRAME_SIZE
subspc, lr, #4@ return & move spsr_svc into
@ cpsr
.endm

.macro get_bad_stack
ldrr13, IRQ_STACK_START_IN@ setup our mode stack (enter
@ in banked mode)

strlr, [r13]@ save caller lr in position 0
@ of saved stack
mrslr, spsr@ get the spsr
strlr, [r13, #4]@ save spsr in position 1 of
@ saved stack

movr13, #MODE_SVC@ prepare SVC-Mode
@ msrspsr_c, r13
msrspsr, r13@ switch modes, make sure
@ moves will execute
movlr, pc@ capture return pc
movspc, lr@ jump to next instruction &
@ switch modes.
.endm

.macro get_bad_stack_swi
subr13, r13, #4@ space on current stack for
@ scratch reg.
strr0, [r13]@ save R0's value.
ldrr0, IRQ_STACK_START_IN@ get data regions start
@ spots for abort stack
strlr, [r0]@ save caller lr in position 0
@ of saved stack
mrsr0, spsr@ get the spsr
strlr, [r0, #4]@ save spsr in position 1 of
@ saved stack
ldrr0, [r13]@ restore r0
addr13, r13, #4@ pop stack entry
.endm

.macro get_irq_stack@ setup IRQ stack
ldrsp, IRQ_STACK_START
.endm

.macro get_fiq_stack@ setup FIQ stack
ldrsp, FIQ_STACK_START
.endm

/*
* exception handlers
*/
.align5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bldo_undefined_instruction

.align5
software_interrupt:
get_bad_stack_swi
bad_save_user_regs
bldo_software_interrupt

.align5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bldo_prefetch_abort

.align5
data_abort:
get_bad_stack
bad_save_user_regs
bldo_data_abort

.align5
not_used:
get_bad_stack
bad_save_user_regs
bldo_not_used

#ifdef CONFIG_USE_IRQ

.align5
irq:
get_irq_stack
irq_save_user_regs
bldo_irq
irq_restore_user_regs

.align5
fiq:
get_fiq_stack
/* someone ought to write a more effective fiq_save_user_regs */
irq_save_user_regs
bldo_fiq
irq_restore_user_regs

#else

.align5
irq:
get_bad_stack
bad_save_user_regs
bldo_irq

.align5
fiq:
get_bad_stack
bad_save_user_regs
bldo_fiq

#endif /* CONFIG_USE_IRQ */
#endif /* CONFIG_SPL_BUILD */







lowlevel_init.S的完整代码:

/*
* Copyright (C) 2009 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
* Minkyu Kang <mk7.kang@samsung.com>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <config.h>
#include <version.h>
#include <asm/arch/cpu.h>
#include <asm/arch/power.h>
#include <s5pv210.h>
#include "zsy210_val.h"
/*
* Register usages:
*
* r5 has zero always
*/

_TEXT_BASE:
.wordCONFIG_SYS_TEXT_BASE

.globl lowlevel_init
lowlevel_init:
movr9, lr

/* check reset status */
ldrr0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
ldrr1, [r0]
bicr1, r1, #0xfff6ffff
cmpr1, #0x10000
beqwakeup_reset_pre
cmpr1, #0x80000
beqwakeup_reset_from_didle

/* IO Retention release */
ldrr0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
ldrr1, [r0]
ldrr2, =IO_RET_REL
orrr1, r1, r2
strr1, [r0]

/* Disable Watchdog */
ldrr0, =ELFIN_WATCHDOG_BASE/* 0xE2700000 */
movr1, #0
strr1, [r0]
/* SRAM(2MB) init for SMDKC110 */
/* GPJ1 SROM_ADDR_16to21 */
ldrr0, =ELFIN_GPIO_BASE

ldrr1, [r0, #GPJ1CON_OFFSET]
bicr1, r1, #0xFFFFFF
ldrr2, =0x444444
orrr1, r1, r2
strr1, [r0, #GPJ1CON_OFFSET]

ldrr1, [r0, #GPJ1PUD_OFFSET]
ldrr2, =0x3ff
bicr1, r1, r2
strr1, [r0, #GPJ1PUD_OFFSET]

/* GPJ4 SROM_ADDR_16to21 */
ldrr1, [r0, #GPJ4CON_OFFSET]
bicr1, r1, #(0xf<<16)
ldrr2, =(0x4<<16)
orrr1, r1, r2
strr1, [r0, #GPJ4CON_OFFSET]

ldrr1, [r0, #GPJ4PUD_OFFSET]
ldrr2, =(0x3<<8)
bicr1, r1, r2
strr1, [r0, #GPJ4PUD_OFFSET]

/* CS0 - 16bit sram, enable nBE, Byte base address */
ldrr0, =ELFIN_SROM_BASE/* 0xE8000000 */
movr1, #0x1
strr1, [r0]

/* PS_HOLD pin(GPH0_0) set to high */
ldrr0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
ldrr1, [r0]
orrr1, r1, #0x300
orrr1, r1, #0x1
strr1, [r0]

/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
* is running in ram.
*/
ldrr0, =0xff000fff
bicr1, pc, r0/* r0 <- current base addr of code */
ldrr2, _TEXT_BASE/* r1 <- original base addr in ram */
bicr2, r2, r0/* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq 1f/* r0 == r1 then skip sdram init */

/* init PMIC chip */
#ifdef CONFIG_ZSY210_IIC_PM_CHIP
bl PMIC_InitIp
#endif

/* init system clock */
bl system_clock_init
/* Memory initialize */
bl mem_ctrl_asm_init

1:
/* for UART */
bl uart_asm_init

/* for TZPC */
bl tzpc_asm_init

#if defined(CONFIG_NAND)
/* simple init for NAND */
bl nand_asm_init
#endif
/* check reset status */

ldrr0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
ldrr1, [r0]
bicr1, r1, #0xfffeffff
cmpr1, #0x10000
beqwakeup_reset_pre

/* ABB disable */
ldrr0, =0xE010C300
orrr1, r1, #(0x1<<23)
strr1, [r0]

/* Print 'K' */
ldrr0, =ELFIN_UART_CONSOLE_BASE
ldrr1, =0x4b4b4b4b
strr1, [r0, #UTXH_OFFSET]

movlr, r9
movpc, lr


/*
* uart_asm_init: Initialize UART's pins
*/
uart_asm_init:
/* set GPIO(GPA) to enable UART */
@ GPIO setting for UART
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x22222222
str r1, [r0, #GPA0CON_OFFSET]

ldr r1, =0x2222
str r1, [r0, #GPA1CON_OFFSET]

ldrr0, =ELFIN_UART_CONSOLE_BASE@0xEC000000
movr1, #0x0
strr1, [r0, #UFCON_OFFSET]
strr1, [r0, #UMCON_OFFSET]

movr1, #0x3
strr1, [r0, #ULCON_OFFSET]

ldrr1, =0x3c5
strr1, [r0, #UCON_OFFSET]

ldrr1, =UART_UBRDIV_VAL
strr1, [r0, #UBRDIV_OFFSET]

ldrr1, =UART_UDIVSLOT_VAL
strr1, [r0, #UDIVSLOT_OFFSET]

ldrr1, =0x4f4f4f4f
strr1, [r0, #UTXH_OFFSET]@'O'

movpc, lr

/*
* tzpc_asm_init: Initialize TZPC
*/
tzpc_asm_init:

ldrr0, =ELFIN_TZPC0_BASE
movr1, #0x0
strr1, [r0]
movr1, #0xff
strr1, [r0, #TZPC_DECPROT0SET_OFFSET]
strr1, [r0, #TZPC_DECPROT1SET_OFFSET]
strr1, [r0, #TZPC_DECPROT2SET_OFFSET]

ldr r0, =ELFIN_TZPC1_BASE
strr1, [r0, #TZPC_DECPROT0SET_OFFSET]
strr1, [r0, #TZPC_DECPROT1SET_OFFSET]
strr1, [r0, #TZPC_DECPROT2SET_OFFSET]

ldrr0, =ELFIN_TZPC2_BASE
strr1, [r0, #TZPC_DECPROT0SET_OFFSET]
strr1, [r0, #TZPC_DECPROT1SET_OFFSET]
strr1, [r0, #TZPC_DECPROT2SET_OFFSET]
strr1, [r0, #TZPC_DECPROT3SET_OFFSET]

ldrr0, =ELFIN_TZPC3_BASE
strr1, [r0, #TZPC_DECPROT0SET_OFFSET]
strr1, [r0, #TZPC_DECPROT1SET_OFFSET]
strr1, [r0, #TZPC_DECPROT2SET_OFFSET]

movpc, lr


/******************** zsy add 2013.3.14 *******************************/
/*
* Nand Interface Init for SMDKC110
*/
nand_asm_init:

/* Setting GPIO for NAND */
/* This setting is NAND initialze code at booting time in iROM. */

ldrr0, =ELFIN_GPIO_BASE

ldrr1, [r0, #MP01CON_OFFSET]
bicr1, r1, #(0xf<<8)
orrr1, r1, #(0x3<<8)
strr1, [r0, #MP01CON_OFFSET]

ldrr1, [r0, #MP01PUD_OFFSET]
bicr1, r1, #(0x3<<4)
strr1, [r0, #MP01PUD_OFFSET]

ldrr1, [r0, #MP03CON_OFFSET]
bicr1, r1, #0xFFFFFF
ldrr2, =0x22222222
orrr1, r1, r2
strr1, [r0, #MP03CON_OFFSET]

ldrr1, [r0, #MP03PUD_OFFSET]
ldrr2, =0x3fff
bicr1, r1, r2
strr1, [r0, #MP03PUD_OFFSET]

ldrr0, =ELFIN_NAND_BASE

ldrr1, [r0, #NFCONF_OFFSET]
ldrr2, =0x777F
bicr1, r1, r2
ldrr2, =NFCONF_VAL
orrr1, r1, r2
strr1, [r0, #NFCONF_OFFSET]

ldrr1, [r0, #NFCONT_OFFSET]
ldrr2, =0x707C7
bicr1, r1, r2
ldrr2, =NFCONT_VAL
orrr1, r1, r2
strr1, [r0, #NFCONT_OFFSET]

ldrr1, [r0, #NFCONF_OFFSET]
orrr1, r1, #0x70
orrr1, r1, #0x7700
strr1, [r0, #NFCONF_OFFSET]

ldrr1, [r0, #NFCONT_OFFSET]
orrr1, r1, #0x03
strr1, [r0, #NFCONT_OFFSET]

movpc, lr


/******************** zsy add 2013.3.14 *******************************/
wakeup_reset_from_didle:
/* Wait when APLL is locked */
ldrr0, =ELFIN_CLOCK_POWER_BASE
lockloop:
ldrr1, [r0, #APLL_CON0_OFFSET]
andr1, r1, #(1<<29)
cmpr1, #(1<<29)
bne lockloop
beqexit_wakeup

wakeup_reset_pre:
mrcp15, 0, r1, c1, c0, 1@Read CP15 Auxiliary control register
andr1, r1, #0x80000000@Check L2RD is disable or not
cmpr1, #0x80000000
bnewakeup_reset@if L2RD is not disable jump to wakeup_reset

bldisable_l2cache
blv7_flush_dcache_all
/* L2 cache enable at sleep.S of kernel
* blenable_l2cache
*/
#ifdef CONFIG_ZSY210
blenable_l2cache
#endif

wakeup_reset:
/* init system clock */
bl system_clock_init
bl mem_ctrl_asm_init
bl tzpc_asm_init
#if defined(CONFIG_NAND)
bl nand_asm_init
#endif

exit_wakeup:
/*Load return address and jump to kernel*/
ldrr0, =(INF_REG_BASE+INF_REG0_OFFSET)
ldrr1, [r0]/* r1 = physical address of s5pc110_cpu_resume function*/

movpc, r1/*Jump to kernel */
nop
nop

/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
system_clock_init:

ldrr0, =ELFIN_CLOCK_POWER_BASE@0xe0100000

/* Set Mux to FIN */
ldrr1, =0x0
strr1, [r0, #CLK_SRC0_OFFSET]

ldrr1,=APLL_LOCKTIME_VAL
strr1,[r0, #APLL_LOCK_OFFSET]

/* Disable PLL */
#if defined(CONFIG_CHECK_MPLL_LOCK)
retryloop:
#endif
ldrr1, =0x0
strr1, [r0, #APLL_CON0_OFFSET]
ldrr1, =0x0
strr1, [r0, #MPLL_CON_OFFSET]

ldrr1, =0x0
strr1, [r0, #MPLL_CON_OFFSET]

ldr r1, [r0, #CLK_DIV0_OFFSET]
ldrr2, =CLK_DIV0_MASK
bicr1, r1, r2

ldrr2, =CLK_DIV0_VAL
orrr1, r1, r2
strr1, [r0, #CLK_DIV0_OFFSET]

ldrr1, =APLL_VAL
strr1, [r0, #APLL_CON0_OFFSET]

ldrr1, =MPLL_VAL
strr1, [r0, #MPLL_CON_OFFSET]

ldrr1, =VPLL_VAL
strr1, [r0, #VPLL_CON_OFFSET]
#if defined(CONFIG_EVT1)
ldrr1, =AFC_ON
strr1, [r0, #APLL_CON1_OFFSET]
#endif
movr1, #0x10000
1:subsr1, r1, #1
bne1b

#if defined(CONFIG_CHECK_MPLL_LOCK)
/* MPLL software workaround */
ldrr1, [r0, #MPLL_CON_OFFSET]
orr r1, r1, #(1<<28)
strr1, [r0, #MPLL_CON_OFFSET]

movr1, #0x100
1:subsr1, r1, #1
bne1b

ldrr1, [r0, #MPLL_CON_OFFSET]
andr1, r1, #(1<<29)
cmpr1, #(1<<29)
bne retryloop

/* H/W lock detect disable */
ldrr1, [r0, #MPLL_CON_OFFSET]
bic r1, r1, #(1<<28)
strr1, [r0, #MPLL_CON_OFFSET]
#endif

ldrr1, [r0, #CLK_SRC0_OFFSET]
ldrr2, =0x10001111
orrr1, r1, r2
strr1, [r0, #CLK_SRC0_OFFSET]

#if defined(CONFIG_MCP_AC)

/* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */
ldrr1, [r0, #CLK_SRC6_OFFSET]
bicr1, r1, #(0x3<<24)
orrr1, r1, #0x01000000
strr1, [r0, #CLK_SRC6_OFFSET]

/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldrr1, [r0, #CLK_DIV6_OFFSET]
bicr1, r1, #(0xF<<28)
bicr1, r1, #(0x7<<12)@; ONENAND_RATIO: 0
orrr1, r1, #0x30000000
strr1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_N)
/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldrr1, [r0, #CLK_SRC6_OFFSET]
movr1, #0x00000000
strr1, [r0, #CLK_SRC6_OFFSET]

/* CLK_DIV6[31:28] -> 0=1/1 */
ldrr1, [r0, #CLK_DIV6_OFFSET]
movr1, #0x00000000
strr1, [r0, #CLK_DIV6_OFFSET]


#elif defined (CONFIG_MCP_H)

/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldrr1, [r0, #CLK_SRC6_OFFSET]
bicr1, r1, #(0x3<<24)
orrr1, r1, #0x00000000
strr1, [r0, #CLK_SRC6_OFFSET]

/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldrr1, [r0, #CLK_DIV6_OFFSET]
bicr1, r1, #(0xF<<28)
bicr1, r1, #(0x7<<12)@; ONENAND_RATIO: 0
orrr1, r1, #0x00000000
strr1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D)

/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldrr1, [r0, #CLK_SRC6_OFFSET]
bicr1, r1, #(0x3<<24)
orrr1, r1, #0x01000000
strr1, [r0, #CLK_SRC6_OFFSET]

/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldrr1, [r0, #CLK_DIV6_OFFSET]
bicr1, r1, #(0xF<<28)
bicr1, r1, #(0x7<<12)@; ONENAND_RATIO: 0
orrr1, r1, #0x30000000
strr1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_SINGLE)

/* CLK_DIV6 */
ldrr1, [r0, #CLK_DIV6_OFFSET]
bicr1, r1, #(0x7<<12)@; ONENAND_RATIO: 0
strr1, [r0, #CLK_DIV6_OFFSET]

#endif
movpc, lr




#ifdef CONFIG_ENABLE_MMU

#ifdef CONFIG_MCP_SINGLE
/*
* MMU Table for SMDKC110
* 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed
* 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF
* 0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF
* 0xC800_0000 -- 0xDFFF_FFFF => Not Allowed
* 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF
*/

/* form a first-level section entry */
.macro FL_SECTION_ENTRY base,ap,d,c,b
.word (\base << 20) | (\ap << 10) | \
(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
.section .mmudata, "a"
.align 14
// the following alignment creates the mmu table at address 0x4000.
.globl mmu_table
mmu_table:
.set __base,0
// Access for iRAM
.rept 0x100
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

// Not Allowed
.rept 0x200 - 0x100
.word 0x00000000
.endr
#ifdef CONFIG_ZSY10_1G
.set __base,0x200
// should be accessed
.rept 0x600 - 0x200
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
#else
.set __base,0x200
// should be accessed
.rept 0x600 - 0x200
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
/*
.set __base,0x400
// should be accessed
.rept 0x500 - 0x400
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr*/
#endif /* CONFIG_ZSY10_1G */
.rept 0x800 - 0x600
.word 0x00000000
.endr


.set __base,0x800
// should be accessed
.rept 0xb00 - 0x800
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

/*.rept 0xc00 - 0xb00
.word 0x00000000
.endr */

.set __base,0xB00
.rept 0xc00 - 0xb00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
#ifdef CONFIG_ZSY10_1G
.set __base,0x200
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

// access is not allowed.
@.rept 0xD00 - 0xC80
@.word 0x00000000
@.endr

.set __base,0xD00
// 1:1 mapping for debugging with non-cacheable
.rept 0x1000 - 0xD00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
#else
.set __base,0x200
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

// access is not allowed.
@.rept 0xD00 - 0xC80
@.word 0x00000000
@.endr

.set __base,0xD00
// 1:1 mapping for debugging with non-cacheable
.rept 0x1000 - 0xD00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
#endif /* CONFIG_ZSY10_1G */
#else// CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B

/*
* MMU Table for SMDKC110
* 0x0000_0000 -- 0xBFFF_FFFF => Not Allowed
* 0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF
* 0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF
* 0xC800_0000 -- 0xDFFF_FFFF => Not Allowed
* 0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF
*/

/* form a first-level section entry */
.macro FL_SECTION_ENTRY base,ap,d,c,b
.word (\base << 20) | (\ap << 10) | \
(\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)
.endm
.section .mmudata, "a"
.align 14
// the following alignment creates the mmu table at address 0x4000.
.globl mmu_table
mmu_table:
.set __base,0
// Access for iRAM
.rept 0x100
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

// Not Allowed
.rept 0x300 - 0x100
.word 0x00000000
.endr

#if defined(CONFIG_MCP_N)
.set __base,0x300
// should be accessed
.rept 0x400 - 0x300
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
#else
.set __base,0x300
// should be accessed
.rept 0x350 - 0x300
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

// Not Allowed
.rept 0x400 - 0x350
.word 0x00000000
.endr
#endif

.set __base,0x400
// should be accessed
.rept 0x500 - 0x400
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

.rept 0x800 - 0x500
.word 0x00000000
.endr

.set __base,0x800
// should be accessed
.rept 0xb00 - 0x800
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

.set __base,0xB00
.rept 0xc00 - 0xb00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr

#if defined(CONFIG_MCP_N)
.set __base,0x300
// 256MB for SDRAM with cacheable
.rept 0xD00 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr
#else
.set __base,0x300
// 80MB for SDRAM with cacheable
.rept 0xC50 - 0xC00
FL_SECTION_ENTRY __base,3,0,1,1
.set __base,__base+1
.endr

// Not Allowed
.rept 0xD00 - 0xC50
.word 0x00000000
.endr
#endif

.set __base,0xD00
// 1:1 mapping for debugging with non-cacheable
.rept 0x1000 - 0xD00
FL_SECTION_ENTRY __base,3,0,0,0
.set __base,__base+1
.endr
#endif
#endif






mem_setup.S的完整代码:

#include <config.h>
#include <s5pv210.h>

.globl mem_ctrl_asm_init
mem_ctrl_asm_init:

#ifndef CONFIG_EVT1

ldr r0, =ASYNC_MSYS_DMC0_BASE

ldr r1, =0x0
str r1, [r0, #0x0]

/* This register is removed at EVT1 of C110. */
ldr r1, =0x0
str r1, [r0, #0xC]

#endif

#ifdef CONFIG_MCP_SINGLE

/* DMC0 Drive Strength (Setting 2X) */

ldrr0, =ELFIN_GPIO_BASE

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_0DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_1DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_2DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_3DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_4DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_5DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_6DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP1_7DRV_SR_OFFSET]

ldrr1, =0x00002AAA
strr1, [r0, #MP1_8DRV_SR_OFFSET]


/* DMC1 Drive Strength (Setting 2X) */

ldrr0, =ELFIN_GPIO_BASE

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_0DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_1DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_2DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_3DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_4DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_5DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_6DRV_SR_OFFSET]

ldrr1, =0x0000AAAA
strr1, [r0, #MP2_7DRV_SR_OFFSET]

ldrr1, =0x00002AAA
strr1, [r0, #MP2_8DRV_SR_OFFSET]

/* DMC0 initialization at single Type*/
ldrr0, =APB_DMC_0_BASE

ldrr1, =0x00101000@PhyControl0 DLL parameter setting, manual 0x00101000
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00000086@PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case
strr1, [r0, #DMC_PHYCONTROL1]

ldrr1, =0x00101002@PhyControl0 DLL on
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00101003@PhyControl0 DLL start
strr1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
ldrr1, [r0, #DMC_PHYSTATUS]@Load Phystatus register value
andr2, r1, #0x7
cmpr2, #0x7@Loop until DLL is locked
bnefind_lock_val

andr1, #0x3fc0
movr2, r1, LSL #18
orrr2, r2, #0x100000
orrr2 ,r2, #0x1000

orrr1, r2, #0x3@Force Value locking
strr1, [r0, #DMC_PHYCONTROL0]

#if 0/* Memory margin test 10.01.05 */
orrr1, r2, #0x1@DLL off
strr1, [r0, #DMC_PHYCONTROL0]
#endif
/* setting DDR2 */
ldrr1, =0x0FFF2010@ConControl auto refresh off
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0x00212400@MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
strr1, [r0, #DMC_MEMCONTROL]

ldrr1, =DMC0_MEMCONFIG_0@MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
strr1, [r0, #DMC_MEMCONFIG0]

ldrr1, =DMC0_MEMCONFIG_1@MemConfig1
strr1, [r0, #DMC_MEMCONFIG1]

ldrr1, =0xFF000000@PrechConfig
strr1, [r0, #DMC_PRECHCONFIG]

ldrr1, =DMC0_TIMINGA_REF@TimingAref7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)
strr1, [r0, #DMC_TIMINGAREF]

ldrr1, =DMC0_TIMING_ROW@TimingRowfor @200MHz
strr1, [r0, #DMC_TIMINGROW]

ldrr1, =DMC0_TIMING_DATA@TimingDataCL=3
strr1, [r0, #DMC_TIMINGDATA]

ldrr1, =DMC0_TIMING_PWR@TimingPower
strr1, [r0, #DMC_TIMINGPOWER]

ldrr1, =0x07000000@DirectCmdchip0 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@DirectCmdchip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00020000@DirectCmdchip0 EMRS2
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00030000@DirectCmdchip0 EMRS3
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010400@DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000542@DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@DirectCmdchip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@DirectCmdchip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@DirectCmdchip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000442@DirectCmdchip0 MRS (MEM DLL unreset)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010780@DirectCmdchip0 EMRS1 (OCD default)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010400@DirectCmdchip0 EMRS1 (OCD exit)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x07100000@DirectCmdchip1 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@DirectCmdchip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00120000@DirectCmdchip1 EMRS2
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00130000@DirectCmdchip1 EMRS3
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110400@DirectCmdchip1 EMRS1 (MEM DLL on, DQS# disable)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100542@DirectCmdchip1 MRS (MEM DLL reset) CL=4, BL=4
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@DirectCmdchip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@DirectCmdchip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@DirectCmdchip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100442@DirectCmdchip1 MRS (MEM DLL unreset)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110780@DirectCmdchip1 EMRS1 (OCD default)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110400@DirectCmdchip1 EMRS1 (OCD exit)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x0FF02030@ConControlauto refresh on
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0xFFFF00FF@PwrdnConfig
strr1, [r0, #DMC_PWRDNCONFIG]

ldrr1, =0x00202400@MemControlBL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
strr1, [r0, #DMC_MEMCONTROL]

/* DMC1 initialization */
ldrr0, =APB_DMC_1_BASE

ldrr1, =0x00101000@Phycontrol0 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00000086@Phycontrol1 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL1]

ldrr1, =0x00101002@PhyControl0 DLL on
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00101003@PhyControl0 DLL start
strr1, [r0, #DMC_PHYCONTROL0]
find_lock_val1:
ldrr1, [r0, #DMC_PHYSTATUS]@Load Phystatus register value
andr2, r1, #0x7
cmpr2, #0x7@Loop until DLL is locked
bnefind_lock_val1

andr1, #0x3fc0
movr2, r1, LSL #18
orrr2, r2, #0x100000
orrr2, r2, #0x1000

orrr1, r2, #0x3@Force Value locking
strr1, [r0, #DMC_PHYCONTROL0]

#if 0/* Memory margin test 10.01.05 */
orrr1, r2, #0x1@DLL off
strr1, [r0, #DMC_PHYCONTROL0]
#endif

/* settinf fot DDR2 */
ldrr0, =APB_DMC_1_BASE

ldrr1, =0x0FFF2010@auto refresh off
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =DMC1_MEMCONTROL@MemControlBL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
strr1, [r0, #DMC_MEMCONTROL]

ldrr1, =DMC1_MEMCONFIG_0@MemConfig0512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed
strr1, [r0, #DMC_MEMCONFIG0]

ldrr1, =DMC1_MEMCONFIG_1@MemConfig1
strr1, [r0, #DMC_MEMCONFIG1]

ldrr1, =0xFF000000
strr1, [r0, #DMC_PRECHCONFIG]

ldrr1, =DMC1_TIMINGA_REF@TimingAref7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4
strr1, [r0, #DMC_TIMINGAREF]

ldrr1, =DMC1_TIMING_ROW@TimingRowfor @200MHz
strr1, [r0, #DMC_TIMINGROW]

ldrr1, =DMC1_TIMING_DATA@TimingDataCL=3
strr1, [r0, #DMC_TIMINGDATA]

ldrr1, =DMC1_TIMING_PWR@TimingPower
strr1, [r0, #DMC_TIMINGPOWER]


ldrr1, =0x07000000@DirectCmdchip0 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@DirectCmdchip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00020000@DirectCmdchip0 EMRS2
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00030000@DirectCmdchip0 EMRS3
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010400@DirectCmdchip0 EMRS1 (MEM DLL on, DQS# disable)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000542@DirectCmdchip0 MRS (MEM DLL reset) CL=4, BL=4
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@DirectCmdchip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@DirectCmdchip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@DirectCmdchip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000442@DirectCmdchip0 MRS (MEM DLL unreset)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010780@DirectCmdchip0 EMRS1 (OCD default)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00010400@DirectCmdchip0 EMRS1 (OCD exit)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x07100000@DirectCmdchip1 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@DirectCmdchip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00120000@DirectCmdchip1 EMRS2
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00130000@DirectCmdchip1 EMRS3
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110440@DirectCmdchip1 EMRS1 (MEM DLL on, DQS# disable)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100542@DirectCmdchip1 MRS (MEM DLL reset) CL=4, BL=4
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@DirectCmdchip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@DirectCmdchip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@DirectCmdchip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100442@DirectCmdchip1 MRS (MEM DLL unreset)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110780@DirectCmdchip1 EMRS1 (OCD default)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00110400@DirectCmdchip1 EMRS1 (OCD exit)
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x0FF02030@ConControlauto refresh on
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0xFFFF00FF@PwrdnConfig
strr1, [r0, #DMC_PWRDNCONFIG]

ldrr1, =DMC1_MEMCONTROL@MemControlBL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off
strr1, [r0, #DMC_MEMCONTROL]

#else/* CONFIG_MCP_SINGLE */

/* DMC0 initialization */
ldrr0, =APB_DMC_0_BASE

ldrr1, =0x00101000@Phycontrol0 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00000084@Phycontrol1 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL1]

ldrr1, =0x00101002@Phycontrol2 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00101003@Dll on
strr1, [r0, #DMC_PHYCONTROL0]

find_lock_val:
ldrr1, [r0, #DMC_PHYSTATUS]@Load Phystatus register value
and r2, r1, #0x7
cmpr2, #0x7@Loop until DLL is locked
bnefind_lock_val

andr1, #0x3fc0
movr2, r1, LSL #18
orrr2, r2, #0x100000
orrr2, r2, #0x1000

orrr1, r2, #0x3@Force Value locking
strr1, [r0, #DMC_PHYCONTROL0]
#if 1 /* DRAM margin test 10.01.06 */
orrr1, r2, #0x1@DLL off
strr1, [r0, #DMC_PHYCONTROL0]
#endif
ldrr1, =0x0fff1010@auto refresh off
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0x00212100
strr1, [r0, #DMC_MEMCONTROL]

ldrr1, =DMC0_MEMCONFIG_0
strr1, [r0, #DMC_MEMCONFIG0]

ldrr1, =DMC0_MEMCONFIG_1
strr1, [r0, #DMC_MEMCONFIG1]

ldrr1, =0xff000000
strr1, [r0, #DMC_PRECHCONFIG]

ldrr1, =DMC0_TIMINGA_REF
strr1, [r0, #DMC_TIMINGAREF]

ldrr1, =DMC0_TIMING_ROW@TimingRow@133MHz
strr1, [r0, #DMC_TIMINGROW]

ldrr1, =DMC0_TIMING_DATA
strr1, [r0, #DMC_TIMINGDATA]

ldrr1, =DMC0_TIMING_PWR@Timing Power
strr1, [r0, #DMC_TIMINGPOWER]

ldrr1, =0x07000000@chip0 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@chip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@chip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@chip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000032@chip0 MRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x07100000@chip1 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@chip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@chip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@chip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100032@chip1 MRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x0FFF20B0@ConControl auto refresh on
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0xFFFF00FF@PwrdnConfig
strr1, [r0, #DMC_PWRDNCONFIG]

ldrr1, =0x00212113@MemControl
strr1, [r0, #DMC_MEMCONTROL]

/* DMC1 initialization */
ldrr0, =APB_DMC_1_BASE

ldrr1, =0x00101000@Phycontrol0 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00000084@Phycontrol1 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL1]

ldrr1, =0x00101002@Phycontrol2 DLL parameter setting
strr1, [r0, #DMC_PHYCONTROL0]

ldrr1, =0x00101003@Dll on
strr1, [r0, #DMC_PHYCONTROL0]

find_lock_val1:
ldrr1, [r0, #DMC_PHYSTATUS]@Load Phystatus register value
and r2, r1, #0x7
cmpr2, #0x7@Loop until DLL is locked
bnefind_lock_val1

andr1, #0x3fc0
movr2, r1, LSL #18
orrr2, r2, #0x100000
orrr2, r2, #0x1000

orrr1, r2, #0x3@Force Value locking
strr1, [r0, #DMC_PHYCONTROL0]

#if 1/* Memory margin test 10.01.05 */
orrr1, r2, #0x1@DLL off
strr1, [r0, #DMC_PHYCONTROL0]
#endif
ldrr0, =APB_DMC_1_BASE

ldrr1, =0x0FFF1010@auto refresh off
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =DMC1_MEMCONTROL
strr1, [r0, #DMC_MEMCONTROL]

ldrr1, =DMC1_MEMCONFIG_0
strr1, [r0, #DMC_MEMCONFIG0]

ldrr1, =DMC1_MEMCONFIG_1
strr1, [r0, #DMC_MEMCONFIG1]

ldrr1, =0xff000000
strr1, [r0, #DMC_PRECHCONFIG]

ldrr1, =DMC1_TIMINGA_REF
strr1, [r0, #DMC_TIMINGAREF]

ldrr1, =DMC1_TIMING_ROW@TimingRow@133MHz
strr1, [r0, #DMC_TIMINGROW]

ldrr1, =DMC1_TIMING_DATA
strr1, [r0, #DMC_TIMINGDATA]

ldrr1, =DMC1_TIMING_PWR@Timing Power
strr1, [r0, #DMC_TIMINGPOWER]

ldrr1, =0x07000000@chip0 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01000000@chip0 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@chip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05000000@chip0 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00000032@chip0 MRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00020020@chip0 EMRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x07100000@chip1 Deselect
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x01100000@chip1 PALL
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@chip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x05100000@chip1 REFA
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00100032@chip1 MRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x00120020@chip0 EMRS
strr1, [r0, #DMC_DIRECTCMD]

ldrr1, =0x0FFF10B0@ConControl auto refresh on
strr1, [r0, #DMC_CONCONTROL]

ldrr1, =0xFFFF00FF@PwrdnConfig
strr1, [r0, #DMC_PWRDNCONFIG]

ldrr1, =0x00212113@MemControl
strr1, [r0, #DMC_MEMCONTROL]

#endif/* CONFIG_MCP_AC / CONFIG_MCP_H / CONFIG_MCP_B / CONFIG_MCP_D / CONFIG_MCP_N */

movpc, lr

/*
* v7_flush_dcache_all()
*
* Flush the whole D-cache.
*
* Corrupted registers: r0-r5, r7, r9-r11
*
* - mm - mm_struct describing address space
*/
.align 5
.global v7_flush_dcache_all
v7_flush_dcache_all:

ldrr0, =0xffffffff
mrcp15, 1, r0, c0, c0, 1 @ Read CLIDR
andsr3, r0, #0x7000000
movr3, r3, LSR #23 @ Cache level value (naturally aligned)
beq Finished
movr10, #0
Loop1:
addr2, r10, r10, LSR #1 @ Work out 3xcachelevel
movr1, r0, LSR r2 @ bottom 3 bits are the Ctype for this level
andr1, r1, #7 @ get those 3 bits alone
cmpr1, #2
bltSkip @ no cache or only instruction cache at this level
mcrp15, 2, r10, c0, c0, 0 @ write the Cache Size selection register
movr1, #0
mcrp15, 0, r1, c7, c5, 4 @ PrefetchFlush to sync the change to the CacheSizeID reg
mrcp15, 1, r1, c0, c0, 0 @ reads current Cache Size ID register
andr2, r1, #0x7 @ extract the line length field
addr2, r2, #4 @ add 4 for the line length offset (log2 16 bytes)
ldrr4, =0x3FF
andsr4, r4, r1, LSR #3 @ R4 is the max number on the way size (right aligned)
clzr5, r4 @ R5 is the bit position of the way size increment
ldrr7, =0x00007FFF
andsr7, r7, r1, LSR #13 @ R7 is the max number of the index size (right aligned)
Loop2:
movr9, r4 @ R9 working copy of the max way size (right aligned)
Loop3:
orrr11, r10, r9, LSL r5 @ factor in the way number and cache number into R11
orrr11, r11, r7, LSL r2 @ factor in the index number
mcrp15, 0, r11, c7, c6, 2 @ invalidate by set/way
subsr9, r9, #1 @ decrement the way number
bgeLoop3
subsr7, r7, #1 @ decrement the index
bgeLoop2
Skip:
addr10, r10, #2 @ increment the cache number
cmpr3, r10
bgtLoop1
Finished:
movpc, lr

.align 5
.global disable_l2cache
disable_l2cache:
mrc p15, 0, r0, c1, c0, 1
bic r0, r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1
movpc, lr


.align 5
.global enable_l2cache
enable_l2cache:
mrc p15, 0, r0, c1, c0, 1
orr r0, r0, #(1<<1)
mcr p15, 0, r0, c1, c0, 1
mov pc, lr

.align 5
.global set_l2cache_auxctrl
set_l2cache_auxctrl:
movr0, #0x0
mcr p15, 1, r0, c9, c0, 2
mov pc, lr

.align 5
.global set_l2cache_auxctrl_cycle
set_l2cache_auxctrl_cycle:
mrc p15, 1, r0, c9, c0, 2
bic r0, r0, #(0x1<<29)
bic r0, r0, #(0x1<<21)
bic r0, r0, #(0x7<<6)
bic r0, r0, #(0x7<<0)
mcr p15, 1, r0, c9, c0, 2
mov pc,lr

.align 5
CoInvalidateDCacheIndex:
;/* r0 = index */
mcr p15, 0, r0, c7, c6, 2
mov pc,lr


/* Below code is for ARM926EJS and ARM1026EJS */
.globl cleanDCache
cleanDCache:
mrcp15, 0, pc, c7, c10, 3/* test/clean D-Cache */
bnecleanDCache
movpc, lr

.globl cleanFlushDCache
cleanFlushDCache:
mrcp15, 0, pc, c7, c14, 3/* test/cleanflush D-Cache */
bnecleanFlushDCache
movpc, lr

.globl cleanFlushCache
cleanFlushCache:
mrcp15, 0, pc, c7, c14, 3/* test/cleanflush D-Cache */
bnecleanFlushCache
mcrp15, 0, r0, c7, c5, 0/* flush I-Cache */
movpc, lr

.ltorg



.globl ledon_1
ledon_1:
/*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x11000
str r1, [r0, #GPC0CON_OFFSET]
ldr r2, [r0, #GPC0CON_OFFSET]
orrr2, r2, #0x08
str r2, [r0, #GPC0DAT_OFFSET]
movpc, lr

.globl ledon_2
ledon_2:
/*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x11000
str r1, [r0, #GPC0CON_OFFSET]
ldr r2, [r0, #GPC0CON_OFFSET]
orrr2, r2, #0x10
str r2, [r0, #GPC0DAT_OFFSET]
movpc, lr

.globl ledon
ledon:
/*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x11000
str r1, [r0, #GPC0CON_OFFSET]
ldr r2, =0x18
str r2, [r0, #GPC0DAT_OFFSET]
movpc, lr

.globl ledoff
ledoff:
/*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/
ldrr0, =ELFIN_GPIO_BASE
ldrr1, =0x11000
str r1, [r0, #GPC0CON_OFFSET]
ldr r2, =0x00
str r2, [r0, #GPC0DAT_OFFSET]
movpc, lr








crt0.S的完整代码(这个代码u-boot本身就有,并且不需要改动,但这里也贴出来):

/*
* crt0 - C-runtime startup Code for ARM U-Boot
*
* Copyright (c) 2012 Albert ARIBAUD <albert.u.boot@aribaud.net>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/

#include <config.h>
#include <asm-offsets.h>

/*
* This file handles the target-independent stages of the U-Boot
* start-up where a C runtime environment is needed. Its entry point
* is _main and is branched into from the target's start.S file.
*
* _main execution sequence is:
*
* 1. Set up initial environment for calling board_init_f().
* This environment only provides a stack and a place to store
* the GD ('global data') structure, both located in some readily
* available RAM (SRAM, locked cache...). In this context, VARIABLE
* global data, initialized or not (BSS), are UNAVAILABLE; only
* CONSTANT initialized data are available.
*
* 2. Call board_init_f(). This function prepares the hardware for
* execution from system RAM (DRAM, DDR...) As system RAM may not
* be available yet, , board_init_f() must use the current GD to
* store any data which must be passed on to later stages. These
* data include the relocation destination, the future stack, and
* the future GD location.
*
* (the following applies only to non-SPL builds)
*
* 3. Set up intermediate environment where the stack and GD are the
* ones allocated by board_init_f() in system RAM, but BSS and
* initialized non-const data are still not available.
*
* 4. Call relocate_code(). This function relocates U-Boot from its
* current location into the relocation destination computed by
* board_init_f().
*
* 5. Set up final environment for calling board_init_r(). This
* environment has BSS (initialized to 0), initialized non-const
* data (initialized to their intended value), and stack in system
* RAM. GD has retained values set by board_init_f(). Some CPUs
* have some work left to do at this point regarding memory, so
* call c_runtime_cpu_setup.
*
* 6. Branch to either nand_boot() or board_init_r().
*/

/*
* declare nand_boot() or board_init_r() to jump to at end of crt0
*/

#if defined(CONFIG_NAND_SPL)

.globl nand_boot


#elif !defined(CONFIG_SPL_BUILD)

.globl board_init_r

#endif

/*
* start and end of BSS
*/

.globl __bss_start
.globl __bss_end__

/*
* entry point of crt0 sequence
*/

.global _main

_main:

/*
* Set up initial C runtime environment and call board_init_f(0).
*/

#if defined(CONFIG_NAND_SPL)
/* deprecated, use instead CONFIG_SPL_BUILD */
ldrsp, =(CONFIG_SYS_INIT_SP_ADDR)
#elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldrsp, =(CONFIG_SPL_STACK)
#else
ldrsp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
bicsp, sp, #7/* 8-byte alignment for ABI compliance */
subsp, #GD_SIZE/* allocate one GD above SP */
bicsp, sp, #7/* 8-byte alignment for ABI compliance */
movr8, sp/* GD is above SP */
movr0, #0
blboard_init_f

#if ! defined(CONFIG_SPL_BUILD)

/*
* Set up intermediate environment (new sp and gd) and call
* relocate_code(addr_sp, gd, addr_moni). Trick here is that
* we'll return 'here' but relocated.
*/

ldrsp, [r8, #GD_START_ADDR_SP]/* r8 = gd->start_addr_sp */
bicsp, sp, #7/* 8-byte alignment for ABI compliance */
ldrr8, [r8, #GD_BD]/* r8 = gd->bd */
subr8, r8, #GD_SIZE/* new GD is below bd */

adrlr, here
ldrr0, [r8, #GD_RELOC_OFF]/* lr = gd->start_addr_sp */
addlr, lr, r0
ldrr0, [r8, #GD_START_ADDR_SP]/* r0 = gd->start_addr_sp */
movr1, r8/* r1 = gd */
ldrr2, [r8, #GD_RELOCADDR]/* r2 = gd->relocaddr */
brelocate_code
here:

/* Set up final (full) environment */

blc_runtime_cpu_setup/* we still call old routine here */

ldrr0, =__bss_start/* this is auto-relocated! */
ldrr1, =__bss_end__/* this is auto-relocated! */

movr2, #0x00000000/* prepare zero to clear BSS */

clbss_l:cmpr0, r1/* while not at end of BSS */
strlor2, [r0]/* clear 32-bit BSS word */
addlor0, r0, #4/* move to next */
bloclbss_l

bl coloured_LED_init
bl red_led_on

#if defined(CONFIG_NAND_SPL)

/* call _nand_boot() */
ldr pc, =nand_boot

#else
/* call board_init_r(gd_t *id, ulong dest_addr) */
movr0, r8/* gd_t */
ldrr1, [r8, #GD_RELOCADDR]/* dest_addr */
/* call board_init_r */
ldrpc, =board_init_r/* this is auto-relocated! */

#endif

/* we should not return here. */

#endif