s5pv210-uboot分析(一)

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到<span style="font-family: Arial, Helvetica, sans-serif;">DRAM</span>中_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   */

判断当前程序是否已经运行在内存中了,如果不是则要重定位代码

猜你喜欢

转载自blog.csdn.net/coolperl/article/details/82532557