您的位置:首页 > 其它

S5PV210(TQ210)U-BOOT第一阶段

2013-05-22 15:57 483 查看
地址:http://write.blog.csdn.net/postedit/8960858

#include <config.h>            //#include <configs/TQ210.h>

#include <version.h>

#include <asm/proc/domain.h>

#include <regs.h>

/* 内部96K SRAM,有一信息头,共16字节。前4字节为BL1大小(此处为.word 0x2000,即BL1大小为8K);4到8字节为保留位,

默认为0;8到12字节为checkSum,校验位,此处默认为0;最后4字节为保留字节,默认为0 */

#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)

 .word 0x2000

 .word 0x0

 .word 0x0

 .word 0x0

#endif

.globl _start

_start: b reset

reset:

 /*

  * set the cpu to SVC32 mode and IRQ & FIQ disable,设置CPU为管理模式,禁止中断及快速中断

  */

 @;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_init_crit:

 bl disable_l2cache

  .global disable_l2cache

  disable_l2cache:

  mrc     p15, 0, r0, c1, c0, 1 @具体参照DDI0344K_cortex_a8_r3p2_trm.pdf文件,Auxiliary Control辅助控制

  bic     r0, r0, #(1<<1) @将bit1清零

  mcr     p15, 0, r0, c1, c0, 1 @L2 cache disabled

  mov pc, lr

 bl set_l2cache_auxctrl_cycle

  .global set_l2cache_auxctrl_cycle

  set_l2cache_auxctrl_cycle:

  mrc  p15, 1, r0, c9, c0, 2  @L2 Cache Auxiliary Control

  bic  r0, r0, #(0x1<<29)     @two cycles, default

  bic  r0, r0, #(0x1<<21)     @disables parity or ECC, default

  bic  r0, r0, #(0x7<<6)      @tag RAM latency =4 cycles

  bic  r0, r0, #(0x7<<0)      @Data RAM latency = 8 cycles

  mcr  p15, 1, r0, c9, c0, 2

  mov     pc,lr

 

 bl enable_l2cache

  .global enable_l2cache

  enable_l2cache:

  mrc     p15, 0, r0, c1, c0, 1

  orr     r0, r0, #(1<<1)

  mcr     p15, 0, r0, c1, c0, 1  @L2 cache enabled

  mov     pc, lr

 

 /*

 * Invalidate L1 I/D

 */

 mov r0, #0                  @ set up for MCR

 mcr p15, 0, r0, c8, c7, 0   @ Invalidate Inst-TLB and Data-TLB,无效指令TLB与数据TLB

 mcr p15, 0, r0, c7, c5, 0   @ Invalidate all instruction caches to PoU. Also flushes branch target cache

                                @无效所有指令缓存,刷新分支目标缓存

 /*

 * disable MMU stuff and caches

 */

 mrc p15, 0, r0, c1, c0, 0   @ Control

 bic r0, r0, #0x00002000     @ clear bits 13 (--V-),正常异常向量选择,复位值,向量基地址寄存器决定地址范围

 bic r0, r0, #0x00000007     @ clear bits 2:0 (-CAM),关闭数据缓存,禁止对其错误检查,关闭MMU

 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

 /* Read booting information */

 ldr r0, =PRO_ID_BASE        @0xE0000000

 ldr r1, [r0,#OMR_OFFSET]    @R0+0x04;引导模式寄存器地址,此条命令为读寄存器状态

 bic r2, r1, #0xffffffc1     @此条命令为读OM引脚配置状态,将OM[0]位清零,选择X-TAL

 

#ifdef CONFIG_TQ210_IIC_PM_CHIP

 /* PS_HOLD(GPJ2_5) set to output high,电源管理芯片PS_HOLD引脚*/

 ldr  r0, =ELFIN_GPIO_BASE@ 0xE02000000

 ldr  r1, =0x00100000

 str  r1, [r0, #GPJ2CON_OFFSET]@ 0xE02000000+0X280;将R1寄存器值存入GPJ2CON,设置为输出.

 

 ldr  r1, =0x0400

 str  r1, [r0, #GPJ2PUD_OFFSET]@ 0xE02000000+0X288;将R1寄存器值存入GPJ2PUD,设置为上拉

 ldr  r1, =0x20

 str  r1, [r0, #GPJ2DAT_OFFSET]@ 0xE02000000+0X284;将R1寄存器值存入GPJ2DAT,设置为1

#endif /* CONFIG_TQ210_IIC_PM_CHIP */

 /* NAND BOOT根据OM引脚配置状态来给R3寄存器赋予代表系统是从何种外部存储器启动的配置值,

 确定从哪个介质中copy U-Boot到RAM ,识别各种启动方式,并将识别到的启动识别码写入R3中 */

 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 

 /* Uart BOOTONG failed */

 cmp     r2, #(0x1<<4)

 moveq   r3, #BOOT_SEC_DEV

 

 ldr r0, =INF_REG_BASE

 str r3, [r0, #INF_REG3_OFFSET]@  将R3存入INFORM3(0xE010_F00C)中 

 /*

  * 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 /* lowlevel_init.S go setup pll,mux,memory,完成关看门狗,电源模块初始化,时钟初始化,

      串口初始化,sdram初始化,NANDFLASH初始化 */

    .globl lowlevel_init

   lowlevel_init:

   push {lr}

   /* check reset status,检查复位状态 */

   ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)@将R0值设为0XE010A000,为复位状态寄存器,反映了各位复位条件的状态。

   ldr r1, [r0]

   bic r1, r1, #0xfff6ffff  @保留bit16及bit19位,其他位清零

   cmp r1, #0x10000         @ARM reset from DEEP-IDLE

   beq wakeup_reset_pre

   cmp r1, #0x80000      @Reset by SLEEP mode wake-up

   beq wakeup_reset_from_didle

   /* IO Retention release,不太明白 */

   ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)@0xE010_E000,OTHERS

   ldr r1, [r0]

   ldr r2, =IO_RET_REL                              @((1 << 31) | (1 << 29) | (1 << 28))

   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, 配置sram引脚,16位数据宽度,SROM_ADDR_16to22[ ]为复用引脚,22位地址宽度*/

   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]    @引脚功能SROM_ADDR_16to22[ ]

   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]    @引脚功能SROM_ADDR_16to22[ ]

   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)@0xE010_E81C,PS_HOLD_CONTROL寄存器

   ldr r1, [r0]

   orr r1, r1, #0x300

   orr r1, r1, #0x1 

   str r1, [r0]   @将寄存器bit8,bit9,bit1置1;

   /* 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     1f   /* r0 == r1 then skip sdram init   */

   

   /* init PMIC chip */

   #ifdef CONFIG_TQ210_IIC_PM_CHIP

   bl PMIC_InitIp    @电源管理单元初始化

   #endif

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

   系统时钟初始化后频率为:ARMCLK=1G; SCLKA2M=200M; HCLK_MSYS=200M; PCLK_MSYS=100M;HCLK_DSYS=166M;

   PCLK_DSYS=83M;HCLK_PSYS=133M;PCLK_PSYS=66.5M

   */

   bl system_clock_init @1)选择时钟源;2)设置锁定时间;3)设置APLL,MPLL,VPLL频率;4)配置各模块分频;5)开ACF;6)耗时等待稳定 

    system_clock_init:

    

     ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000

     /* Set Mux to FIN */

     ldr r1, =0x0

     str r1, [r0, #CLK_SRC0_OFFSET]   @CLK_SRC0,时钟源选择

     ldr r1, =APLL_LOCKTIME_VAL

     str r1, [r0, #APLL_LOCK_OFFSET]  @将APLL_LOCK,APLL锁定时间设置为0x2cf

     /* Disable PLL */

     ldr r1, =0x0

     str r1, [r0, #APLL_CON0_OFFSET]  @APLL_CON0 设置APLL使能锁存,锁定时间使能,APLL频率设置,此处将APLL禁止

     ldr r1, =0x0

     str r1, [r0, #MPLL_CON_OFFSET]   @MPLL_CON0 设置APLL使能锁存,锁定时间使能,APLL频率设置,此处将MPLL禁止

     ldr    r1, [r0, #CLK_DIV0_OFFSET]

     ldr r2, =CLK_DIV0_MASK

     bic r1, r1, r2

     ldr r2, =CLK_DIV0_VAL

     orr r1, r1, r2

     str r1, [r0, #CLK_DIV0_OFFSET]  @时钟分频控制寄存器CLK _DIV0,(0<<APLL_RATIO)|(4<<A2M_RATIO)|

             @(4<<HCLK_MSYS_RATIO)|(1<<PCLK_MSYS_RATIO)|(3<<HCLK_DSYS_RATIO)|

             @(1<<PCLK_DSYS_RATIO)|(4<<HCLK_PSYS_RATIO)|(1<<PCLK_PSYS_RATIO))

     ldr r1, =APLL_VAL

     str r1, [r0, #APLL_CON0_OFFSET]  @APLL_CON0 ,使能APLL,设置APLL频率,即MDIV=7D;PDIV=3;SDIV=1;APLL频率为1G

     ldr r1, =MPLL_VAL

     str r1, [r0, #MPLL_CON_OFFSET]   @MPLL_CON0 ,使能MPLL,设置MPLL频率,即MDIV=29B;PDIV=C;SDIV=1;MPLL频率为667M

     ldr r1, =VPLL_VAL

     str r1, [r0, #VPLL_CON_OFFSET]   @VPLL_CON0 ,使能VPLL,设置VPLL频率,即MDIV=6C;PDIV=6;SDIV=3;MPLL频率为108M

    #if defined(CONFIG_EVT1)

     ldr r1, =AFC_ON

     str r1, [r0, #APLL_CON1_OFFSET]  @APLL_CON1 ,设置为0,开AFC,AFC是干什么用的?

    #endif

     mov r1, #0x10000                  /*耗时等待稳定*/

    1: subs r1, r1, #1

     bne 1b

     

     ldr r1, [r0, #CLK_SRC0_OFFSET]

     ldr r2, =0x10001111

     orr r1, r1, r2

     str r1, [r0, #CLK_SRC0_OFFSET]  @设置MUXVPLL,MUXEPLL,MUXMPLL,MUXAPLL为FOUTxPLL

     

    #if defined(CONFIG_MCP_SINGLE)

     /* CLK_DIV6 */

     ldr r1, [r0, #CLK_DIV6_OFFSET]  @时钟分频寄存器CLK _DIV6,SCLK_ONENAND = MOUTFLASH / (ONENAND_RATIO + 1)

     bic r1, r1, #(0x7<<12) @; ONENAND_RATIO: 0

     str r1, [r0, #CLK_DIV6_OFFSET]

    #endif 

     mov pc, lr

   bl mem_ctrl_asm_init @cpu_init.s SDRAM初始化

  1:

   /* for UART */

   bl uart_asm_init

    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]

     ldr r0, =ELFIN_UART_CONSOLE_BASE  @0xEC000000

     mov r1, #0x0

     str r1, [r0, #UFCON_OFFSET]    @USART FIFO控制寄存器,禁止FIFO

     str r1, [r0, #UMCON_OFFSET]    @USART MODEM控制寄存器,禁止MODEM及AFC

     mov r1, #0x3

     str r1, [r0, #ULCON_OFFSET]    @ULCON0,设置为普通模式,无奇偶校验位,1位停止位,8位数据位

     ldr r1, =0x3c5

     str r1, [r0, #UCON_OFFSET]     @时钟源为PCLK,TX,RX中断类型为电平触发,接收错误状态中断使能,

               @接收超时使能,RX与TX模式为中断请求或轮询

     ldr r1, =UART_UBRDIV_VAL

     str r1, [r0, #UBRDIV_OFFSET]    @设置模特率,设置波特率为115200,则UBRDIV=(66.7x10^5/115200/16)-1取整,

             @此处求出的值为35,不太清楚为什么设置为34?

     ldr r1, =UART_UDIVSLOT_VAL

     str r1, [r0, #UDIVSLOT_OFFSET]   @UDIVSLOT=((66.7x10^5/115200/16)-1取余),此处求出为3,不明白为什么设置为0XDDDD?

     ldr r1, =0x4f4f4f4f

     str r1, [r0, #UTXH_OFFSET]  @'O',@发送“0x4f4f4f4f”

     mov pc, lr

   

   bl tzpc_init         @TrustZone Protection Controller,安全模式,取消存储保护区域,无安全区域

   bl nand_asm_init     @nand简单的初始化

   

   /* 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}

 

 /*不清楚作用,别的文档标注:PS_HOLD输出高电平,PS_HOLD使能。PMIC相关*/

 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,0x23E0_0000 */

 sub sp, sp, #12

 mov fp, #0   /* no previous frame, so fp=0 */

 /* 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  /* _TEXT_BASE:0xC3E0_0000,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   */

#if defined(CONFIG_EVT1)

 /* If BL1 was copied from SD/MMC CH2 */

 ldr r0, =0xD0037488    @V210_SDMMC_BASE,Current boot channel

 ldr r1, [r0]

 ldr r2, =0xEB200000    @SDMA System Address

 cmp r1, r2

 beq     mmcsd_boot

#endif

/*判断启动类型,根据启动方式不同,跳转不同执行*/

 ldr  r0, =INF_REG_BASE

 ldr  r1, [r0, #INF_REG3_OFFSET]

 cmp  r1, #BOOT_NAND  /* 0x0 => boot device is nand */

 beq  nand_boot

 cmp  r1, #BOOT_ONENAND /* 0x1 => boot device is onenand */

 beq  onenand_boot

 cmp  r1, #BOOT_MMCSD

 beq  mmcsd_boot

 cmp  r1, #BOOT_NOR

 beq  nor_boot

 cmp  r1, #BOOT_SEC_DEV

 beq  mmcsd_boot   

 nand_boot:      @copy_from_nand

 mov  r0, #0x1000

 bl  copy_from_nand

 b  after_copy

 onenand_boot:    @onenand_bl2_copy

 bl  onenand_bl2_copy

 b  after_copy

 mmcsd_boot:     @movi_bl2_copy

#if DELETE

 ldr  sp, _TEXT_PHY_BASE     

 sub  sp, sp, #12

 mov  fp, #0

#endif

 bl  movi_bl2_copy

 b  after_copy

 nor_boot:    @read_hword

 bl  read_hword

 b  after_copy

 

after_copy:

#if defined(CONFIG_ENABLE_MMU)

enable_mmu:

 /* enable domain access */

 ldr r5, =0x0000ffff

 mcr p15, 0, r5, c3, c0, 0  @load domain access register,定义使能域的访问权限,Manager

 /* Set the TTB register */

 ldr r0, _mmu_table_base    @映射页表地址

  /*定义一个名为 FL_SECTION_ENTRY 的宏,参数为 base,ap,d,c,b,内容为

  (\base << 20) | (\ap << 10) | \ (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1),

  根据控制参数建立一个字大小的描述符,以.endm结束*/

  .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

  /*将这一部分代码都编译进以.mmudata命名的段中(定义MMU数据段,在lds文件里面用到了,定义了

  mmu_table放置的位置,“a”表示这是一个需要鉴权的段),权限为a,并确保14喂对齐*/ 

  .section .mmudata, "a"

  .align 14

  

 .globl mmu_table

  mmu_table:

  .set __base,0    @__base设置为0,物理地址高12位

  // Access for iRAM

  .rept 0x100      @循环0x100次

  FL_SECTION_ENTRY __base,3,0,0,0    @页表描述符

  .set __base,__base+1

  .endr

  // Not Allowed

  .rept 0x200 - 0x100

  .word 0x00000000

  .endr

  .set __base,0x200

  // should be accessed

  .rept 0x600 - 0x200

  FL_SECTION_ENTRY __base,3,0,1,1

  .set __base,__base+1

  .endr

  

  .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

  .set __base,0xB00

  .rept 0xc00 - 0xb00

  FL_SECTION_ENTRY __base,3,0,0,0

  .set __base,__base+1

  .endr

  

  .set __base,0x200

  // 256MB for SDRAM with cacheable

  .rept 0xD00 - 0xC00

  FL_SECTION_ENTRY __base,3,0,1,1

  .set __base,__base+1

  .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 

 /*不太明白为什么这么求的*/

 ldr r1, =CFG_PHY_UBOOT_BASE    @0xc3e00000

 ldr r2, =0xfff00000 

 bic r0, r0, r2   

 orr r1, r0, r1

 mcr p15, 0, r1, c2, c0, 0

 /* Enable the MMU,开MMU*/

mmu_on:

 mrc p15, 0, r0, c1, c0, 0

 orr r0, r0, #1

 mcr p15, 0, r0, c1, c0, 0

 nop

 nop

 nop

 nop

#endif

skip_hw_init:

 /* Set up the stack          */

stack_setup:  @建立栈,栈的设置灵活性很大,只要将SP指向一段没有使用的内存即可

#if defined(CONFIG_MEMORY_UPPER_CODE)

 ldr sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)

#endif

clear_bss:    @清BSS

 ldr r0, _bss_start  /* find start of bss segment        */

 ldr r1, _bss_end  /* stop here                        */

 mov  r2, #0x00000000  /* clear                            */

clbss_l:

 str r2, [r0]  /* clear loop...                    */

 add r0, r0, #4

 cmp r0, r1

 ble clbss_l

 ldr pc, _start_armboot @跳转到start_armboot处继续运行。

_start_armboot:

 .word start_armboot

讨论加QQ:1735613836
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: