lowlevle_init.s
https://www.2cto.com/kf/201609/549272.html
https://blog.csdn.net/zjhsucceed_329/article/details/34567451
.globl _start
_start: b reset //代码运行开始地址 breset 相对跳转指令
ldr pc, _undefined_instruction
ldr pc, _software_interrupt
ldr pc, _prefetch_abort
ldr pc, _data_abort
ldr pc, _not_used
ldr pc, _irq
ldr pc, _fiq
//对_start为标号地址,相对代码0的地址,对_start的绝对引用,都是代表连接地址,而非0
_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 */
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
上面部分定义了一堆异常向量表,cpu根据异常指令调到对应的异常向量处,去执行对应的指令
_TEXT_BASE:
.word TEXT_BASE
TEXT_BASE地址为代码连接运行地址,在编译连接时指定,本uboot中该值为0xc3e00000
_TEXT_PHY_BASE:
.word CFG_PHY_UBOOT_BASE //uboot在内存中的物理基地址
.globl _armboot_start
_armboot_start:
.word _start
/*
* These are defined in the board-specific linker script.
*/
.globl _bss_start //bss段开始地址
_bss_start:
.word __bss_start
.globl _bss_end //bss段结束地址
_bss_end:
.word _end
/*********************************************************************************************************************/
/*
* the actual reset code
*/
reset:
/*
* set the cpu to SVC32 mode and IRQ & FIQ disable
*/
@;mrs r0,cpsr
@;bic r0,r0,#0x1f
@;orr r0,r0,#0xd3
@;msr cpsr,r0
msr cpsr_c, #0xd3 @ I & F disable, Mode: 0x13 - SVC
//设置cpu模式为管理模式
cpu_init_crit:
#ifndef CONFIG_EVT1
#if 0
bl v7_flush_dcache_all
#else
bl disable_l2cache
mov r0, #0x0 @
mov r1, #0x0 @ i
mov r3, #0x0
mov r4, #0x0
lp1:
mov r2, #0x0 @ j
lp2:
mov r3, r1, LSL #29 @ r3 = r1(i) <<29
mov r4, r2, LSL #6 @ r4 = r2(j) <<6
orr r4, r4, #0x2 @ r3 = (i<<29)|(j<<6)|(1<<1)
orr r3, r3, r4
mov r0, r3 @ r0 = r3
bl CoInvalidateDCacheIndex 清除数据缓存 8 * 1024
add r2, #0x1 @ r2(j)++
cmp r2, #1024 @ r2 < 1024
bne lp2 @ jump to lp2
add r1, #0x1 @ r1(i)++
cmp r1, #8 @ r1(i) < 8
bne lp1 @ jump to lp1
bl set_l2cache_auxctrl 锁定l2cache
bl enable_l2cache 使能l2cache地址对齐
#endif
#endif
bl disable_l2cache 禁止l2cache
bl set_l2cache_auxctrl_cycle 锁定l2cache
bl enable_l2cache 使能l2cache
/*
* Invalidate L1 I/D
*/
mov r0, #0 @ set up for MCR
mcr p15, 0, r0, c8, c7, 0 @ invalidate TLBs
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
//此部分为cache部分相关功能初始化
/***************************MMU初始化**************************************/
/*
* disable MMU stuff and caches
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002000 @ clear bits 13 (--V-)
bic r0, r0, #0x00000007 @ clear bits 2:0 (-CAM)
orr r0, r0, #0x00000002 @ set bit 1 (--A-) Align
orr r0, r0, #0x00000800 @ set bit 12 (Z---) BTB
mcr p15, 0, r0, c1, c0, 0
mrc是协处理器命令。用于读取协处理器中的寄存器的数据到ARM处理器的寄存器里面。
/* Read booting information */
ldr r0, =PRO_ID_BASE
ldr r1, [r0,#OMR_OFFSET]
bic r2, r1, #0xffffffc1
读取启动信息,从PRO_ID_BASE(0xE0000000)中读取数据到r0,在加上OMR_OFFSET(0x04)的偏移量,所以值为0xE0000004,这个寄存器的值是根据OM引脚自动设置的,指定了从什么地方启动,我们在代码中可以读取该值来判断来选择什么启动介质来启动。最终r2就存储了启动信息。
bic BIC指令的格式为: BIC{条件}{S} 目的寄存器,操作数1,操作数2
BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。
操作数1应是一个寄存器, 操作数2可以是一个寄存器、被移位的寄存器、或一个立即数。
操作数2为32位的掩码,如果在 掩码中置了某一位1,则清除这一位。未设置的掩码位保持不变。
orr ORR指令的格式为: ORR{条件}{S} 目的寄存器,操作数1,操作数2
ORR指令用于在两个操作数上进行逻辑戒运算,并把结果放置到目的寄存器中。
操作数1应该是一 个寄存器,操作数2可以是一个寄存器,被移位的寄存器,或一个立即数。
该指令常用于设置操 作数1的某些位。
/* PS_HOLD(GPJ2_5) set to output high */
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x00100000
str r1, [r0, #GPJ2CON_OFFSET]
ldr r1, =0x0400
str r1, [r0, #GPJ2PUD_OFFSET]
ldr r1, =0x20
str r1, [r0, #GPJ2DAT_OFFSET]
此处为电源相关初始化
/* NAND BOOT */
cmp r2, #0x0 @ 512B 4-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x2 @ 2KB 5-cycle
moveq r3, #BOOT_NAND
cmp r2, #0x4 @ 4KB 5-cycle 8-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x6 @ 4KB 5-cycle 16-bit ECC
moveq r3, #BOOT_NAND
cmp r2, #0x8 @ OneNAND Mux
moveq r3, #BOOT_ONENAND
/* SD/MMC BOOT */
cmp r2, #0xc
moveq r3, #BOOT_MMCSD
/* NOR BOOT */
cmp r2, #0x14
moveq r3, #BOOT_NOR
根据r2寄存器中的值来判断启动方式并保存到r3寄存器中
/* Uart BOOTONG failed */
cmp r2, #(0x1<<4)
moveq r3, #BOOT_SEC_DEV
ldr r0, =INF_REG_BASE
str r3, [r0, #INF_REG3_OFFSET]
将启动标识码写入INF_REG3中
/*
* Go setup Memory and board specific bits prior to relocation.
*/
ldr sp, =0xd0036000 /* end of sram dedicated to u-boot */
sub sp, sp, #12 /* set stack */
mov fp, #0
第一次设置栈
/************************************************************************************************/
bl lowlevel_init /* go setup pll,mux,memory */
跳转到 lowlevel_init 处进行初始化
lowlevel_init:
push {lr}
/* check reset status */
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
@ 跳转到目的地Reset Control Register的地址传送给r0 Address = 0xE010_A000 =0xE010_0000+
0xA000
ldr r1, [r0]
@ 将存储器地址为 R0(内存储的值) 的字数据读入寄存器 R1
bic r1, r1, #0xfff6ffff
@将r1与
0xfff6ffff
的反码按位进行与运算(既和
0xfff6ffff
进行与非运算),并写入r1;结合上一步,可知,这一步的作用是
16
和19bit置一,其他位清零
cmp r1, #0x10000 @ 判断16bit是不是等于1
beq wakeup_reset_pre
如果是从睡眠状态唤醒,就跳转到wakeup_reset_pre,既跳过接下来的初始化
cmp r1, #0x80000
beq wakeup_reset_from_didle
@ 判断是不是从深度空闲(Deep-IDLE)状态唤醒
/* IO Retention release */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
此处判断复位状态,是冷启动 、热启动还是休眠唤醒,若是热启动和唤醒则直接跳转,不用再执行下面的初始化
@ 将跳转目的地址MISC Register的地址传送给r0 Address = 0xE010_E000 =0xE010_0000+
0xE000
ldr r1, [r0]
ldr r2, =IO_RET_REL
orr r1, r1, r2
str r1, [r0]
/* Disable Watchdog */
ldr r0, =ELFIN_WATCHDOG_BASE /* 0xE2700000 */
mov r1, #0
str r1, [r0]
/* SRAM(2MB) init for SMDKC110 */
/* GPJ1 SROM_ADDR_16to21 */
ldr r0, =ELFIN_GPIO_BASE
ldr r1, [r0, #GPJ1CON_OFFSET]
bic r1, r1, #0xFFFFFF
ldr r2, =0x444444
orr r1, r1, r2
str r1, [r0, #GPJ1CON_OFFSET]
ldr r1, [r0, #GPJ1PUD_OFFSET]
ldr r2, =0x3ff
bic r1, r1, r2
str r1, [r0, #GPJ1PUD_OFFSET]
/* GPJ4 SROM_ADDR_16to21 */
ldr r1, [r0, #GPJ4CON_OFFSET]
bic r1, r1, #(0xf<<16)
ldr r2, =(0x4<<16)
orr r1, r1, r2
str r1, [r0, #GPJ4CON_OFFSET]
ldr r1, [r0, #GPJ4PUD_OFFSET]
ldr r2, =(0x3<<8)
bic r1, r1, r2
str r1, [r0, #GPJ4PUD_OFFSET]
/* CS0 - 16bit sram, enable nBE, Byte base address */
ldr r0, =ELFIN_SROM_BASE /* 0xE8000000 */
mov r1, #0x1
str r1, [r0]
/* PS_HOLD pin(GPH0_0) set to high */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
@ 设置PMIC(Power Management IC)控制引脚,既电源管理ic引脚(基于I2C)
ldr r1, [r0]
orr r1, r1, #0x300
orr r1, r1, #0x1
str r1, [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.
*/
/*下面的代码事实上只是判断pc和_TEXT_BASE(0X23e00000)的最高两位是否相同*/
/* 根据s5pv210的数据手册可知,首先,系统会运行固化在irom的BL0,紧接着会从外部nand
* 或sdcard等设备读取前16K的BL1代码到IRAM中的0xD0020000处。然后从0xD0020010处运行(因为前16byte是校验和的值)
* BL1的作用是初始化DRAM,拷贝BL2到DRAM中_TEXT_BASE(0X23e00000)处,然后跳到DRAM中运行
* 因此可以通过最高两位来判断代码是在哪里运行
* 同时可知,当代码已经就在DRAM中运行时,就必须跳过DRAM的初始化
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, 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_TQ210_IIC_PM_CHIP
bl PMIC_InitIp
#endif
/* init system clock */
@ 时钟初始化 PLL初始化,要想看懂此汇编,请查看datsheet中,clk control章节
bl system_clock_init
/* Memory initialize */
@ 内存初始化
bl mem_ctrl_asm_init
1
:
/* for UART */
@ 串口初始化,要看懂此汇编, 请查看datsheet中, 请查看串口章节
bl uart_asm_init
bl tzpc_init
@ 这段不执行
#
if
defined(CONFIG_ONENAND)
bl onenandcon_init
#endif
@ nand初始化
#
if
defined(CONFIG_NAND)
/* simple init for NAND */
bl nand_asm_init
#endif
/* check reset status */
ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
ldr r1, [r0]
bic r1, r1, #
0xfffeffff
cmp r1, #
0x10000
beq wakeup_reset_pre
/* ABB disable */
ldr r0, =
0xE010C300
orr r1, r1, #(
0x1
<<
23
)
str r1, [r0]
/* Print 'K' */
ldr r0, =ELFIN_UART_CONSOLE_BASE
ldr r1, =
0x4b4b4b4b
str r1, [r0, #UTXH_OFFSET]
pop {pc} @ 返回到start.S
wakeup_reset_from_didle: @ 从深度睡眠中唤醒
/* Wait when APLL is locked */
ldr r0, =ELFIN_CLOCK_POWER_BASE
lockloop:
ldr r1, [r0, #APLL_CON0_OFFSET]
and r1, r1, #(
1
<<
29
)
cmp r1, #(
1
<<
29
)
bne lockloop @ 这里使用循环
beq exit_wakeup
wakeup_reset_pre:
mrc p15,
0
, r1, c1, c0,
1
@Read
CP15 Auxiliary control register
and r1, r1, #
0x80000000
@Check
L2RD is disable or not
cmp r1, #
0x80000000
bne wakeup_reset
@if
L2RD is not disable jump to wakeup_reset
bl disable_l2cache
bl v7_flush_dcache_all
/* L2 cache enable at sleep.S of kernel
* bl enable_l2cache
*/
#ifdef CONFIG_TQ210
bl enable_l2cache
#endif
wakeup_reset:
/* init system clock */
bl system_clock_init
bl mem_ctrl_asm_init
bl tzpc_init
#
if
defined(CONFIG_ONENAND)
bl onenandcon_init
#endif
#
if
defined(CONFIG_NAND)
bl nand_asm_init
#endif
exit_wakeup:
/*Load return address and jump to kernel*/
ldr r0, =(INF_REG_BASE+INF_REG0_OFFSET)
ldr r1, [r0]
/* r1 = physical address of s5pc110_cpu_resume function*/
mov pc, r1
/*Jump to kernel */
nop
nop
/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
system_clock_init:
/* 这一段的作用是将Clock Source Control Registers值清空
* 具体的作用是将VPLL_SEL、EPLL_SEL、MPLL_SEL和APLL_SEL的时钟源设置为FINVPLL,将MUX_MSYS_SEL、MUX_DSYS_SEL和MUX_PSYS_SEL时钟源设置为SCLKMPLL
* 将ONENAND_SEL时钟源设置为HCLK_PSYS
* 为什么这样设置,因为未设置 PLL 和各种分频系数之前,我们不能使用 PLL,为了保险起见,暂时直接使用频率较低
* 的外接的 24MHz 晶振,待设置好 PLL 和分频系数后再重新设置各种时钟开关
*/
ldr r0, =ELFIN_CLOCK_POWER_BASE
@0xe0100000
/* Set Mux to FIN */
ldr r1, =
0x0
str r1, [r0, #CLK_SRC0_OFFSET]
ldr r1, =APLL_LOCKTIME_VAL @将APLL_LOCKTIME_VAL(
0x2cf
)装入r1
str r1, [r0, #APLL_LOCK_OFFSET] @将r1内的值装入地址为(r0内的值+CLK_SRC0_OFFSET =
0xe0100000
)的内存,即设置APLL的锁定周期
/*
* A PLL requires locking period when input frequency is changed or frequency pision (multiplication) values are
* changed.PLL_LOCK register specifies this locking period, which is based on PLL’s source clock. During this
* period, output will be low state
*/
/* Disable PLL */
#
if
defined(CONFIG_CHECK_MPLL_LOCK)
retryloop:
#endif
ldr r1, =
0x0
str r1, [r0, #APLL_CON0_OFFSET] @ 将APLL控制寄存器的值清空,这个寄存器的第
31
位置零关闭APLL
25
-16bit配置MDIV的分频
@
13
-8bit配置PDIV的分频
2
-0bit配置SDIV的分频
ldr r1, =
0x0
str r1, [r0, #MPLL_CON_OFFSET] @ 配置MPLL
ldr r1, =
0x0
str r1, [r0, #MPLL_CON_OFFSET] @ 重复配置MPLL,确保MPLL配置成功
ldr r1, [r0, #CLK_DIV0_OFFSET] @ Clock Divider Control Register(
0xe0100300
)
ldr r2, =CLK_DIV0_MASK @ CLK_DIV0_MASK(
0x7fffffff
)
bic r1, r1, r2 @ 首先清零
ldr r2, =CLK_DIV0_VAL @ CLK_DIV0_VAL
orr r1, r1, r2
str r1, [r0, #CLK_DIV0_OFFSET]
/*
*CLK_DIV0_VAL = ((0< OneDRAM clock sel = MPLL */
ldr r1, [r0, #CLK_SRC6_OFFSET]
bic r1, r1, #(
0x3
<<
24
)
orr r1, r1, #
0x01000000
str r1, [r0, #CLK_SRC6_OFFSET]
/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldr r1, [r0, #CLK_DIV6_OFFSET]
bic r1, r1, #(
0xF
<<
28
)
bic r1, r1, #(
0x7
<<
12
) @; ONENAND_RATIO:
0
orr r1, r1, #
0x30000000
str r1, [r0, #CLK_DIV6_OFFSET]
#elif defined (CONFIG_MCP_N)
/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldr r1, [r0, #CLK_SRC6_OFFSET]
mov r1, #
0x00000000
str r1, [r0, #CLK_SRC6_OFFSET]
/* CLK_DIV6[31:28] -> 0=1/1 */
ldr r1, [r0, #CLK_DIV6_OFFSET]
mov r1, #
0x00000000
str r1, [r0, #CLK_DIV6_OFFSET]
#elif defined (CONFIG_MCP_H)
/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldr r1, [r0, #CLK_SRC6_OFFSET]
bic r1, r1, #(
0x3
<<
24
)
orr r1, r1, #
0x00000000
str r1, [r0, #CLK_SRC6_OFFSET]
/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldr r1, [r0, #CLK_DIV6_OFFSET]
bic r1, r1, #(
0xF
<<
28
)
bic r1, r1, #(
0x7
<<
12
) @; ONENAND_RATIO:
0
orr r1, r1, #
0x00000000
str r1, [r0, #CLK_DIV6_OFFSET]
#elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D)
/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
ldr r1, [r0, #CLK_SRC6_OFFSET]
bic r1, r1, #(
0x3
<<
24
)
orr r1, r1, #
0x01000000
str r1, [r0, #CLK_SRC6_OFFSET]
/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
ldr r1, [r0, #CLK_DIV6_OFFSET]
bic r1, r1, #(
0xF
<<
28
)
bic r1, r1, #(
0x7
<<
12
) @; ONENAND_RATIO:
0
orr r1, r1, #
0x30000000
str r1, [r0, #CLK_DIV6_OFFSET]
#elif defined (CONFIG_MCP_SINGLE) @ 这段定义了,分析分析
/* CLK_DIV6 */
ldr r1, [r0, #CLK_DIV6_OFFSET] @ 设置分频 Clock Divider Control Register(
0xe0100318
)
bic r1, r1, #(
0x7
<<
12
) @; ONENAND_RATIO:
0
@ 0DIVFLASH clock pider ratio,计算公式:SCLK_ONENAND = MOUTFLASH / (ONENAND_RATIO +
1
)
str r1, [r0, #CLK_DIV6_OFFSET]
#endif
mov pc, lr @ 返回到start.S
/*
* uart_asm_init: Initialize UART in asm mode, 115200bps fixed.
* void uart_asm_init(void)
*/
uart_asm_init:
/* set GPIO(GPA) to enable UART */
@ GPIO setting
for
UART
@ 串口引脚复用设置
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =
0x22222222
str r1, [r0, #GPA0CON_OFFSET]
ldr r1, =
0x2222
str r1, [r0, #GPA1CON_OFFSET]
// HP V210 use. SMDK not use.
#
if
defined(CONFIG_VOGUES)
ldr r1, =
0x100
str r1, [r0, #GPC0CON_OFFSET]
ldr r1, =
0x4
str r1, [r0, #GPC0DAT_OFFSET]
#endif
ldr r0, =ELFIN_UART_CONSOLE_BASE
@0xEC000000
mov r1, #
0x0
str r1, [r0, #UFCON_OFFSET]
str r1, [r0, #UMCON_OFFSET]
mov r1, #
0x3
str r1, [r0, #ULCON_OFFSET]
ldr r1, =
0x3c5
str r1, [r0, #UCON_OFFSET]
ldr r1, =UART_UBRDIV_VAL
str r1, [r0, #UBRDIV_OFFSET]
ldr r1, =UART_UDIVSLOT_VAL
str r1, [r0, #UDIVSLOT_OFFSET]
ldr r1, =
0x4f4f4f4f
str r1, [r0, #UTXH_OFFSET] @
'O'
mov pc, lr
/*
* Nand Interface Init for SMDKC110
*/
nand_asm_init:
/* Setting GPIO for NAND */
/* This setting is NAND initialze code at booting time in iROM. */
@ 设置IO BASE
ldr r0, =ELFIN_GPIO_BASE
ldr r1, [r0, #MP01CON_OFFSET]
bic r1, r1, #(
0xf
<<
8
)
orr r1, r1, #(
0x3
<<
8
)
str r1, [r0, #MP01CON_OFFSET]
ldr r1, [r0, #MP01PUD_OFFSET]
bic r1, r1, #(
0x3
<<
4
)
str r1, [r0, #MP01PUD_OFFSET]
ldr r1, [r0, #MP03CON_OFFSET]
bic r1, r1, #
0xFFFFFF
ldr r2, =
0x22222222
orr r1, r1, r2
str r1, [r0, #MP03CON_OFFSET]
ldr r1, [r0, #MP03PUD_OFFSET]
ldr r2, =
0x3fff
bic r1, r1, r2
str r1, [r0, #MP03PUD_OFFSET]
ldr r0, =ELFIN_NAND_BASE
ldr r1, [r0, #NFCONF_OFFSET]
ldr r2, =
0x777F
bic r1, r1, r2
ldr r2, =NFCONF_VAL
orr r1, r1, r2
str r1, [r0, #NFCONF_OFFSET]
ldr r1, [r0, #NFCONT_OFFSET]
ldr r2, =
0x707C7
bic r1, r1, r2
ldr r2, =NFCONT_VAL
orr r1, r1, r2
str r1, [r0, #NFCONT_OFFSET]
ldr r1, [r0, #NFCONF_OFFSET]
orr r1, r1, #
0x70
orr r1, r1, #
0x7700
str r1, [r0, #NFCONF_OFFSET]
ldr r1, [r0, #NFCONT_OFFSET]
orr r1, r1, #
0x03
str r1, [r0, #NFCONT_OFFSET]
mov pc, lr
/*
* Setting TZPC[TrustZone Protection Controller]
*/
tzpc_init:
ldr r0, =ELFIN_TZPC0_BASE
mov r1, #
0x0
str r1, [r0]
mov r1, #
0xff
str r1, [r0, #TZPC_DECPROT0SET_OFFSET]
str r1, [r0, #TZPC_DECPROT1SET_OFFSET]
str r1, [r0, #TZPC_DECPROT2SET_OFFSET]
ldr r0, =ELFIN_TZPC1_BASE
str r1, [r0, #TZPC_DECPROT0SET_OFFSET]
str r1, [r0, #TZPC_DECPROT1SET_OFFSET]
str r1, [r0, #TZPC_DECPROT2SET_OFFSET]
ldr r0, =ELFIN_TZPC2_BASE
str r1, [r0, #TZPC_DECPROT0SET_OFFSET]
str r1, [r0, #TZPC_DECPROT1SET_OFFSET]
str r1, [r0, #TZPC_DECPROT2SET_OFFSET]
str r1, [r0, #TZPC_DECPROT3SET_OFFSET]
ldr r0, =ELFIN_TZPC3_BASE
str r1, [r0, #TZPC_DECPROT0SET_OFFSET]
str r1, [r0, #TZPC_DECPROT1SET_OFFSET]
str r1, [r0, #TZPC_DECPROT2SET_OFFSET]
mov pc, lr
/*
* OneNAND Interface Init
*/
onenandcon_init:
@; GPIO setting
for
OneNAND
ldr r0, =ELFIN_GPIO_BASE
@0xE0200000
ldr r1, [r0, #MP01CON_OFFSET]
orr r1, r1, #
0x00550000
str r1, [r0, #MP01CON_OFFSET]
ldr r1, [r0, #MP03CON_OFFSET]
orr r1, r1, #
0x0550
orr r1, r1, #
0x00550000
str r1, [r0, #MP03CON_OFFSET]
ldr r1, =
0xFFFF
str r1, [r0, #MP01DRV_SR_OFFSET]
str r1, [r0, #MP03DRV_SR_OFFSET]
str r1, [r0, #MP06DRV_SR_OFFSET]
str r1, [r0, #MP07DRV_SR_OFFSET]
wait_orwb:
@; Read ONENAND_IF_STATUS
ldr r0, =ELFIN_ONENANDCON_BASE @;
0xB0600000
ldr r1, [r0, #ONENAND_IF_STATUS_OFFSET]
bic r1, r1, #
0xFFFFFFFE
cmp r1, #0x0
@; ORWB !=
0x0
bne wait_orwb
@; write
new
configuration to onenand system configuration1 register
ldr r1, =
0xF006
@; Sync.
ldr r2, =(ELFIN_ONENAND_BASE+
0x1E442
) @;
0x1E442
(REG_SYS_CONF1)
strh r1, [r2]
@; read one dummy halfword
ldrh r1, [r2]
ldrh r1, [r2]
@; write
new
configuration to ONENAND_IF_CTRL
ldr r0, =ELFIN_ONENANDCON_BASE @;
0xB0600000
@;ldr r1, =
0x2F006
@; ONENAND_IF_CTRL_REG_VAL (GCE off)
ldr r1, =
0x402F006
@; ONENAND_IF_CTRL_REG_VAL (GCE on)
str r1, [r0, #ONENAND_IF_CTRL_OFFSET]
mov pc, lr
后面是创建mmu映射列表代码,详见我的mmu博客
/********************************返回start.s****************************/
ldr r0, =0xE010E81C /* PS_HOLD_CONTROL register */
ldr r1, =0x00005301 /* PS_HOLD output high */
str r1, [r0]
/* get ready to call C functions */
ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
sub sp, sp, #12
mov fp, #0 /* no previous frame, so fp=0 */
@第二次设置栈,此次设置的栈在SDRAM内存中,内存上面一初始化
/* 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.
*/
ldr r0, =0xff000fff
bic r1, pc, r0 /* r0 <- current base addr of code */
ldr r2, _TEXT_BASE /* r1 <- original base addr in ram */
bic r2, r2, r0 /* r0 <- current base addr of code */
cmp r1, r2 /* compare r0, r1 */
beq after_copy /* r0 == r1 then skip flash copy */
判断当前程序是否已经运行在内存中了,如果不是则要重定位代码