精华内容
下载资源
问答
  • UBOOT启动流程

    千次阅读 2018-02-24 15:18:52
    uboot启动流程分析

    新版UBOOT启动流程


    转载请注明地址: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:


                                                                                               图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。


                                                                                            图2


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


                                                                                        图3


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


    start.S的完整代码:

    1. /* 
    2.  * armboot - Startup Code for OMAP3530/ARM Cortex CPU-core 
    3.  * 
    4.  * Copyright (c) 2004   Texas Instruments <r-woodruff2@ti.com> 
    5.  * 
    6.  * Copyright (c) 2001   Marius Gröger <mag@sysgo.de> 
    7.  * Copyright (c) 2002   Alex Züpke <azu@sysgo.de> 
    8.  * Copyright (c) 2002   Gary Jennejohn <garyj@denx.de> 
    9.  * Copyright (c) 2003   Richard Woodruff <r-woodruff2@ti.com> 
    10.  * Copyright (c) 2003   Kshitij <kshitij@ti.com> 
    11.  * Copyright (c) 2006-2008 Syed Mohammed Khasim <x0khasim@ti.com> 
    12.  * 
    13.  * See file CREDITS for list of people who contributed to this 
    14.  * project. 
    15.  * 
    16.  * This program is free software; you can redistribute it and/or 
    17.  * modify it under the terms of the GNU General Public License as 
    18.  * published by the Free Software Foundation; either version 2 of 
    19.  * the License, or (at your option) any later version. 
    20.  * 
    21.  * This program is distributed in the hope that it will be useful, 
    22.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    24.  * GNU General Public License for more details. 
    25.  * 
    26.  * You should have received a copy of the GNU General Public License 
    27.  * along with this program; if not, write to the Free Software 
    28.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
    29.  * MA 02111-1307 USA 
    30.  */  
    31.   
    32. #include <asm-offsets.h>  
    33. #include <config.h>  
    34. #include <version.h>  
    35. #include <asm/system.h>  
    36. #include <linux/linkage.h>  
    37. #include <s5pv210.h>  
    38.   
    39. #ifndef CONFIG_ENABLE_MMU  
    40. #ifndef CONFIG_PHY_UBOOT_BASE  
    41. #define CONFIG_PHY_UBOOT_BASE   CONFIG_UBOOT_BASE  
    42. #endif /* CONFIG_PHY_UBOOT_BASE */  
    43. #endif /* CONFIG_ENABLE_MMU */  
    44.   
    45.   
    46. .globl _start  
    47. _start: b   reset  
    48.     ldr pc, _undefined_instruction  
    49.     ldr pc, _software_interrupt  
    50.     ldr pc, _prefetch_abort  
    51.     ldr pc, _data_abort  
    52.     ldr pc, _not_used  
    53.     ldr pc, _irq  
    54.     ldr pc, _fiq  
    55. #ifdef CONFIG_SPL_BUILD  
    56. _undefined_instruction: .word _undefined_instruction  
    57. _software_interrupt:    .word _software_interrupt  
    58. _prefetch_abort:    .word _prefetch_abort  
    59. _data_abort:        .word _data_abort  
    60. _not_used:      .word _not_used  
    61. _irq:           .word _irq  
    62. _fiq:           .word _fiq  
    63. _pad:           .word 0x12345678 /* now 16*4=64 */  
    64. #else  
    65. _undefined_instruction: .word undefined_instruction  
    66. _software_interrupt:    .word software_interrupt  
    67. _prefetch_abort:    .word prefetch_abort  
    68. _data_abort:        .word data_abort  
    69. _not_used:      .word not_used  
    70. _irq:           .word irq  
    71. _fiq:           .word fiq  
    72. _pad:           .word 0x12345678 /* now 16*4=64 */  
    73. #endif  /* CONFIG_SPL_BUILD */  
    74.   
    75. .global _end_vect  
    76. _end_vect:  
    77.   
    78.     .balignl 16,0xdeadbeef  
    79. /************************************************************************* 
    80.  * 
    81.  * Startup Code (reset vector) 
    82.  * 
    83.  * do important init only if we don’t start from memory! 
    84.  * setup Memory and board specific bits prior to relocation. 
    85.  * relocate armboot to ram 
    86.  * setup stack 
    87.  * 
    88.  *************************************************************************/  
    89.   
    90. .globl _TEXT_BASE  
    91. _TEXT_BASE:  
    92.     .word   CONFIG_SYS_TEXT_BASE  
    93. /* 
    94.  * Below variable is very important because we use MMU in U-Boot. 
    95.  * Without it, we cannot run code correctly before MMU is ON. 
    96.  * by scsuh. 
    97.  */  
    98.  .globl _TEXT_PHY_BASE  
    99. _TEXT_PHY_BASE:  
    100.     .word   CONFIG_PHY_UBOOT_BASE  
    101.   
    102. /* 
    103.  * These are defined in the board-specific linker script. 
    104.  */  
    105. .globl _bss_start_ofs  
    106. _bss_start_ofs:  
    107.     .word __bss_start - _start  
    108.   
    109. .global _image_copy_end_ofs  
    110. _image_copy_end_ofs:  
    111.     .word   __image_copy_end - _start  
    112.   
    113. .globl _bss_end_ofs  
    114. _bss_end_ofs:  
    115.     .word __bss_end__ - _start  
    116.   
    117. .globl _end_ofs  
    118. _end_ofs:  
    119.     .word _end - _start  
    120.   
    121. #ifdef CONFIG_USE_IRQ  
    122. /* IRQ stack memory (calculated at run-time) */  
    123. .globl IRQ_STACK_START  
    124. IRQ_STACK_START:  
    125.     .word   0x0badc0de  
    126.   
    127. /* IRQ stack memory (calculated at run-time) */  
    128. .globl FIQ_STACK_START  
    129. FIQ_STACK_START:  
    130.     .word 0x0badc0de  
    131. #endif  
    132.   
    133. /* IRQ stack memory (calculated at run-time) + 8 bytes */  
    134. .globl IRQ_STACK_START_IN  
    135. IRQ_STACK_START_IN:  
    136.     .word   0x0badc0de  
    137.   
    138. /* 
    139.  * the actual reset code 
    140.  */  
    141.   
    142. reset:  
    143.     bl  save_boot_params  
    144.   
    145.     /* 
    146.      * set the cpu to SVC32 mode and IRQ & FIQ disable 
    147.      */  
    148.     msr cpsr_c, #0xd3       @ I & F disable, Mode: 0x13 - SVC  
    149.   
    150. /* 
    151.  * Setup vector: 
    152.  * (OMAP4 spl TEXT_BASE is not 32 byte aligned. 
    153.  * Continue to use ROM code vector only in OMAP4 spl) 
    154.  */  
    155. #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))  
    156.     /* Set V=0 in CP15 SCTRL register - for VBAR to point to vector */  
    157.     mrc p15, 0, r0, c1, c0, 0   @ Read CP15 SCTRL Register  
    158.     bic r0, #CR_V       @ V = 0  
    159.     mcr p15, 0, r0, c1, c0, 0   @ Write CP15 SCTRL Register  
    160.   
    161.     /* Set vector address in CP15 VBAR register */  
    162.     ldr r0, =_start  
    163.     mcr p15, 0, r0, c12, c0, 0  @Set VBAR  
    164. #endif  
    165. /***************************** zsy add 2013-3-14 *****************************/  
    166. #ifndef CONFIG_EVT1  
    167.     bl  disable_l2cache  
    168.   
    169.     mov r0, #0x0    @  
    170.     mov r1, #0x0    @ i  
    171.     mov r3, #0x0  
    172.     mov r4, #0x0  
    173. lp1:  
    174.     mov r2, #0x0    @ j  
    175. lp2:  
    176.     mov r3, r1, LSL #29     @ r3 = r1(i) <<29  
    177.     mov r4, r2, LSL #6      @ r4 = r2(j) <<6  
    178.     orr r4, r4, #0x2        @ r3 = (i<<29)|(j<<6)|(1<<1)  
    179.     orr r3, r3, r4  
    180.     mov r0, r3          @ r0 = r3  
    181.     bl  CoInvalidateDCacheIndex  
    182.     add r2, #0x1        @ r2(j)++  
    183.     cmp r2, #1024       @ r2 < 1024  
    184.     bne lp2         @ jump to lp2  
    185.     add r1, #0x1        @ r1(i)++  
    186.     cmp r1, #8          @ r1(i) < 8  
    187.     bne lp1         @ jump to lp1  
    188.   
    189.     bl  set_l2cache_auxctrl  
    190.   
    191.     bl  enable_l2cache  
    192. #endif  
    193.   
    194.     bl  disable_l2cache  
    195.   
    196.     bl  set_l2cache_auxctrl_cycle  
    197.   
    198.     bl  enable_l2cache  
    199.   
    200.     bl  zsy210_iic_pm_open  
    201.   
    202. /**************************  end of zsy add 2013-3-14 ****************************/  
    203.     /* the mask ROM code should have PLL and others stable */  
    204. #ifndef CONFIG_SKIP_LOWLEVEL_INIT  
    205.     bl  cpu_init_cp15  
    206.     bl  cpu_init_crit  
    207. #endif  
    208. /***************************  zsy add 2013-3-14  ********************************/  
    209.     /* 读取启动模式信息 */  
    210.     ldr r0, =PRO_ID_BASE  
    211.     ldr r1, [r0,#OMR_OFFSET]  
    212.     bic r2, r1, #0xffffffc1  
    213.   
    214.     /* NAND BOOT */  
    215.     cmp r2, #0x0        @ 512B 4-cycle  
    216.     moveq   r3, #BOOT_NAND  
    217.   
    218.     cmp r2, #0x2        @ 2KB 5-cycle  
    219.     moveq   r3, #BOOT_NAND  
    220.   
    221.     cmp r2, #0x4        @ 4KB 5-cycle   8-bit ECC  
    222.     moveq   r3, #BOOT_NAND  
    223.   
    224.     cmp r2, #0x6        @ 4KB 5-cycle   16-bit ECC  
    225.     moveq   r3, #BOOT_NAND  
    226.   
    227.     cmp r2, #0x8        @ OneNAND Mux  
    228.     moveq   r3, #BOOT_ONENAND  
    229.   
    230.     /* SD/MMC BOOT */  
    231.     cmp     r2, #0xc  
    232.     moveq   r3, #BOOT_MMCSD  
    233.   
    234.     /* NOR BOOT */  
    235.     cmp     r2, #0x14  
    236.     moveq   r3, #BOOT_NOR  
    237.   
    238.     /* Uart BOOTONG failed */  
    239.     cmp     r2, #(0x1<<4)  
    240.     moveq   r3, #BOOT_SEC_DEV  
    241.   
    242.     ldr r0, =INF_REG_BASE  
    243.     str r3, [r0, #INF_REG3_OFFSET]  
    244.   
    245.     ldr r0, =0xE010E81C  /* PS_HOLD_CONTROL register */  
    246.     ldr r1, =0x00005301  /* PS_HOLD output high */  
    247.     str r1, [r0]  
    248.   
    249.     /* when we already run in ram, we don’t need to relocate U-Boot. 
    250.      * and actually, memory controller must be configured before U-Boot 
    251.      * is running in ram. 
    252.      */  
    253.     ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)  
    254.     bic sp, sp, #7 /* 8-byte alignment for ABI compliance */  
    255.     ldr r0,=0x00000000  
    256.   
    257.     ldr r1, =0xff000fff  
    258.     bic r2, pc, r1      /* r0 <- current base addr of code */  
    259.     ldr r3, _TEXT_BASE      /* r1 <- original base addr in ram */  
    260.     bic r3, r3, r1      /* r0 <- current base addr of code */  
    261.     cmp r2, r3                  /* compare r0, r1     */  
    262.     beq run_in_ram          /* r0 == r1 then skip sdram init   */  
    263.   
    264. #if defined(CONFIG_EVT1)  
    265.     /* If BL1 was copied from SD/MMC CH2 */  
    266.     ldr r0, =0xD0037488  
    267.     ldr r1, [r0]  
    268.     ldr r2, =0xEB200000  
    269.     cmp r1, r2  
    270.     beq mmcsd_boot  
    271. #endif  
    272.   
    273.     ldr r0, =INF_REG_BASE  
    274.     ldr r1, [r0, #INF_REG3_OFFSET]  
    275.     cmp r1, #BOOT_NAND      /* 0x0 => boot device is nand */  
    276.     beq nand_boot  
    277.     cmp r1, #BOOT_ONENAND   /* 0x1 => boot device is onenand */  
    278.     beq onenand_boot  
    279.     cmp r1, #BOOT_MMCSD  
    280.     beq mmcsd_boot  
    281.     cmp r1, #BOOT_NOR  
    282.     beq nor_boot  
    283.     cmp r1, #BOOT_SEC_DEV  
    284.     beq mmcsd_boot  
    285.   
    286. nand_boot:  
    287.     bl  ledon_1  
    288.     bl  board_init_f_nand  
    289.   
    290. mmcsd_boot:  
    291.     bl  ledon_1  
    292.     bl  board_init_f_movi  
    293.   
    294. nor_boot:  
    295.     bl  ledon  
    296. onenand_boot:  
    297.     bl  ledon  
    298.   
    299. /************************************************************************* 
    300.  * 
    301.  * after_copy 
    302.  * 
    303.  *************************************************************************/  
    304. run_in_ram:  
    305.   
    306. #if defined(CONFIG_ENABLE_MMU)  
    307. enable_mmu:  
    308.     /* enable domain access */  
    309.     ldr r5, =0x0000ffff  
    310.     mcr p15, 0, r5, c3, c0, 0       @load domain access register  
    311.   
    312.     /* Set the TTB register */  
    313.     ldr r0, _mmu_table_base  
    314.     ldr r1, =CONFIG_PHY_UBOOT_BASE  
    315.     ldr r2, =0xfff00000  
    316.     bic r0, r0, r2  
    317.     orr r1, r0, r1  
    318.     mcr p15, 0, r1, c2, c0, 0  
    319.   
    320.     /* Enable the MMU */  
    321. mmu_on:  
    322.     mrc p15, 0, r0, c1, c0, 0  
    323.     orr r0, r0, #1  
    324.     mcr p15, 0, r0, c1, c0, 0  
    325.     nop  
    326.     nop  
    327.     nop  
    328.     nop  
    329. #endif  
    330.     bl ledon_2  
    331.     bl _main  
    332. /**************************  end of zsy add 2013-3-14 ****************************/  
    333. /*——————————————————————————*/  
    334.   
    335. #ifndef CONFIG_SPL_BUILD  
    336. /* 
    337.  * void relocate_code (addr_sp, gd, addr_moni) 
    338.  * 
    339.  * This “function” does not return, instead it continues in RAM 
    340.  * after relocating the monitor code. 
    341.  * 
    342.  */  
    343. ENTRY(relocate_code)  
    344.     mov r4, r0  /* save addr_sp */  
    345.     mov r5, r1  /* save addr of gd */  
    346.     mov r6, r2  /* save addr of destination */  
    347.   
    348.     adr r0, _start  
    349.     cmp r0, r6  
    350.     moveq   r9, #0      /* no relocation. relocation offset(r9) = 0 */  
    351.     beq relocate_done       /* skip relocation */  
    352.     mov r1, r6          /* r1 <- scratch for copy_loop */  
    353.     ldr r3, _image_copy_end_ofs  
    354.     add r2, r0, r3      /* r2 <- source end address      */  
    355.   
    356. copy_loop:  
    357.     ldmia   r0!, {r9-r10}       /* copy from source address [r0]    */  
    358.     stmia   r1!, {r9-r10}       /* copy to   target address [r1]    */  
    359.     cmp r0, r2          /* until source end address [r2]    */  
    360.     blo copy_loop  
    361.   
    362.     /* 
    363.      * fix .rel.dyn relocations 
    364.      */  
    365.     ldr r0, _TEXT_BASE      /* r0 <- Text base */  
    366.     sub r9, r6, r0      /* r9 <- relocation offset */  
    367.     ldr r10, _dynsym_start_ofs  /* r10 <- sym table ofs */  
    368.     add r10, r10, r0        /* r10 <- sym table in FLASH */  
    369.     ldr r2, _rel_dyn_start_ofs  /* r2 <- rel dyn start ofs */  
    370.     add r2, r2, r0      /* r2 <- rel dyn start in FLASH */  
    371.     ldr r3, _rel_dyn_end_ofs    /* r3 <- rel dyn end ofs */  
    372.     add r3, r3, r0      /* r3 <- rel dyn end in FLASH */  
    373. fixloop:  
    374.     ldr r0, [r2]        /* r0 <- location to fix up, IN FLASH! */  
    375.     add r0, r0, r9      /* r0 <- location to fix up in RAM */  
    376.     ldr r1, [r2, #4]  
    377.     and r7, r1, #0xff  
    378.     cmp r7, #23         /* relative fixup? */  
    379.     beq fixrel  
    380.     cmp r7, #2          /* absolute fixup? */  
    381.     beq fixabs  
    382.     /* ignore unknown type of fixup */  
    383.     b   fixnext  
    384. fixabs:  
    385.     /* absolute fix: set location to (offset) symbol value */  
    386.     mov r1, r1, LSR #4      /* r1 <- symbol index in .dynsym */  
    387.     add r1, r10, r1     /* r1 <- address of symbol in table */  
    388.     ldr r1, [r1, #4]        /* r1 <- symbol value */  
    389.     add r1, r1, r9      /* r1 <- relocated sym addr */  
    390.     b   fixnext  
    391. fixrel:  
    392.     /* relative fix: increase location by offset */  
    393.     ldr r1, [r0]  
    394.     add r1, r1, r9  
    395. fixnext:  
    396.     str r1, [r0]  
    397.     add r2, r2, #8      /* each rel.dyn entry is 8 bytes */  
    398.     cmp r2, r3  
    399.     blo fixloop  
    400.   
    401. relocate_done:  
    402.   
    403.     bx  lr   /*返回到从定位的高端地址执行新的boot code ??*/
    404.   
    405. _rel_dyn_start_ofs:  
    406.     .word __rel_dyn_start - _start  
    407. _rel_dyn_end_ofs:  
    408.     .word __rel_dyn_end - _start  
    409. _dynsym_start_ofs:  
    410.     .word __dynsym_start - _start  
    411. ENDPROC(relocate_code)  
    412.   
    413. #endif  
    414.   
    415. ENTRY(c_runtime_cpu_setup)  
    416. /* 
    417.  * If I-cache is enabled invalidate it 
    418.  */  
    419. #ifndef CONFIG_SYS_ICACHE_OFF  
    420.     mcr p15, 0, r0, c7, c5, 0   @ invalidate icache  
    421.     mcr     p15, 0, r0, c7, c10, 4  @ DSB  
    422.     mcr     p15, 0, r0, c7, c5, 4   @ ISB  
    423. #endif  
    424. /* 
    425.  * Move vector table 
    426.  */  
    427. #if !defined(CONFIG_TEGRA20)  
    428.     /* Set vector address in CP15 VBAR register */  
    429.     ldr     r0, =_start  
    430.     add     r0, r0, r9  
    431.     mcr     p15, 0, r0, c12, c0, 0  @Set VBAR  
    432. #endif /* !Tegra20 */  
    433.   
    434.     bx  lr  
    435.   
    436. ENDPROC(c_runtime_cpu_setup)  
    437.   
    438. /************************************************************************* 
    439.  * 
    440.  * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) 
    441.  *  __attribute__((weak)); 
    442.  * 
    443.  * Stack pointer is not yet initialized at this moment 
    444.  * Don’t save anything to stack even if compiled with -O0 
    445.  * 
    446.  *************************************************************************/  
    447. ENTRY(save_boot_params)  
    448.     bx  lr          @ back to my caller  
    449. ENDPROC(save_boot_params)  
    450.     .weak   save_boot_params  
    451.   
    452. /************************************************************************* 
    453.  * 
    454.  * cpu_init_cp15 
    455.  * 
    456.  * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless 
    457.  * CONFIG_SYS_ICACHE_OFF is defined. 
    458.  * 
    459.  *************************************************************************/  
    460. ENTRY(cpu_init_cp15)  
    461.   
    462.    /* 
    463.     * Invalidate L1 I/D 
    464.     */  
    465.     mov r0, #0                  @ set up for MCR  
    466.     mcr p15, 0, r0, c8, c7, 0   @ invalidate TLBs  
    467.     mcr p15, 0, r0, c7, c5, 0   @ invalidate icache  
    468.   
    469.    /* 
    470.     * disable MMU stuff and caches 
    471.     */  
    472.     mrc p15, 0, r0, c1, c0, 0  
    473.     bic r0, r0, #0x00002000     @ clear bits 13 (–V-)  
    474.     bic r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)  
    475.     orr r0, r0, #0x00000002     @ set bit 1 (–A-) Align  
    476.     orr r0, r0, #0x00000800     @ set bit 12 (Z—) BTB  
    477.     mcr     p15, 0, r0, c1, c0, 0  
    478.   
    479.     mov pc, lr          @ back to my caller  
    480. ENDPROC(cpu_init_cp15)  
    481.   
    482. #ifndef CONFIG_SKIP_LOWLEVEL_INIT  
    483. /************************************************************************* 
    484.  * 
    485.  * CPU_init_critical registers 
    486.  * 
    487.  * setup important registers 
    488.  * setup memory timing 
    489.  * 
    490.  *************************************************************************/  
    491. ENTRY(cpu_init_crit)  
    492.     /* 
    493.      * Jump to board specific initialization… 
    494.      * The Mask ROM will have already initialized 
    495.      * basic memory. Go here to bump up clock rate and handle 
    496.      * wake up conditions. 
    497.      */  
    498.     b   lowlevel_init       @ go setup pll,mux,memory  
    499. ENDPROC(cpu_init_crit)  
    500. #endif  
    501.   
    502. /************************************************************************* 
    503.  * 
    504.  * zsy210_iic_pm_open 
    505.  * 
    506.  *************************************************************************/  
    507. ENTRY(zsy210_iic_pm_open)  
    508.     /*电源管理,保持供电*/  
    509. #ifdef CONFIG_ZSY210_IIC_PM_CHIP  
    510.     /* PS_HOLD(GPJ2_5) 设置为高点平 */  
    511.     ldr     r0, =ELFIN_GPIO_BASE  
    512.     ldr     r1, =0x00100000  
    513.     str     r1, [r0, #GPJ2CON_OFFSET]  
    514.   
    515.     ldr     r1, =0x0400  
    516.     str     r1, [r0, #GPJ2PUD_OFFSET]  
    517.   
    518.     ldr     r1, =0x20  
    519.     str     r1, [r0, #GPJ2DAT_OFFSET]  
    520. #endif /* CONFIG_ZSY210_IIC_PM_CHIP */  
    521.     mov pc, lr          @ back to my caller  
    522. ENDPROC(zsy210_iic_pm_open)  
    523.   
    524.   
    525. #if defined(CONFIG_ENABLE_MMU)  
    526. _mmu_table_base:  
    527.     .word mmu_table  
    528. #endif  
    529.   
    530.   
    531. /* 
    532.  * we assume that cache operation is done before. (eg. cleanup_before_linux()) 
    533.  * actually, we don’t need to do anything about cache if not use d-cache in U-Boot 
    534.  * So, in this function we clean only MMU. by scsuh 
    535.  * 
    536.  * void theLastJump(void *kernel, int arch_num, uint boot_params); 
    537.  */  
    538. #if defined(CONFIG_ENABLE_MMU)  
    539.     .globl theLastJump  
    540. theLastJump:  
    541.     mov r9, r0  
    542.     ldr r3, =0xfff00000  
    543.     ldr r4, _TEXT_PHY_BASE  
    544.     adr r5, phy_last_jump  
    545.     bic r5, r5, r3  
    546.     orr r5, r5, r4  
    547.     mov pc, r5  
    548. phy_last_jump:  
    549.     /* 
    550.      * disable MMU stuff 
    551.      */  
    552.     mrc p15, 0, r0, c1, c0, 0  
    553.     bic r0, r0, #0x00002300 /* clear bits 13, 9:8 (–V- –RS) */  
    554.     bic r0, r0, #0x00000087 /* clear bits 7, 2:0 (B— -CAM) */  
    555.     orr r0, r0, #0x00000002 /* set bit 2 (A) Align */  
    556.     orr r0, r0, #0x00001000 /* set bit 12 (I) I-Cache */  
    557.     mcr p15, 0, r0, c1, c0, 0  
    558.   
    559.     mcr p15, 0, r0, c8, c7, 0   /* flush v4 TLB */  
    560.   
    561.     mov r0, #0  
    562.     mov pc, r9  
    563. #endif  
    564.   
    565.   
    566.   
    567. #ifndef CONFIG_SPL_BUILD  
    568. /* 
    569.  ************************************************************************* 
    570.  * 
    571.  * Interrupt handling 
    572.  * 
    573.  ************************************************************************* 
    574.  */  
    575. @  
    576. @ IRQ stack frame.  
    577. @  
    578. #define S_FRAME_SIZE    72  
    579.   
    580. #define S_OLD_R0    68  
    581. #define S_PSR       64  
    582. #define S_PC        60  
    583. #define S_LR        56  
    584. #define S_SP        52  
    585.   
    586. #define S_IP        48  
    587. #define S_FP        44  
    588. #define S_R10       40  
    589. #define S_R9        36  
    590. #define S_R8        32  
    591. #define S_R7        28  
    592. #define S_R6        24  
    593. #define S_R5        20  
    594. #define S_R4        16  
    595. #define S_R3        12  
    596. #define S_R2        8  
    597. #define S_R1        4  
    598. #define S_R0        0  
    599.   
    600. #define MODE_SVC 0x13  
    601. #define I_BIT    0x80  
    602.   
    603. /* 
    604.  * use bad_save_user_regs for abort/prefetch/undef/swi … 
    605.  * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling 
    606.  */  
    607.   
    608.     .macro  bad_save_user_regs  
    609.     sub sp, sp, #S_FRAME_SIZE       @ carve out a frame on current  
    610.                         @ user stack  
    611.     stmia   sp, {r0 - r12}          @ Save user registers (now in  
    612.                         @ svc mode) r0-r12  
    613.     ldr r2, IRQ_STACK_START_IN      @ set base 2 words into abort  
    614.                         @ stack  
    615.     ldmia   r2, {r2 - r3}           @ get values for “aborted” pc  
    616.                         @ and cpsr (into parm regs)  
    617.     add r0, sp, #S_FRAME_SIZE       @ grab pointer to old stack  
    618.   
    619.     add r5, sp, #S_SP  
    620.     mov r1, lr  
    621.     stmia   r5, {r0 - r3}           @ save sp_SVC, lr_SVC, pc, cpsr  
    622.     mov r0, sp              @ save current stack into r0  
    623.                         @ (param register)  
    624.     .endm  
    625.   
    626.     .macro  irq_save_user_regs  
    627.     sub sp, sp, #S_FRAME_SIZE  
    628.     stmia   sp, {r0 - r12}          @ Calling r0-r12  
    629.     add r8, sp, #S_PC           @ !! R8 NEEDS to be saved !!  
    630.                         @ a reserved stack spot would  
    631.                         @ be good.  
    632.     stmdb   r8, {sp, lr}^           @ Calling SP, LR  
    633.     str lr, [r8, #0]            @ Save calling PC  
    634.     mrs r6, spsr  
    635.     str r6, [r8, #4]            @ Save CPSR  
    636.     str r0, [r8, #8]            @ Save OLD_R0  
    637.     mov r0, sp  
    638.     .endm  
    639.   
    640.     .macro  irq_restore_user_regs  
    641.     ldmia   sp, {r0 - lr}^          @ Calling r0 - lr  
    642.     mov r0, r0  
    643.     ldr lr, [sp, #S_PC]         @ Get PC  
    644.     add sp, sp, #S_FRAME_SIZE  
    645.     subs    pc, lr, #4          @ return & move spsr_svc into  
    646.                         @ cpsr  
    647.     .endm  
    648.   
    649.     .macro get_bad_stack  
    650.     ldr r13, IRQ_STACK_START_IN     @ setup our mode stack (enter  
    651.                         @ in banked mode)  
    652.   
    653.     str lr, [r13]           @ save caller lr in position 0  
    654.                         @ of saved stack  
    655.     mrs lr, spsr            @ get the spsr  
    656.     str lr, [r13, #4]           @ save spsr in position 1 of  
    657.                         @ saved stack  
    658.   
    659.     mov r13, #MODE_SVC          @ prepare SVC-Mode  
    660.     @ msr   spsr_c, r13  
    661.     msr spsr, r13           @ switch modes, make sure  
    662.                         @ moves will execute  
    663.     mov lr, pc              @ capture return pc  
    664.     movs    pc, lr              @ jump to next instruction &  
    665.                         @ switch modes.  
    666.     .endm  
    667.   
    668.     .macro get_bad_stack_swi  
    669.     sub r13, r13, #4            @ space on current stack for  
    670.                         @ scratch reg.  
    671.     str r0, [r13]           @ save R0’s value.  
    672.     ldr r0, IRQ_STACK_START_IN      @ get data regions start  
    673.                         @ spots for abort stack  
    674.     str lr, [r0]            @ save caller lr in position 0  
    675.                         @ of saved stack  
    676.     mrs r0, spsr            @ get the spsr  
    677.     str lr, [r0, #4]            @ save spsr in position 1 of  
    678.                         @ saved stack  
    679.     ldr r0, [r13]           @ restore r0  
    680.     add r13, r13, #4            @ pop stack entry  
    681.     .endm  
    682.   
    683.     .macro get_irq_stack            @ setup IRQ stack  
    684.     ldr sp, IRQ_STACK_START  
    685.     .endm  
    686.   
    687.     .macro get_fiq_stack            @ setup FIQ stack  
    688.     ldr sp, FIQ_STACK_START  
    689.     .endm  
    690.   
    691. /* 
    692.  * exception handlers 
    693.  */  
    694.     .align  5  
    695. undefined_instruction:  
    696.     get_bad_stack  
    697.     bad_save_user_regs  
    698.     bl  do_undefined_instruction  
    699.   
    700.     .align  5  
    701. software_interrupt:  
    702.     get_bad_stack_swi  
    703.     bad_save_user_regs  
    704.     bl  do_software_interrupt  
    705.   
    706.     .align  5  
    707. prefetch_abort:  
    708.     get_bad_stack  
    709.     bad_save_user_regs  
    710.     bl  do_prefetch_abort  
    711.   
    712.     .align  5  
    713. data_abort:  
    714.     get_bad_stack  
    715.     bad_save_user_regs  
    716.     bl  do_data_abort  
    717.   
    718.     .align  5  
    719. not_used:  
    720.     get_bad_stack  
    721.     bad_save_user_regs  
    722.     bl  do_not_used  
    723.   
    724. #ifdef CONFIG_USE_IRQ  
    725.   
    726.     .align  5  
    727. irq:  
    728.     get_irq_stack  
    729.     irq_save_user_regs  
    730.     bl  do_irq  
    731.     irq_restore_user_regs  
    732.   
    733.     .align  5  
    734. fiq:  
    735.     get_fiq_stack  
    736.     /* someone ought to write a more effective fiq_save_user_regs */  
    737.     irq_save_user_regs  
    738.     bl  do_fiq  
    739.     irq_restore_user_regs  
    740.   
    741. #else  
    742.   
    743.     .align  5  
    744. irq:  
    745.     get_bad_stack  
    746.     bad_save_user_regs  
    747.     bl  do_irq  
    748.   
    749.     .align  5  
    750. fiq:  
    751.     get_bad_stack  
    752.     bad_save_user_regs  
    753.     bl  do_fiq  
    754.   
    755. #endif /* CONFIG_USE_IRQ */  
    756. #endif /* CONFIG_SPL_BUILD */  







    lowlevel_init.S的完整代码:

    1. /* 
    2.  * Copyright (C) 2009 Samsung Electronics 
    3.  * Kyungmin Park <kyungmin.park@samsung.com> 
    4.  * Minkyu Kang <mk7.kang@samsung.com> 
    5.  * 
    6.  * See file CREDITS for list of people who contributed to this 
    7.  * project. 
    8.  * 
    9.  * This program is free software; you can redistribute it and/or 
    10.  * modify it under the terms of the GNU General Public License as 
    11.  * published by the Free Software Foundation; either version 2 of 
    12.  * the License, or (at your option) any later version. 
    13.  * 
    14.  * This program is distributed in the hope that it will be useful, 
    15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    17.  * GNU General Public License for more details. 
    18.  * 
    19.  * You should have received a copy of the GNU General Public License 
    20.  * along with this program; if not, write to the Free Software 
    21.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
    22.  * MA 02111-1307 USA 
    23.  */  
    24.   
    25. #include <config.h>  
    26. #include <version.h>  
    27. #include <asm/arch/cpu.h>  
    28. #include <asm/arch/power.h>  
    29. #include <s5pv210.h>  
    30. #include “zsy210_val.h”  
    31. /* 
    32.  * Register usages: 
    33.  * 
    34.  * r5 has zero always 
    35.  */  
    36.   
    37. _TEXT_BASE:  
    38.     .word   CONFIG_SYS_TEXT_BASE  
    39.   
    40.     .globl lowlevel_init  
    41. lowlevel_init:  
    42.     mov r9, lr  
    43.   
    44.     /* check reset status  */  
    45.     ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)  
    46.     ldr r1, [r0]  
    47.     bic r1, r1, #0xfff6ffff  
    48.     cmp r1, #0x10000  
    49.     beq wakeup_reset_pre  
    50.     cmp r1, #0x80000  
    51.     beq wakeup_reset_from_didle  
    52.   
    53.     /* IO Retention release */  
    54.     ldr r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)  
    55.     ldr r1, [r0]  
    56.     ldr r2, =IO_RET_REL  
    57.     orr r1, r1, r2  
    58.     str r1, [r0]  
    59.   
    60.     /* Disable Watchdog */  
    61.     ldr r0, =ELFIN_WATCHDOG_BASE    /* 0xE2700000 */  
    62.     mov r1, #0  
    63.     str r1, [r0]  
    64.     /* SRAM(2MB) init for SMDKC110 */  
    65.     /* GPJ1 SROM_ADDR_16to21 */  
    66.     ldr r0, =ELFIN_GPIO_BASE  
    67.   
    68.     ldr r1, [r0, #GPJ1CON_OFFSET]  
    69.     bic r1, r1, #0xFFFFFF  
    70.     ldr r2, =0x444444  
    71.     orr r1, r1, r2  
    72.     str r1, [r0, #GPJ1CON_OFFSET]  
    73.   
    74.     ldr r1, [r0, #GPJ1PUD_OFFSET]  
    75.     ldr r2, =0x3ff  
    76.     bic r1, r1, r2  
    77.     str r1, [r0, #GPJ1PUD_OFFSET]  
    78.   
    79.     /* GPJ4 SROM_ADDR_16to21 */  
    80.     ldr r1, [r0, #GPJ4CON_OFFSET]  
    81.     bic r1, r1, #(0xf<<16)  
    82.     ldr r2, =(0x4<<16)  
    83.     orr r1, r1, r2  
    84.     str r1, [r0, #GPJ4CON_OFFSET]  
    85.   
    86.     ldr r1, [r0, #GPJ4PUD_OFFSET]  
    87.     ldr r2, =(0x3<<8)  
    88.     bic r1, r1, r2  
    89.     str r1, [r0, #GPJ4PUD_OFFSET]  
    90.   
    91.     /* CS0 - 16bit sram, enable nBE, Byte base address */  
    92.     ldr r0, =ELFIN_SROM_BASE    /* 0xE8000000 */  
    93.     mov r1, #0x1  
    94.     str r1, [r0]  
    95.   
    96.     /* PS_HOLD pin(GPH0_0) set to high */  
    97.     ldr r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)  
    98.     ldr r1, [r0]  
    99.     orr r1, r1, #0x300  
    100.     orr r1, r1, #0x1  
    101.     str r1, [r0]  
    102.   
    103.     /* when we already run in ram, we don’t need to relocate U-Boot. 
    104.      * and actually, memory controller must be configured before U-Boot 
    105.      * is running in ram. 
    106.      */  
    107.     ldr r0, =0xff000fff  
    108.     bic r1, pc, r0      /* r0 <- current base addr of code */  
    109.     ldr r2, _TEXT_BASE      /* r1 <- original base addr in ram */  
    110.     bic r2, r2, r0      /* r0 <- current base addr of code */  
    111.     cmp     r1, r2                  /* compare r0, r1     */  
    112.     beq     1f          /* r0 == r1 then skip sdram init   */  
    113.   
    114.     /* init PMIC chip */  
    115. #ifdef CONFIG_ZSY210_IIC_PM_CHIP  
    116.     bl PMIC_InitIp  
    117. #endif  
    118.   
    119.     /* init system clock */  
    120.     bl system_clock_init  
    121.     /* Memory initialize */  
    122.     bl mem_ctrl_asm_init  
    123.   
    124. 1:  
    125.     /* for UART */  
    126.     bl uart_asm_init  
    127.   
    128.     /* for TZPC */  
    129.     bl tzpc_asm_init  
    130.   
    131. #if defined(CONFIG_NAND)  
    132.     /* simple init for NAND */  
    133.     bl nand_asm_init  
    134. #endif  
    135.     /* check reset status  */  
    136.   
    137.     ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)  
    138.     ldr r1, [r0]  
    139.     bic r1, r1, #0xfffeffff  
    140.     cmp r1, #0x10000  
    141.     beq wakeup_reset_pre  
    142.   
    143.     /* ABB disable */  
    144.     ldr r0, =0xE010C300  
    145.     orr r1, r1, #(0x1<<23)  
    146.     str r1, [r0]  
    147.   
    148.     /* Print ‘K’ */  
    149.     ldr r0, =ELFIN_UART_CONSOLE_BASE  
    150.     ldr r1, =0x4b4b4b4b  
    151.     str r1, [r0, #UTXH_OFFSET]  
    152.   
    153.     mov lr, r9  
    154.     mov pc, lr  
    155.   
    156.   
    157. /* 
    158.  * uart_asm_init: Initialize UART’s pins 
    159.  */  
    160. uart_asm_init:  
    161.     /* set GPIO(GPA) to enable UART */  
    162.     @ GPIO setting for UART  
    163.     ldr r0, =ELFIN_GPIO_BASE  
    164.     ldr r1, =0x22222222  
    165.     str     r1, [r0, #GPA0CON_OFFSET]  
    166.   
    167.     ldr     r1, =0x2222  
    168.     str     r1, [r0, #GPA1CON_OFFSET]  
    169.   
    170.     ldr r0, =ELFIN_UART_CONSOLE_BASE        @0xEC000000  
    171.     mov r1, #0x0  
    172.     str r1, [r0, #UFCON_OFFSET]  
    173.     str r1, [r0, #UMCON_OFFSET]  
    174.   
    175.     mov r1, #0x3  
    176.     str r1, [r0, #ULCON_OFFSET]  
    177.   
    178.     ldr r1, =0x3c5  
    179.     str r1, [r0, #UCON_OFFSET]  
    180.   
    181.     ldr r1, =UART_UBRDIV_VAL  
    182.     str r1, [r0, #UBRDIV_OFFSET]  
    183.   
    184.     ldr r1, =UART_UDIVSLOT_VAL  
    185.     str r1, [r0, #UDIVSLOT_OFFSET]  
    186.   
    187.     ldr r1, =0x4f4f4f4f  
    188.     str r1, [r0, #UTXH_OFFSET]      @’O’  
    189.   
    190.     mov pc, lr  
    191.   
    192. /* 
    193.  * tzpc_asm_init: Initialize TZPC 
    194.  */  
    195. tzpc_asm_init:  
    196.   
    197.     ldr r0, =ELFIN_TZPC0_BASE  
    198.     mov r1, #0x0  
    199.     str r1, [r0]  
    200.     mov r1, #0xff  
    201.     str r1, [r0, #TZPC_DECPROT0SET_OFFSET]  
    202.     str r1, [r0, #TZPC_DECPROT1SET_OFFSET]  
    203.     str r1, [r0, #TZPC_DECPROT2SET_OFFSET]  
    204.   
    205.     ldr     r0, =ELFIN_TZPC1_BASE  
    206.     str r1, [r0, #TZPC_DECPROT0SET_OFFSET]  
    207.     str r1, [r0, #TZPC_DECPROT1SET_OFFSET]  
    208.     str r1, [r0, #TZPC_DECPROT2SET_OFFSET]  
    209.   
    210.     ldr r0, =ELFIN_TZPC2_BASE  
    211.     str r1, [r0, #TZPC_DECPROT0SET_OFFSET]  
    212.     str r1, [r0, #TZPC_DECPROT1SET_OFFSET]  
    213.     str r1, [r0, #TZPC_DECPROT2SET_OFFSET]  
    214.     str r1, [r0, #TZPC_DECPROT3SET_OFFSET]  
    215.   
    216.     ldr r0, =ELFIN_TZPC3_BASE  
    217.     str r1, [r0, #TZPC_DECPROT0SET_OFFSET]  
    218.     str r1, [r0, #TZPC_DECPROT1SET_OFFSET]  
    219.     str r1, [r0, #TZPC_DECPROT2SET_OFFSET]  
    220.   
    221.     mov pc, lr  
    222.   
    223.   
    224. /******************** zsy add 2013.3.14 *******************************/  
    225. /* 
    226.  * Nand Interface Init for SMDKC110 
    227.  */  
    228. nand_asm_init:  
    229.   
    230.     /* Setting GPIO for NAND */  
    231.     /* This setting is NAND initialze code at booting time in iROM. */  
    232.   
    233.     ldr     r0, =ELFIN_GPIO_BASE  
    234.   
    235.     ldr     r1, [r0, #MP01CON_OFFSET]  
    236.     bic     r1, r1, #(0xf<<8)  
    237.     orr     r1, r1, #(0x3<<8)  
    238.     str     r1, [r0, #MP01CON_OFFSET]  
    239.   
    240.     ldr     r1, [r0, #MP01PUD_OFFSET]  
    241.     bic     r1, r1, #(0x3<<4)  
    242.     str     r1, [r0, #MP01PUD_OFFSET]  
    243.   
    244.     ldr     r1, [r0, #MP03CON_OFFSET]  
    245.     bic     r1, r1, #0xFFFFFF  
    246.     ldr     r2, =0x22222222  
    247.     orr     r1, r1, r2  
    248.     str     r1, [r0, #MP03CON_OFFSET]  
    249.   
    250.     ldr     r1, [r0, #MP03PUD_OFFSET]  
    251.     ldr     r2, =0x3fff  
    252.     bic     r1, r1, r2  
    253.     str     r1, [r0, #MP03PUD_OFFSET]  
    254.   
    255.     ldr     r0, =ELFIN_NAND_BASE  
    256.   
    257.     ldr     r1, [r0, #NFCONF_OFFSET]  
    258.     ldr     r2, =0x777F  
    259.     bic     r1, r1, r2  
    260.     ldr     r2, =NFCONF_VAL  
    261.     orr     r1, r1, r2  
    262.     str     r1, [r0, #NFCONF_OFFSET]  
    263.   
    264.     ldr     r1, [r0, #NFCONT_OFFSET]  
    265.     ldr     r2, =0x707C7  
    266.     bic     r1, r1, r2  
    267.     ldr     r2, =NFCONT_VAL  
    268.     orr     r1, r1, r2  
    269.     str     r1, [r0, #NFCONT_OFFSET]  
    270.   
    271.     ldr     r1, [r0, #NFCONF_OFFSET]  
    272.     orr     r1, r1, #0x70  
    273.     orr     r1, r1, #0x7700  
    274.     str     r1, [r0, #NFCONF_OFFSET]  
    275.   
    276.     ldr     r1, [r0, #NFCONT_OFFSET]  
    277.     orr     r1, r1, #0x03  
    278.     str     r1, [r0, #NFCONT_OFFSET]  
    279.   
    280.     mov     pc, lr  
    281.   
    282.   
    283. /******************** zsy add 2013.3.14 *******************************/  
    284.     wakeup_reset_from_didle:  
    285.     /* Wait when APLL is locked */  
    286.     ldr r0, =ELFIN_CLOCK_POWER_BASE  
    287. lockloop:  
    288.     ldr r1, [r0, #APLL_CON0_OFFSET]  
    289.     and r1, r1, #(1<<29)  
    290.     cmp r1, #(1<<29)  
    291.     bne     lockloop  
    292.     beq exit_wakeup  
    293.   
    294. wakeup_reset_pre:  
    295.     mrc p15, 0, r1, c1, c0, 1   @Read CP15 Auxiliary control register  
    296.     and r1, r1, #0x80000000 @Check L2RD is disable or not  
    297.     cmp r1, #0x80000000  
    298.     bne wakeup_reset        @if L2RD is not disable jump to wakeup_reset  
    299.   
    300.     bl  disable_l2cache  
    301.     bl  v7_flush_dcache_all  
    302.     /* L2 cache enable at sleep.S of kernel 
    303.      * bl   enable_l2cache 
    304.      */  
    305. #ifdef CONFIG_ZSY210  
    306.     bl  enable_l2cache  
    307. #endif  
    308.   
    309. wakeup_reset:  
    310.     /* init system clock */  
    311.     bl system_clock_init  
    312.     bl mem_ctrl_asm_init  
    313.     bl tzpc_asm_init  
    314. #if defined(CONFIG_NAND)  
    315.     bl nand_asm_init  
    316. #endif  
    317.   
    318. exit_wakeup:  
    319.     /*Load return address and jump to kernel*/  
    320.     ldr r0, =(INF_REG_BASE+INF_REG0_OFFSET)  
    321.     ldr r1, [r0]    /* r1 = physical address of s5pc110_cpu_resume function*/  
    322.   
    323.     mov pc, r1      /*Jump to kernel */  
    324.     nop  
    325.     nop  
    326.   
    327. /* 
    328.  * system_clock_init: Initialize core clock and bus clock. 
    329.  * void system_clock_init(void) 
    330.  */  
    331. system_clock_init:  
    332.   
    333.     ldr r0, =ELFIN_CLOCK_POWER_BASE @0xe0100000  
    334.   
    335.     /* Set Mux to FIN */  
    336.     ldr r1, =0x0  
    337.     str r1, [r0, #CLK_SRC0_OFFSET]  
    338.   
    339.     ldr r1, =APLL_LOCKTIME_VAL  
    340.     str r1, [r0, #APLL_LOCK_OFFSET]  
    341.   
    342.     /* Disable PLL */  
    343. #if defined(CONFIG_CHECK_MPLL_LOCK)  
    344. retryloop:  
    345. #endif  
    346.     ldr r1, =0x0  
    347.     str r1, [r0, #APLL_CON0_OFFSET]  
    348.     ldr r1, =0x0  
    349.     str r1, [r0, #MPLL_CON_OFFSET]  
    350.   
    351.     ldr r1, =0x0  
    352.     str r1, [r0, #MPLL_CON_OFFSET]  
    353.   
    354.     ldr     r1, [r0, #CLK_DIV0_OFFSET]  
    355.     ldr r2, =CLK_DIV0_MASK  
    356.     bic r1, r1, r2  
    357.   
    358.     ldr r2, =CLK_DIV0_VAL  
    359.     orr r1, r1, r2  
    360.     str r1, [r0, #CLK_DIV0_OFFSET]  
    361.   
    362.     ldr r1, =APLL_VAL  
    363.     str r1, [r0, #APLL_CON0_OFFSET]  
    364.   
    365.     ldr r1, =MPLL_VAL  
    366.     str r1, [r0, #MPLL_CON_OFFSET]  
    367.   
    368.     ldr r1, =VPLL_VAL  
    369.     str r1, [r0, #VPLL_CON_OFFSET]  
    370. #if defined(CONFIG_EVT1)  
    371.     ldr r1, =AFC_ON  
    372.     str r1, [r0, #APLL_CON1_OFFSET]  
    373. #endif  
    374.     mov r1, #0x10000  
    375. 1:  subs    r1, r1, #1  
    376.     bne 1b  
    377.   
    378. #if defined(CONFIG_CHECK_MPLL_LOCK)  
    379.     /* MPLL software workaround */  
    380.     ldr r1, [r0, #MPLL_CON_OFFSET]  
    381.     orr     r1, r1, #(1<<28)  
    382.     str r1, [r0, #MPLL_CON_OFFSET]  
    383.   
    384.     mov r1, #0x100  
    385. 1:  subs    r1, r1, #1  
    386.     bne 1b  
    387.   
    388.     ldr r1, [r0, #MPLL_CON_OFFSET]  
    389.     and r1, r1, #(1<<29)  
    390.     cmp r1, #(1<<29)  
    391.     bne     retryloop  
    392.   
    393.     /* H/W lock detect disable */  
    394.     ldr r1, [r0, #MPLL_CON_OFFSET]  
    395.     bic     r1, r1, #(1<<28)  
    396.     str r1, [r0, #MPLL_CON_OFFSET]  
    397. #endif  
    398.   
    399.     ldr r1, [r0, #CLK_SRC0_OFFSET]  
    400.     ldr r2, =0x10001111  
    401.     orr r1, r1, r2  
    402.     str r1, [r0, #CLK_SRC0_OFFSET]  
    403.   
    404. #if defined(CONFIG_MCP_AC)  
    405.   
    406.     /* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */  
    407.     ldr r1, [r0, #CLK_SRC6_OFFSET]  
    408.     bic r1, r1, #(0x3<<24)  
    409.     orr r1, r1, #0x01000000  
    410.     str r1, [r0, #CLK_SRC6_OFFSET]  
    411.   
    412.     /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */  
    413.     ldr r1, [r0, #CLK_DIV6_OFFSET]  
    414.     bic r1, r1, #(0xF<<28)  
    415.     bic r1, r1, #(0x7<<12)    @; ONENAND_RATIO: 0  
    416.     orr r1, r1, #0x30000000  
    417.     str r1, [r0, #CLK_DIV6_OFFSET]  
    418.   
    419. #elif defined (CONFIG_MCP_N)  
    420.     /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */  
    421.     ldr r1, [r0, #CLK_SRC6_OFFSET]  
    422.     mov r1, #0x00000000  
    423.     str r1, [r0, #CLK_SRC6_OFFSET]  
    424.   
    425.     /* CLK_DIV6[31:28] -> 0=1/1 */  
    426.     ldr r1, [r0, #CLK_DIV6_OFFSET]  
    427.     mov r1, #0x00000000  
    428.     str r1, [r0, #CLK_DIV6_OFFSET]  
    429.   
    430.   
    431. #elif defined (CONFIG_MCP_H)  
    432.   
    433.     /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */  
    434.     ldr r1, [r0, #CLK_SRC6_OFFSET]  
    435.     bic r1, r1, #(0x3<<24)  
    436.     orr r1, r1, #0x00000000  
    437.     str r1, [r0, #CLK_SRC6_OFFSET]  
    438.   
    439.     /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */  
    440.     ldr r1, [r0, #CLK_DIV6_OFFSET]  
    441.     bic r1, r1, #(0xF<<28)  
    442.     bic r1, r1, #(0x7<<12)    @; ONENAND_RATIO: 0  
    443.     orr r1, r1, #0x00000000  
    444.     str r1, [r0, #CLK_DIV6_OFFSET]  
    445.   
    446. #elif defined (CONFIG_MCP_B) || defined (CONFIG_MCP_D)  
    447.   
    448.     /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */  
    449.     ldr r1, [r0, #CLK_SRC6_OFFSET]  
    450.     bic r1, r1, #(0x3<<24)  
    451.     orr r1, r1, #0x01000000  
    452.     str r1, [r0, #CLK_SRC6_OFFSET]  
    453.   
    454.     /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */  
    455.     ldr r1, [r0, #CLK_DIV6_OFFSET]  
    456.     bic r1, r1, #(0xF<<28)  
    457.     bic r1, r1, #(0x7<<12)    @; ONENAND_RATIO: 0  
    458.     orr r1, r1, #0x30000000  
    459.     str r1, [r0, #CLK_DIV6_OFFSET]  
    460.   
    461. #elif defined (CONFIG_MCP_SINGLE)  
    462.   
    463.     /* CLK_DIV6 */  
    464.     ldr r1, [r0, #CLK_DIV6_OFFSET]  
    465.     bic r1, r1, #(0x7<<12)    @; ONENAND_RATIO: 0  
    466.     str r1, [r0, #CLK_DIV6_OFFSET]  
    467.   
    468. #endif  
    469.     mov pc, lr  
    470.   
    471.   
    472.   
    473.   
    474. #ifdef CONFIG_ENABLE_MMU  
    475.   
    476. #ifdef CONFIG_MCP_SINGLE  
    477. /* 
    478.  * MMU Table for SMDKC110 
    479.  * 0x0000_0000 – 0xBFFF_FFFF => Not Allowed 
    480.  * 0xB000_0000 – 0xB7FF_FFFF => A:0xB000_0000 – 0xB7FF_FFFF 
    481.  * 0xC000_0000 – 0xC7FF_FFFF => A:0x3000_0000 – 0x37FF_FFFF 
    482.  * 0xC800_0000 – 0xDFFF_FFFF => Not Allowed 
    483.  * 0xE000_0000 – 0xFFFF_FFFF => A:0xE000_0000 – 0XFFFF_FFFF 
    484.  */  
    485.   
    486.     /* form a first-level section entry */  
    487. .macro FL_SECTION_ENTRY base,ap,d,c,b  
    488.     .word (\base << 20) | (\ap << 10) | \  
    489.           (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)  
    490. .endm  
    491. .section .mmudata, ”a”  
    492.     .align 14  
    493.     // the following alignment creates the mmu table at address 0x4000.  
    494.     .globl mmu_table  
    495. mmu_table:  
    496.     .set __base,0  
    497.     // Access for iRAM  
    498.     .rept 0x100  
    499.     FL_SECTION_ENTRY __base,3,0,0,0  
    500.     .set __base,__base+1  
    501.     .endr  
    502.   
    503.     // Not Allowed  
    504.     .rept 0x200 - 0x100  
    505.     .word 0x00000000  
    506.     .endr  
    507. #ifdef CONFIG_ZSY10_1G  
    508.     .set __base,0x200  
    509.     // should be accessed  
    510.     .rept 0x600 - 0x200  
    511.     FL_SECTION_ENTRY __base,3,0,1,1  
    512.     .set __base,__base+1  
    513.     .endr  
    514. #else  
    515.     .set __base,0x200  
    516.     // should be accessed  
    517.     .rept 0x600 - 0x200  
    518.     FL_SECTION_ENTRY __base,3,0,1,1  
    519.     .set __base,__base+1  
    520.     .endr  
    521. /* 
    522.     .set __base,0x400 
    523.     // should be accessed 
    524.     .rept 0x500 - 0x400 
    525.     FL_SECTION_ENTRY __base,3,0,1,1 
    526.     .set __base,__base+1 
    527.     .endr*/  
    528. #endif /* CONFIG_ZSY10_1G */  
    529.     .rept 0x800 - 0x600  
    530.     .word 0x00000000  
    531.     .endr  
    532.   
    533.   
    534.     .set __base,0x800  
    535.     // should be accessed  
    536.     .rept 0xb00 - 0x800  
    537.     FL_SECTION_ENTRY __base,3,0,0,0  
    538.     .set __base,__base+1  
    539.     .endr  
    540.   
    541. /*  .rept 0xc00 - 0xb00 
    542.     .word 0x00000000 
    543.     .endr */  
    544.   
    545.     .set __base,0xB00  
    546.     .rept 0xc00 - 0xb00  
    547.     FL_SECTION_ENTRY __base,3,0,0,0  
    548.     .set __base,__base+1  
    549.     .endr  
    550. #ifdef CONFIG_ZSY10_1G  
    551.     .set __base,0x200  
    552.     // 256MB for SDRAM with cacheable  
    553.     .rept 0xD00 - 0xC00  
    554.     FL_SECTION_ENTRY __base,3,0,1,1  
    555.     .set __base,__base+1  
    556.     .endr  
    557.   
    558.     // access is not allowed.  
    559.     @.rept 0xD00 - 0xC80  
    560.     @.word 0x00000000  
    561.     @.endr  
    562.   
    563.     .set __base,0xD00  
    564.     // 1:1 mapping for debugging with non-cacheable  
    565.     .rept 0x1000 - 0xD00  
    566.     FL_SECTION_ENTRY __base,3,0,0,0  
    567.     .set __base,__base+1  
    568.     .endr  
    569. #else  
    570.     .set __base,0x200  
    571.     // 256MB for SDRAM with cacheable  
    572.     .rept 0xD00 - 0xC00  
    573.     FL_SECTION_ENTRY __base,3,0,1,1  
    574.     .set __base,__base+1  
    575.     .endr  
    576.   
    577.     // access is not allowed.  
    578.     @.rept 0xD00 - 0xC80  
    579.     @.word 0x00000000  
    580.     @.endr  
    581.   
    582.     .set __base,0xD00  
    583.     // 1:1 mapping for debugging with non-cacheable  
    584.     .rept 0x1000 - 0xD00  
    585.     FL_SECTION_ENTRY __base,3,0,0,0  
    586.     .set __base,__base+1  
    587.     .endr  
    588. #endif /* CONFIG_ZSY10_1G */  
    589.     #else   // CONFIG_MCP_AC, CONFIG_MCP_H, CONFIG_MCP_B  
    590.   
    591. /* 
    592.  * MMU Table for SMDKC110 
    593.  * 0x0000_0000 – 0xBFFF_FFFF => Not Allowed 
    594.  * 0xB000_0000 – 0xB7FF_FFFF => A:0xB000_0000 – 0xB7FF_FFFF 
    595.  * 0xC000_0000 – 0xC7FF_FFFF => A:0x3000_0000 – 0x37FF_FFFF 
    596.  * 0xC800_0000 – 0xDFFF_FFFF => Not Allowed 
    597.  * 0xE000_0000 – 0xFFFF_FFFF => A:0xE000_0000 – 0XFFFF_FFFF 
    598.  */  
    599.   
    600.     /* form a first-level section entry */  
    601. .macro FL_SECTION_ENTRY base,ap,d,c,b  
    602.     .word (\base << 20) | (\ap << 10) | \  
    603.           (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) | (1<<1)  
    604. .endm  
    605. .section .mmudata, ”a”  
    606.     .align 14  
    607.     // the following alignment creates the mmu table at address 0x4000.  
    608.     .globl mmu_table  
    609. mmu_table:  
    610.     .set __base,0  
    611.     // Access for iRAM  
    612.     .rept 0x100  
    613.     FL_SECTION_ENTRY __base,3,0,0,0  
    614.     .set __base,__base+1  
    615.     .endr  
    616.   
    617.     // Not Allowed  
    618.     .rept 0x300 - 0x100  
    619.     .word 0x00000000  
    620.     .endr  
    621.   
    622. #if defined(CONFIG_MCP_N)  
    623.     .set __base,0x300  
    624.     // should be accessed  
    625.     .rept 0x400 - 0x300  
    626.     FL_SECTION_ENTRY __base,3,0,1,1  
    627.     .set __base,__base+1  
    628.     .endr  
    629. #else  
    630.     .set __base,0x300  
    631.     // should be accessed  
    632.     .rept 0x350 - 0x300  
    633.     FL_SECTION_ENTRY __base,3,0,1,1  
    634.     .set __base,__base+1  
    635.     .endr  
    636.   
    637.     // Not Allowed  
    638.     .rept 0x400 - 0x350  
    639.     .word 0x00000000  
    640.     .endr  
    641. #endif  
    642.   
    643.     .set __base,0x400  
    644.     // should be accessed  
    645.     .rept 0x500 - 0x400  
    646.     FL_SECTION_ENTRY __base,3,0,1,1  
    647.     .set __base,__base+1  
    648.     .endr  
    649.   
    650.     .rept 0x800 - 0x500  
    651.     .word 0x00000000  
    652.     .endr  
    653.   
    654.     .set __base,0x800  
    655.     // should be accessed  
    656.     .rept 0xb00 - 0x800  
    657.     FL_SECTION_ENTRY __base,3,0,0,0  
    658.     .set __base,__base+1  
    659.     .endr  
    660.   
    661.     .set __base,0xB00  
    662.     .rept 0xc00 - 0xb00  
    663.     FL_SECTION_ENTRY __base,3,0,0,0  
    664.     .set __base,__base+1  
    665.     .endr  
    666.   
    667. #if defined(CONFIG_MCP_N)  
    668.     .set __base,0x300  
    669.     // 256MB for SDRAM with cacheable  
    670.     .rept 0xD00 - 0xC00  
    671.     FL_SECTION_ENTRY __base,3,0,1,1  
    672.     .set __base,__base+1  
    673.     .endr  
    674. #else  
    675.     .set __base,0x300  
    676.     // 80MB for SDRAM with cacheable  
    677.     .rept 0xC50 - 0xC00  
    678.     FL_SECTION_ENTRY __base,3,0,1,1  
    679.     .set __base,__base+1  
    680.     .endr  
    681.   
    682.     // Not Allowed  
    683.     .rept 0xD00 - 0xC50  
    684.     .word 0x00000000  
    685.     .endr  
    686. #endif  
    687.   
    688.     .set __base,0xD00  
    689.     // 1:1 mapping for debugging with non-cacheable  
    690.     .rept 0x1000 - 0xD00  
    691.     FL_SECTION_ENTRY __base,3,0,0,0  
    692.     .set __base,__base+1  
    693.     .endr  
    694.     #endif  
    695. #endif  






    mem_setup.S的完整代码:

    1. #include <config.h>  
    2. #include <s5pv210.h>  
    3.   
    4.     .globl mem_ctrl_asm_init  
    5. mem_ctrl_asm_init:  
    6.   
    7. #ifndef CONFIG_EVT1  
    8.   
    9.     ldr     r0, =ASYNC_MSYS_DMC0_BASE  
    10.   
    11.     ldr     r1, =0x0  
    12.     str     r1, [r0, #0x0]  
    13.   
    14.     /* This register is removed at EVT1 of C110. */  
    15.     ldr     r1, =0x0  
    16.     str     r1, [r0, #0xC]  
    17.    
    18. #endif  
    19.   
    20. #ifdef CONFIG_MCP_SINGLE  
    21.   
    22.     /* DMC0 Drive Strength (Setting 2X) */  
    23.   
    24.     ldr r0, =ELFIN_GPIO_BASE  
    25.   
    26.     ldr r1, =0x0000AAAA  
    27.     str r1, [r0, #MP1_0DRV_SR_OFFSET]  
    28.   
    29.     ldr r1, =0x0000AAAA  
    30.     str r1, [r0, #MP1_1DRV_SR_OFFSET]  
    31.   
    32.     ldr r1, =0x0000AAAA  
    33.     str r1, [r0, #MP1_2DRV_SR_OFFSET]  
    34.   
    35.     ldr r1, =0x0000AAAA  
    36.     str r1, [r0, #MP1_3DRV_SR_OFFSET]  
    37.   
    38.     ldr r1, =0x0000AAAA  
    39.     str r1, [r0, #MP1_4DRV_SR_OFFSET]  
    40.   
    41.     ldr r1, =0x0000AAAA  
    42.     str r1, [r0, #MP1_5DRV_SR_OFFSET]  
    43.   
    44.     ldr r1, =0x0000AAAA  
    45.     str r1, [r0, #MP1_6DRV_SR_OFFSET]  
    46.   
    47.     ldr r1, =0x0000AAAA  
    48.     str r1, [r0, #MP1_7DRV_SR_OFFSET]  
    49.   
    50.     ldr r1, =0x00002AAA  
    51.     str r1, [r0, #MP1_8DRV_SR_OFFSET]  
    52.   
    53.   
    54.     /* DMC1 Drive Strength (Setting 2X) */  
    55.   
    56.     ldr r0, =ELFIN_GPIO_BASE  
    57.   
    58.     ldr r1, =0x0000AAAA  
    59.     str r1, [r0, #MP2_0DRV_SR_OFFSET]  
    60.   
    61.     ldr r1, =0x0000AAAA  
    62.     str r1, [r0, #MP2_1DRV_SR_OFFSET]  
    63.   
    64.     ldr r1, =0x0000AAAA  
    65.     str r1, [r0, #MP2_2DRV_SR_OFFSET]  
    66.   
    67.     ldr r1, =0x0000AAAA  
    68.     str r1, [r0, #MP2_3DRV_SR_OFFSET]  
    69.   
    70.     ldr r1, =0x0000AAAA  
    71.     str r1, [r0, #MP2_4DRV_SR_OFFSET]  
    72.   
    73.     ldr r1, =0x0000AAAA  
    74.     str r1, [r0, #MP2_5DRV_SR_OFFSET]  
    75.   
    76.     ldr r1, =0x0000AAAA  
    77.     str r1, [r0, #MP2_6DRV_SR_OFFSET]  
    78.   
    79.     ldr r1, =0x0000AAAA  
    80.     str r1, [r0, #MP2_7DRV_SR_OFFSET]  
    81.   
    82.     ldr r1, =0x00002AAA  
    83.     str r1, [r0, #MP2_8DRV_SR_OFFSET]  
    84.   
    85.     /* DMC0 initialization at single Type*/  
    86.     ldr r0, =APB_DMC_0_BASE  
    87.   
    88.     ldr r1, =0x00101000             @PhyControl0 DLL parameter setting, manual 0x00101000  
    89.     str r1, [r0, #DMC_PHYCONTROL0]  
    90.   
    91.     ldr r1, =0x00000086             @PhyControl1 DLL parameter setting, LPDDR/LPDDR2 Case  
    92.     str r1, [r0, #DMC_PHYCONTROL1]  
    93.   
    94.     ldr r1, =0x00101002             @PhyControl0 DLL on  
    95.     str r1, [r0, #DMC_PHYCONTROL0]  
    96.   
    97.     ldr r1, =0x00101003             @PhyControl0 DLL start  
    98.     str r1, [r0, #DMC_PHYCONTROL0]  
    99.   
    100. find_lock_val:  
    101.     ldr r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register value  
    102.     and r2, r1, #0x7  
    103.     cmp r2, #0x7                @Loop until DLL is locked  
    104.     bne find_lock_val  
    105.   
    106.     and r1, #0x3fc0  
    107.     mov r2, r1, LSL #18  
    108.     orr r2, r2, #0x100000  
    109.     orr r2 ,r2, #0x1000  
    110.   
    111.     orr r1, r2, #0x3                @Force Value locking  
    112.     str r1, [r0, #DMC_PHYCONTROL0]  
    113.   
    114. #if 0   /* Memory margin test 10.01.05 */  
    115.     orr r1, r2, #0x1                @DLL off  
    116.     str r1, [r0, #DMC_PHYCONTROL0]  
    117. #endif  
    118.     /* setting DDR2 */  
    119.     ldr r1, =0x0FFF2010             @ConControl auto refresh off  
    120.     str r1, [r0, #DMC_CONCONTROL]  
    121.   
    122.     ldr r1, =0x00212400             @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off  
    123.     str r1, [r0, #DMC_MEMCONTROL]  
    124.   
    125.     ldr r1, =DMC0_MEMCONFIG_0           @MemConfig0 256MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed  
    126.     str r1, [r0, #DMC_MEMCONFIG0]  
    127.   
    128.     ldr r1, =DMC0_MEMCONFIG_1           @MemConfig1  
    129.     str r1, [r0, #DMC_MEMCONFIG1]  
    130.   
    131.     ldr r1, =0xFF000000             @PrechConfig  
    132.     str r1, [r0, #DMC_PRECHCONFIG]  
    133.   
    134.     ldr r1, =DMC0_TIMINGA_REF           @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4E)  
    135.     str r1, [r0, #DMC_TIMINGAREF]  
    136.   
    137.     ldr r1, =DMC0_TIMING_ROW            @TimingRow  for @200MHz  
    138.     str r1, [r0, #DMC_TIMINGROW]  
    139.   
    140.     ldr r1, =DMC0_TIMING_DATA           @TimingData CL=3  
    141.     str r1, [r0, #DMC_TIMINGDATA]  
    142.   
    143.     ldr r1, =DMC0_TIMING_PWR            @TimingPower  
    144.     str r1, [r0, #DMC_TIMINGPOWER]  
    145.   
    146.     ldr r1, =0x07000000             @DirectCmd  chip0 Deselect  
    147.     str r1, [r0, #DMC_DIRECTCMD]  
    148.   
    149.     ldr r1, =0x01000000             @DirectCmd  chip0 PALL  
    150.     str r1, [r0, #DMC_DIRECTCMD]  
    151.   
    152.     ldr r1, =0x00020000             @DirectCmd  chip0 EMRS2  
    153.     str r1, [r0, #DMC_DIRECTCMD]  
    154.   
    155.     ldr r1, =0x00030000             @DirectCmd  chip0 EMRS3  
    156.     str r1, [r0, #DMC_DIRECTCMD]  
    157.   
    158.     ldr r1, =0x00010400             @DirectCmd  chip0 EMRS1 (MEM DLL on, DQS# disable)  
    159.     str r1, [r0, #DMC_DIRECTCMD]  
    160.   
    161.     ldr r1, =0x00000542             @DirectCmd  chip0 MRS (MEM DLL reset) CL=4, BL=4  
    162.     str r1, [r0, #DMC_DIRECTCMD]  
    163.   
    164.     ldr r1, =0x01000000             @DirectCmd  chip0 PALL  
    165.     str r1, [r0, #DMC_DIRECTCMD]  
    166.   
    167.     ldr r1, =0x05000000             @DirectCmd  chip0 REFA  
    168.     str r1, [r0, #DMC_DIRECTCMD]  
    169.   
    170.     ldr r1, =0x05000000             @DirectCmd  chip0 REFA  
    171.     str r1, [r0, #DMC_DIRECTCMD]  
    172.   
    173.     ldr r1, =0x00000442             @DirectCmd  chip0 MRS (MEM DLL unreset)  
    174.     str r1, [r0, #DMC_DIRECTCMD]  
    175.   
    176.     ldr r1, =0x00010780             @DirectCmd  chip0 EMRS1 (OCD default)  
    177.     str r1, [r0, #DMC_DIRECTCMD]  
    178.   
    179.     ldr r1, =0x00010400             @DirectCmd  chip0 EMRS1 (OCD exit)  
    180.     str r1, [r0, #DMC_DIRECTCMD]  
    181.   
    182.     ldr r1, =0x07100000             @DirectCmd  chip1 Deselect  
    183.     str r1, [r0, #DMC_DIRECTCMD]  
    184.   
    185.     ldr r1, =0x01100000             @DirectCmd  chip1 PALL  
    186.     str r1, [r0, #DMC_DIRECTCMD]  
    187.   
    188.     ldr r1, =0x00120000             @DirectCmd  chip1 EMRS2  
    189.     str r1, [r0, #DMC_DIRECTCMD]  
    190.   
    191.     ldr r1, =0x00130000             @DirectCmd  chip1 EMRS3  
    192.     str r1, [r0, #DMC_DIRECTCMD]  
    193.   
    194.     ldr r1, =0x00110400             @DirectCmd  chip1 EMRS1 (MEM DLL on, DQS# disable)  
    195.     str r1, [r0, #DMC_DIRECTCMD]  
    196.   
    197.     ldr r1, =0x00100542             @DirectCmd  chip1 MRS (MEM DLL reset) CL=4, BL=4  
    198.     str r1, [r0, #DMC_DIRECTCMD]  
    199.   
    200.     ldr r1, =0x01100000             @DirectCmd  chip1 PALL  
    201.     str r1, [r0, #DMC_DIRECTCMD]  
    202.   
    203.     ldr r1, =0x05100000             @DirectCmd  chip1 REFA  
    204.     str r1, [r0, #DMC_DIRECTCMD]  
    205.   
    206.     ldr r1, =0x05100000             @DirectCmd  chip1 REFA  
    207.     str r1, [r0, #DMC_DIRECTCMD]  
    208.   
    209.     ldr r1, =0x00100442             @DirectCmd  chip1 MRS (MEM DLL unreset)  
    210.     str r1, [r0, #DMC_DIRECTCMD]  
    211.   
    212.     ldr r1, =0x00110780             @DirectCmd  chip1 EMRS1 (OCD default)  
    213.     str r1, [r0, #DMC_DIRECTCMD]  
    214.   
    215.     ldr r1, =0x00110400             @DirectCmd  chip1 EMRS1 (OCD exit)  
    216.     str r1, [r0, #DMC_DIRECTCMD]  
    217.   
    218.     ldr r1, =0x0FF02030             @ConControl auto refresh on  
    219.     str r1, [r0, #DMC_CONCONTROL]  
    220.   
    221.     ldr r1, =0xFFFF00FF             @PwrdnConfig  
    222.     str r1, [r0, #DMC_PWRDNCONFIG]  
    223.   
    224.     ldr r1, =0x00202400             @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off  
    225.     str r1, [r0, #DMC_MEMCONTROL]  
    226.   
    227.     /* DMC1 initialization */  
    228.     ldr r0, =APB_DMC_1_BASE  
    229.   
    230.     ldr r1, =0x00101000             @Phycontrol0 DLL parameter setting  
    231.     str r1, [r0, #DMC_PHYCONTROL0]  
    232.   
    233.     ldr r1, =0x00000086             @Phycontrol1 DLL parameter setting  
    234.     str r1, [r0, #DMC_PHYCONTROL1]  
    235.   
    236.     ldr r1, =0x00101002             @PhyControl0 DLL on  
    237.     str r1, [r0, #DMC_PHYCONTROL0]  
    238.   
    239.     ldr r1, =0x00101003             @PhyControl0 DLL start  
    240.     str r1, [r0, #DMC_PHYCONTROL0]  
    241. find_lock_val1:  
    242.     ldr r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register value  
    243.     and r2, r1, #0x7  
    244.     cmp r2, #0x7                @Loop until DLL is locked  
    245.     bne find_lock_val1  
    246.   
    247.     and r1, #0x3fc0  
    248.     mov r2, r1, LSL #18  
    249.     orr r2, r2, #0x100000  
    250.     orr r2, r2, #0x1000  
    251.   
    252.     orr r1, r2, #0x3                @Force Value locking  
    253.     str r1, [r0, #DMC_PHYCONTROL0]  
    254.   
    255. #if 0   /* Memory margin test 10.01.05 */  
    256.     orr r1, r2, #0x1                @DLL off  
    257.     str r1, [r0, #DMC_PHYCONTROL0]  
    258. #endif  
    259.   
    260.     /* settinf fot DDR2 */  
    261.     ldr r0, =APB_DMC_1_BASE  
    262.   
    263.     ldr r1, =0x0FFF2010             @auto refresh off  
    264.     str r1, [r0, #DMC_CONCONTROL]  
    265.   
    266.     ldr r1, =DMC1_MEMCONTROL            @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off  
    267.     str r1, [r0, #DMC_MEMCONTROL]  
    268.   
    269.     ldr r1, =DMC1_MEMCONFIG_0           @MemConfig0 512MB config, 8 banks,Mapping Method[12:15]0:linear, 1:linterleaved, 2:Mixed  
    270.     str r1, [r0, #DMC_MEMCONFIG0]  
    271.   
    272.     ldr r1, =DMC1_MEMCONFIG_1           @MemConfig1  
    273.     str r1, [r0, #DMC_MEMCONFIG1]  
    274.   
    275.     ldr r1, =0xFF000000  
    276.     str r1, [r0, #DMC_PRECHCONFIG]  
    277.   
    278.     ldr r1, =DMC1_TIMINGA_REF           @TimingAref 7.8us*133MHz=1038(0x40E), 100MHz=780(0x30C), 20MHz=156(0x9C), 10MHz=78(0x4  
    279.     str r1, [r0, #DMC_TIMINGAREF]  
    280.   
    281.     ldr r1, =DMC1_TIMING_ROW            @TimingRow  for @200MHz  
    282.     str r1, [r0, #DMC_TIMINGROW]  
    283.   
    284.     ldr r1, =DMC1_TIMING_DATA           @TimingData CL=3  
    285.     str r1, [r0, #DMC_TIMINGDATA]  
    286.   
    287.     ldr r1, =DMC1_TIMING_PWR            @TimingPower  
    288.     str r1, [r0, #DMC_TIMINGPOWER]  
    289.   
    290.   
    291.     ldr r1, =0x07000000             @DirectCmd  chip0 Deselect  
    292.     str r1, [r0, #DMC_DIRECTCMD]  
    293.   
    294.     ldr r1, =0x01000000             @DirectCmd  chip0 PALL  
    295.     str r1, [r0, #DMC_DIRECTCMD]  
    296.   
    297.     ldr r1, =0x00020000             @DirectCmd  chip0 EMRS2  
    298.     str r1, [r0, #DMC_DIRECTCMD]  
    299.   
    300.     ldr r1, =0x00030000             @DirectCmd  chip0 EMRS3  
    301.     str r1, [r0, #DMC_DIRECTCMD]  
    302.   
    303.     ldr r1, =0x00010400             @DirectCmd  chip0 EMRS1 (MEM DLL on, DQS# disable)  
    304.     str r1, [r0, #DMC_DIRECTCMD]  
    305.   
    306.     ldr r1, =0x00000542             @DirectCmd  chip0 MRS (MEM DLL reset) CL=4, BL=4  
    307.     str r1, [r0, #DMC_DIRECTCMD]  
    308.   
    309.     ldr r1, =0x01000000             @DirectCmd  chip0 PALL  
    310.     str r1, [r0, #DMC_DIRECTCMD]  
    311.   
    312.     ldr r1, =0x05000000             @DirectCmd  chip0 REFA  
    313.     str r1, [r0, #DMC_DIRECTCMD]  
    314.   
    315.     ldr r1, =0x05000000             @DirectCmd  chip0 REFA  
    316.     str r1, [r0, #DMC_DIRECTCMD]  
    317.   
    318.     ldr r1, =0x00000442             @DirectCmd  chip0 MRS (MEM DLL unreset)  
    319.     str r1, [r0, #DMC_DIRECTCMD]  
    320.   
    321.     ldr r1, =0x00010780             @DirectCmd  chip0 EMRS1 (OCD default)  
    322.     str r1, [r0, #DMC_DIRECTCMD]  
    323.   
    324.     ldr r1, =0x00010400             @DirectCmd  chip0 EMRS1 (OCD exit)  
    325.     str r1, [r0, #DMC_DIRECTCMD]  
    326.   
    327.     ldr r1, =0x07100000             @DirectCmd  chip1 Deselect  
    328.     str r1, [r0, #DMC_DIRECTCMD]  
    329.   
    330.     ldr r1, =0x01100000             @DirectCmd  chip1 PALL  
    331.     str r1, [r0, #DMC_DIRECTCMD]  
    332.   
    333.     ldr r1, =0x00120000             @DirectCmd  chip1 EMRS2  
    334.     str r1, [r0, #DMC_DIRECTCMD]  
    335.   
    336.     ldr r1, =0x00130000             @DirectCmd  chip1 EMRS3  
    337.     str r1, [r0, #DMC_DIRECTCMD]  
    338.   
    339.     ldr r1, =0x00110440             @DirectCmd  chip1 EMRS1 (MEM DLL on, DQS# disable)  
    340.     str r1, [r0, #DMC_DIRECTCMD]  
    341.   
    342.     ldr r1, =0x00100542             @DirectCmd  chip1 MRS (MEM DLL reset) CL=4, BL=4  
    343.     str r1, [r0, #DMC_DIRECTCMD]  
    344.   
    345.     ldr r1, =0x01100000             @DirectCmd  chip1 PALL  
    346.     str r1, [r0, #DMC_DIRECTCMD]  
    347.   
    348.     ldr r1, =0x05100000             @DirectCmd  chip1 REFA  
    349.     str r1, [r0, #DMC_DIRECTCMD]  
    350.   
    351.     ldr r1, =0x05100000             @DirectCmd  chip1 REFA  
    352.     str r1, [r0, #DMC_DIRECTCMD]  
    353.   
    354.     ldr r1, =0x00100442             @DirectCmd  chip1 MRS (MEM DLL unreset)  
    355.     str r1, [r0, #DMC_DIRECTCMD]  
    356.   
    357.     ldr r1, =0x00110780             @DirectCmd  chip1 EMRS1 (OCD default)  
    358.     str r1, [r0, #DMC_DIRECTCMD]  
    359.   
    360.     ldr r1, =0x00110400             @DirectCmd  chip1 EMRS1 (OCD exit)  
    361.     str r1, [r0, #DMC_DIRECTCMD]  
    362.   
    363.     ldr r1, =0x0FF02030             @ConControl auto refresh on  
    364.     str r1, [r0, #DMC_CONCONTROL]  
    365.   
    366.     ldr r1, =0xFFFF00FF             @PwrdnConfig  
    367.     str r1, [r0, #DMC_PWRDNCONFIG]  
    368.   
    369.     ldr r1, =DMC1_MEMCONTROL            @MemControl BL=4, 2 chip, DDR2 type, dynamic self refresh, force precharge, dynamic power down off  
    370.     str r1, [r0, #DMC_MEMCONTROL]  
    371.   
    372. #else   /* CONFIG_MCP_SINGLE */  
    373.   
    374.     /* DMC0 initialization */  
    375.     ldr r0, =APB_DMC_0_BASE  
    376.   
    377.     ldr r1, =0x00101000             @Phycontrol0 DLL parameter setting  
    378.     str r1, [r0, #DMC_PHYCONTROL0]  
    379.   
    380.     ldr r1, =0x00000084             @Phycontrol1 DLL parameter setting  
    381.     str r1, [r0, #DMC_PHYCONTROL1]  
    382.   
    383.     ldr r1, =0x00101002             @Phycontrol2 DLL parameter setting  
    384.     str r1, [r0, #DMC_PHYCONTROL0]  
    385.   
    386.     ldr r1, =0x00101003             @Dll on  
    387.     str r1, [r0, #DMC_PHYCONTROL0]  
    388.   
    389. find_lock_val:  
    390.     ldr r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register value  
    391.     and     r2, r1, #0x7  
    392.     cmp r2, #0x7                @Loop until DLL is locked  
    393.     bne find_lock_val  
    394.   
    395.     and r1, #0x3fc0  
    396.     mov r2, r1, LSL #18  
    397.     orr r2, r2, #0x100000  
    398.     orr r2, r2, #0x1000  
    399.   
    400.     orr r1, r2, #0x3                @Force Value locking  
    401.     str r1, [r0, #DMC_PHYCONTROL0]  
    402. #if 1 /* DRAM margin test 10.01.06 */  
    403.     orr r1, r2, #0x1                @DLL off  
    404.     str r1, [r0, #DMC_PHYCONTROL0]  
    405. #endif  
    406.     ldr r1, =0x0fff1010             @auto refresh off  
    407.     str r1, [r0, #DMC_CONCONTROL]  
    408.   
    409.     ldr r1, =0x00212100  
    410.     str r1, [r0, #DMC_MEMCONTROL]  
    411.   
    412.     ldr r1, =DMC0_MEMCONFIG_0  
    413.     str r1, [r0, #DMC_MEMCONFIG0]  
    414.   
    415.     ldr r1, =DMC0_MEMCONFIG_1  
    416.     str r1, [r0, #DMC_MEMCONFIG1]  
    417.   
    418.     ldr r1, =0xff000000  
    419.     str r1, [r0, #DMC_PRECHCONFIG]  
    420.   
    421.     ldr r1, =DMC0_TIMINGA_REF  
    422.     str r1, [r0, #DMC_TIMINGAREF]  
    423.   
    424.     ldr r1, =DMC0_TIMING_ROW            @TimingRow  @133MHz  
    425.     str r1, [r0, #DMC_TIMINGROW]  
    426.   
    427.     ldr r1, =DMC0_TIMING_DATA  
    428.     str r1, [r0, #DMC_TIMINGDATA]  
    429.   
    430.     ldr r1, =DMC0_TIMING_PWR            @Timing Power  
    431.     str r1, [r0, #DMC_TIMINGPOWER]  
    432.   
    433.     ldr r1, =0x07000000             @chip0 Deselect  
    434.     str r1, [r0, #DMC_DIRECTCMD]  
    435.   
    436.     ldr r1, =0x01000000             @chip0 PALL  
    437.     str r1, [r0, #DMC_DIRECTCMD]  
    438.   
    439.     ldr r1, =0x05000000             @chip0 REFA  
    440.     str r1, [r0, #DMC_DIRECTCMD]  
    441.   
    442.     ldr r1, =0x05000000             @chip0 REFA  
    443.     str r1, [r0, #DMC_DIRECTCMD]  
    444.   
    445.     ldr r1, =0x00000032             @chip0 MRS  
    446.     str r1, [r0, #DMC_DIRECTCMD]  
    447.   
    448.     ldr r1, =0x07100000             @chip1 Deselect  
    449.     str r1, [r0, #DMC_DIRECTCMD]  
    450.   
    451.     ldr r1, =0x01100000             @chip1 PALL  
    452.     str r1, [r0, #DMC_DIRECTCMD]  
    453.   
    454.     ldr r1, =0x05100000             @chip1 REFA  
    455.     str r1, [r0, #DMC_DIRECTCMD]  
    456.   
    457.     ldr r1, =0x05100000             @chip1 REFA  
    458.     str r1, [r0, #DMC_DIRECTCMD]  
    459.   
    460.     ldr r1, =0x00100032             @chip1 MRS  
    461.     str r1, [r0, #DMC_DIRECTCMD]  
    462.   
    463.     ldr r1, =0x0FFF20B0         @ConControl auto refresh on  
    464.     str r1, [r0, #DMC_CONCONTROL]  
    465.   
    466.     ldr r1, =0xFFFF00FF             @PwrdnConfig  
    467.     str r1, [r0, #DMC_PWRDNCONFIG]  
    468.   
    469.     ldr r1, =0x00212113             @MemControl  
    470.     str r1, [r0, #DMC_MEMCONTROL]  
    471.   
    472. /* DMC1 initialization */  
    473.     ldr r0, =APB_DMC_1_BASE  
    474.   
    475.     ldr r1, =0x00101000             @Phycontrol0 DLL parameter setting  
    476.     str r1, [r0, #DMC_PHYCONTROL0]  
    477.   
    478.     ldr r1, =0x00000084             @Phycontrol1 DLL parameter setting  
    479.     str r1, [r0, #DMC_PHYCONTROL1]  
    480.   
    481.     ldr r1, =0x00101002             @Phycontrol2 DLL parameter setting  
    482.     str r1, [r0, #DMC_PHYCONTROL0]  
    483.   
    484.     ldr r1, =0x00101003             @Dll on  
    485.     str r1, [r0, #DMC_PHYCONTROL0]  
    486.   
    487. find_lock_val1:  
    488.     ldr r1, [r0, #DMC_PHYSTATUS]        @Load Phystatus register value  
    489.     and     r2, r1, #0x7  
    490.     cmp r2, #0x7                @Loop until DLL is locked  
    491.     bne find_lock_val1  
    492.   
    493.     and r1, #0x3fc0  
    494.     mov r2, r1, LSL #18  
    495.     orr r2, r2, #0x100000  
    496.     orr r2, r2, #0x1000  
    497.   
    498.     orr r1, r2, #0x3                @Force Value locking  
    499.     str r1, [r0, #DMC_PHYCONTROL0]  
    500.   
    501. #if 1   /* Memory margin test 10.01.05 */  
    502.     orr r1, r2, #0x1                @DLL off  
    503.     str r1, [r0, #DMC_PHYCONTROL0]  
    504. #endif  
    505.     ldr r0, =APB_DMC_1_BASE  
    506.   
    507.     ldr r1, =0x0FFF1010             @auto refresh off  
    508.     str r1, [r0, #DMC_CONCONTROL]  
    509.   
    510.     ldr r1, =DMC1_MEMCONTROL  
    511.     str r1, [r0, #DMC_MEMCONTROL]  
    512.   
    513.     ldr r1, =DMC1_MEMCONFIG_0  
    514.     str r1, [r0, #DMC_MEMCONFIG0]  
    515.   
    516.     ldr r1, =DMC1_MEMCONFIG_1  
    517.     str r1, [r0, #DMC_MEMCONFIG1]  
    518.   
    519.     ldr r1, =0xff000000  
    520.     str r1, [r0, #DMC_PRECHCONFIG]  
    521.   
    522.     ldr r1, =DMC1_TIMINGA_REF  
    523.     str r1, [r0, #DMC_TIMINGAREF]  
    524.   
    525.     ldr r1, =DMC1_TIMING_ROW            @TimingRow  @133MHz  
    526.     str r1, [r0, #DMC_TIMINGROW]  
    527.   
    528.     ldr r1, =DMC1_TIMING_DATA  
    529.     str r1, [r0, #DMC_TIMINGDATA]  
    530.   
    531.     ldr r1, =DMC1_TIMING_PWR            @Timing Power  
    532.     str r1, [r0, #DMC_TIMINGPOWER]  
    533.   
    534.     ldr r1, =0x07000000             @chip0 Deselect  
    535.     str r1, [r0, #DMC_DIRECTCMD]  
    536.   
    537.     ldr r1, =0x01000000             @chip0 PALL  
    538.     str r1, [r0, #DMC_DIRECTCMD]  
    539.   
    540.     ldr r1, =0x05000000             @chip0 REFA  
    541.     str r1, [r0, #DMC_DIRECTCMD]  
    542.   
    543.     ldr r1, =0x05000000             @chip0 REFA  
    544.     str r1, [r0, #DMC_DIRECTCMD]  
    545.   
    546.     ldr r1, =0x00000032             @chip0 MRS  
    547.     str r1, [r0, #DMC_DIRECTCMD]  
    548.   
    549.     ldr r1, =0x00020020             @chip0 EMRS  
    550.     str r1, [r0, #DMC_DIRECTCMD]  
    551.   
    552.     ldr r1, =0x07100000             @chip1 Deselect  
    553.     str r1, [r0, #DMC_DIRECTCMD]  
    554.   
    555.     ldr r1, =0x01100000             @chip1 PALL  
    556.     str r1, [r0, #DMC_DIRECTCMD]  
    557.   
    558.     ldr r1, =0x05100000             @chip1 REFA  
    559.     str r1, [r0, #DMC_DIRECTCMD]  
    560.   
    561.     ldr r1, =0x05100000             @chip1 REFA  
    562.     str r1, [r0, #DMC_DIRECTCMD]  
    563.   
    564.     ldr r1, =0x00100032             @chip1 MRS  
    565.     str r1, [r0, #DMC_DIRECTCMD]  
    566.   
    567.     ldr r1, =0x00120020             @chip0 EMRS  
    568.     str r1, [r0, #DMC_DIRECTCMD]  
    569.   
    570.     ldr r1, =0x0FFF10B0             @ConControl auto refresh on  
    571.     str r1, [r0, #DMC_CONCONTROL]  
    572.   
    573.     ldr r1, =0xFFFF00FF             @PwrdnConfig  
    574.     str r1, [r0, #DMC_PWRDNCONFIG]  
    575.   
    576.     ldr r1, =0x00212113             @MemControl  
    577.     str r1, [r0, #DMC_MEMCONTROL]  
    578.   
    579. #endif  /* CONFIG_MCP_AC / CONFIG_MCP_H / CONFIG_MCP_B / CONFIG_MCP_D / CONFIG_MCP_N */  
    580.   
    581.     mov pc, lr  
    582.   
    583. /* 
    584.  *     v7_flush_dcache_all() 
    585.  * 
    586.  *     Flush the whole D-cache. 
    587.  * 
    588.  *     Corrupted registers: r0-r5, r7, r9-r11 
    589.  * 
    590.  *     - mm    - mm_struct describing address space 
    591.  */  
    592.        .align 5  
    593. .global v7_flush_dcache_all  
    594. v7_flush_dcache_all:  
    595.   
    596.     ldr r0, =0xffffffff  
    597.     mrc p15, 1, r0, c0, c0, 1       @ Read CLIDR  
    598.     ands    r3, r0, #0x7000000  
    599.     mov r3, r3, LSR #23             @ Cache level value (naturally aligned)  
    600.     beq     Finished  
    601.     mov r10, #0  
    602. Loop1:  
    603.     add r2, r10, r10, LSR #1        @ Work out 3xcachelevel  
    604.     mov r1, r0, LSR r2              @ bottom 3 bits are the Ctype for this level  
    605.     and r1, r1, #7                  @ get those 3 bits alone  
    606.     cmp r1, #2  
    607.     blt Skip                        @ no cache or only instruction cache at this level  
    608.     mcr p15, 2, r10, c0, c0, 0      @ write the Cache Size selection register  
    609.     mov r1, #0  
    610.     mcr p15, 0, r1, c7, c5, 4       @ PrefetchFlush to sync the change to the CacheSizeID reg  
    611.     mrc p15, 1, r1, c0, c0, 0       @ reads current Cache Size ID register  
    612.     and r2, r1, #0x7                @ extract the line length field  
    613.     add r2, r2, #4                  @ add 4 for the line length offset (log2 16 bytes)  
    614.     ldr r4, =0x3FF  
    615.     ands    r4, r4, r1, LSR #3          @ R4 is the max number on the way size (right aligned)  
    616.     clz r5, r4                      @ R5 is the bit position of the way size increment  
    617.     ldr r7, =0x00007FFF  
    618.     ands    r7, r7, r1, LSR #13         @ R7 is the max number of the index size (right aligned)  
    619. Loop2:  
    620.     mov r9, r4                          @ R9 working copy of the max way size (right aligned)  
    621. Loop3:  
    622.     orr r11, r10, r9, LSL r5            @ factor in the way number and cache number into R11  
    623.     orr r11, r11, r7, LSL r2            @ factor in the index number  
    624.     mcr p15, 0, r11, c7, c6, 2      @ invalidate by set/way  
    625.     subs    r9, r9, #1                  @ decrement the way number  
    626.     bge Loop3  
    627.     subs    r7, r7, #1                  @ decrement the index  
    628.     bge Loop2  
    629. Skip:  
    630.     add r10, r10, #2                    @ increment the cache number  
    631.     cmp r3, r10  
    632.     bgt Loop1  
    633. Finished:  
    634.     mov pc, lr  
    635.   
    636.        .align  5  
    637. .global disable_l2cache  
    638. disable_l2cache:  
    639.     mrc     p15, 0, r0, c1, c0, 1  
    640.     bic     r0, r0, #(1<<1)  
    641.     mcr     p15, 0, r0, c1, c0, 1  
    642.     mov pc, lr  
    643.   
    644.   
    645.        .align  5  
    646. .global enable_l2cache  
    647. enable_l2cache:  
    648.     mrc     p15, 0, r0, c1, c0, 1  
    649.     orr     r0, r0, #(1<<1)  
    650.     mcr     p15, 0, r0, c1, c0, 1  
    651.     mov     pc, lr  
    652.   
    653.        .align  5  
    654. .global set_l2cache_auxctrl  
    655. set_l2cache_auxctrl:  
    656.     mov r0, #0x0  
    657.     mcr     p15, 1, r0, c9, c0, 2  
    658.     mov     pc, lr  
    659.   
    660.        .align  5  
    661. .global set_l2cache_auxctrl_cycle  
    662. set_l2cache_auxctrl_cycle:  
    663.     mrc     p15, 1, r0, c9, c0, 2  
    664.     bic     r0, r0, #(0x1<<29)  
    665.     bic     r0, r0, #(0x1<<21)  
    666.     bic     r0, r0, #(0x7<<6)  
    667.     bic     r0, r0, #(0x7<<0)  
    668.     mcr     p15, 1, r0, c9, c0, 2  
    669.     mov     pc,lr  
    670.   
    671.     .align 5  
    672. CoInvalidateDCacheIndex:  
    673.     ;/* r0 = index */  
    674.     mcr     p15, 0, r0, c7, c6, 2  
    675.     mov     pc,lr  
    676.   
    677.   
    678. /* Below code is for ARM926EJS and ARM1026EJS */  
    679.     .globl cleanDCache  
    680. cleanDCache:  
    681.     mrc p15, 0, pc, c7, c10, 3  /* test/clean D-Cache */  
    682.     bne cleanDCache  
    683.     mov pc, lr  
    684.   
    685.     .globl cleanFlushDCache  
    686. cleanFlushDCache:  
    687.     mrc p15, 0, pc, c7, c14, 3  /* test/cleanflush D-Cache */  
    688.     bne cleanFlushDCache  
    689.     mov pc, lr  
    690.   
    691.     .globl cleanFlushCache  
    692. cleanFlushCache:  
    693.     mrc p15, 0, pc, c7, c14, 3  /* test/cleanflush D-Cache */  
    694.     bne cleanFlushCache  
    695.     mcr p15, 0, r0, c7, c5, 0   /* flush I-Cache */  
    696.     mov pc, lr  
    697.   
    698.     .ltorg  
    699.   
    700.   
    701.   
    702.     .globl ledon_1  
    703. ledon_1:  
    704.     /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/  
    705.     ldr r0, =ELFIN_GPIO_BASE  
    706.     ldr r1, =0x11000  
    707.     str r1, [r0, #GPC0CON_OFFSET]  
    708.     ldr r2, [r0, #GPC0CON_OFFSET]  
    709.     orr r2, r2, #0x08  
    710.     str r2, [r0, #GPC0DAT_OFFSET]  
    711.     mov pc, lr  
    712.   
    713.     .globl ledon_2  
    714. ledon_2:  
    715.     /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/  
    716.     ldr r0, =ELFIN_GPIO_BASE  
    717.     ldr r1, =0x11000  
    718.     str r1, [r0, #GPC0CON_OFFSET]  
    719.     ldr r2, [r0, #GPC0CON_OFFSET]  
    720.     orr r2, r2, #0x10  
    721.     str r2, [r0, #GPC0DAT_OFFSET]  
    722.     mov pc, lr  
    723.   
    724.     .globl ledon  
    725. ledon:  
    726.     /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/  
    727.     ldr r0, =ELFIN_GPIO_BASE  
    728.     ldr r1, =0x11000  
    729.     str r1, [r0, #GPC0CON_OFFSET]  
    730.     ldr r2, =0x18  
    731.     str r2, [r0, #GPC0DAT_OFFSET]  
    732.     mov pc, lr  
    733.   
    734.     .globl ledoff  
    735. ledoff:  
    736.     /*打开led,0x00全灭,0x08为led3亮,0x10为led4亮,0x18为led3,4均亮*/  
    737.     ldr r0, =ELFIN_GPIO_BASE  
    738.     ldr r1, =0x11000  
    739.     str r1, [r0, #GPC0CON_OFFSET]  
    740.     ldr r2, =0x00  
    741.     str r2, [r0, #GPC0DAT_OFFSET]  
    742.     mov pc, lr  






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

    1. /* 
    2.  *  crt0 - C-runtime startup Code for ARM U-Boot 
    3.  * 
    4.  *  Copyright (c) 2012  Albert ARIBAUD <albert.u.boot@aribaud.net> 
    5.  * 
    6.  * See file CREDITS for list of people who contributed to this 
    7.  * project. 
    8.  * 
    9.  * This program is free software; you can redistribute it and/or 
    10.  * modify it under the terms of the GNU General Public License as 
    11.  * published by the Free Software Foundation; either version 2 of 
    12.  * the License, or (at your option) any later version. 
    13.  * 
    14.  * This program is distributed in the hope that it will be useful, 
    15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
    16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    17.  * GNU General Public License for more details. 
    18.  * 
    19.  * You should have received a copy of the GNU General Public License 
    20.  * along with this program; if not, write to the Free Software 
    21.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
    22.  * MA 02111-1307 USA 
    23.  */  
    24.   
    25. #include <config.h>  
    26. #include <asm-offsets.h>  
    27.   
    28. /* 
    29.  * This file handles the target-independent stages of the U-Boot 
    30.  * start-up where a C runtime environment is needed. Its entry point 
    31.  * is _main and is branched into from the target’s start.S file. 
    32.  * 
    33.  * _main execution sequence is: 
    34.  * 
    35.  * 1. Set up initial environment for calling board_init_f(). 
    36.  *    This environment only provides a stack and a place to store 
    37.  *    the GD (‘global data’) structure, both located in some readily 
    38.  *    available RAM (SRAM, locked cache…). In this context, VARIABLE 
    39.  *    global data, initialized or not (BSS), are UNAVAILABLE; only 
    40.  *    CONSTANT initialized data are available. 
    41.  * 
    42.  * 2. Call board_init_f(). This function prepares the hardware for 
    43.  *    execution from system RAM (DRAM, DDR…) As system RAM may not 
    44.  *    be available yet, , board_init_f() must use the current GD to 
    45.  *    store any data which must be passed on to later stages. These 
    46.  *    data include the relocation destination, the future stack, and 
    47.  *    the future GD location. 
    48.  * 
    49.  * (the following applies only to non-SPL builds) 
    50.  * 
    51.  * 3. Set up intermediate environment where the stack and GD are the 
    52.  *    ones allocated by board_init_f() in system RAM, but BSS and 
    53.  *    initialized non-const data are still not available. 
    54.  * 
    55.  * 4. Call relocate_code(). This function relocates U-Boot from its 
    56.  *    current location into the relocation destination computed by 
    57.  *    board_init_f(). 
    58.  * 
    59.  * 5. Set up final environment for calling board_init_r(). This 
    60.  *    environment has BSS (initialized to 0), initialized non-const 
    61.  *    data (initialized to their intended value), and stack in system 
    62.  *    RAM. GD has retained values set by board_init_f(). Some CPUs 
    63.  *    have some work left to do at this point regarding memory, so 
    64.  *    call c_runtime_cpu_setup. 
    65.  * 
    66.  * 6. Branch to either nand_boot() or board_init_r(). 
    67.  */  
    68.   
    69. /* 
    70.  * declare nand_boot() or board_init_r() to jump to at end of crt0 
    71.  */  
    72.   
    73. #if defined(CONFIG_NAND_SPL)  
    74.   
    75. .globl nand_boot  
    76.   
    77.   
    78. #elif !defined(CONFIG_SPL_BUILD)  
    79.   
    80. .globl board_init_r  
    81.   
    82. #endif  
    83.   
    84. /* 
    85.  * start and end of BSS 
    86.  */  
    87.   
    88. .globl __bss_start  
    89. .globl __bss_end__  
    90.   
    91. /* 
    92.  * entry point of crt0 sequence 
    93.  */  
    94.   
    95. .global _main  
    96.   
    97. _main:  
    98.   
    99. /* 
    100.  * Set up initial C runtime environment and call board_init_f(0). 
    101.  */  
    102.   
    103. #if defined(CONFIG_NAND_SPL)  
    104.     /* deprecated, use instead CONFIG_SPL_BUILD */  
    105.     ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)  
    106. #elif defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)  
    107.     ldr sp, =(CONFIG_SPL_STACK)  
    108. #else  
    109.     ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)  
    110. #endif  
    111.     bic sp, sp, #7  /* 8-byte alignment for ABI compliance */  
    112.     sub sp, #GD_SIZE    /* allocate one GD above SP */  
    113.     bic sp, sp, #7  /* 8-byte alignment for ABI compliance */  
    114.     mov r8, sp      /* GD is above SP */  
    115.     mov r0, #0  
    116.     bl  board_init_f  
    117.   
    118. #if ! defined(CONFIG_SPL_BUILD)  
    119.   
    120. /* 
    121.  * Set up intermediate environment (new sp and gd) and call 
    122.  * relocate_code(addr_sp, gd, addr_moni). Trick here is that 
    123.  * we’ll return ‘here’ but relocated. 
    124.  */  
    125.   
    126.     ldr sp, [r8, #GD_START_ADDR_SP] /* r8 = gd->start_addr_sp */  
    127.     bic sp, sp, #7  /* 8-byte alignment for ABI compliance */  
    128.     ldr r8, [r8, #GD_BD]        /* r8 = gd->bd */  
    129.     sub r8, r8, #GD_SIZE        /* new GD is below bd */  
    130.   
    131.     adr lr, here  
    132.     ldr r0, [r8, #GD_RELOC_OFF]     /* lr = gd->start_addr_sp */  
    133.     add lr, lr, r0  
    134.     ldr r0, [r8, #GD_START_ADDR_SP] /* r0 = gd->start_addr_sp */  
    135.     mov r1, r8              /* r1 = gd */  
    136.     ldr r2, [r8, #GD_RELOCADDR]     /* r2 = gd->relocaddr */  
    137.     b   relocate_code  
    138. here:  
    139.   
    140. /* Set up final (full) environment */  
    141.   
    142.     bl  c_runtime_cpu_setup /* we still call old routine here */  
    143.   
    144.     ldr r0, =__bss_start    /* this is auto-relocated! */  
    145.     ldr r1, =__bss_end__    /* this is auto-relocated! */  
    146.   
    147.     mov r2, #0x00000000     /* prepare zero to clear BSS */  
    148.   
    149. clbss_l:cmp r0, r1          /* while not at end of BSS */  
    150.     strlo   r2, [r0]        /* clear 32-bit BSS word */  
    151.     addlo   r0, r0, #4      /* move to next */  
    152.     blo clbss_l  
    153.   
    154.     bl coloured_LED_init  
    155.     bl red_led_on  
    156.   
    157. #if defined(CONFIG_NAND_SPL)  
    158.   
    159.     /* call _nand_boot() */  
    160.     ldr     pc, =nand_boot  
    161.   
    162. #else  
    163.     /* call board_init_r(gd_t *id, ulong dest_addr) */  
    164.     mov r0, r8          /* gd_t */  
    165.     ldr r1, [r8, #GD_RELOCADDR] /* dest_addr */  
    166.     /* call board_init_r */  
    167.     ldr pc, =board_init_r   /* this is auto-relocated! */  
    168.   
    169. #endif  
    170.   
    171.     /* we should not return here. */  
    172.   
    173. #endif  



    展开全文
  • uboot启动流程

    2019-05-15 16:44:00
    对于学习嵌入式的伙伴对于uboot都不陌生,今天我们就来了解一些关于uboot启动流程的一些相关知识,老样子本文结尾会有uboot启动流程的视频资料。  uboot启动流程如下:  1)设置CPU为管理模式  2)关看门狗  3)...

    对于学习嵌入式的伙伴对于uboot都不陌生,今天我们就来了解一些关于uboot启动流程的一些相关知识,老样子本文结尾会有uboot启动流程的视频资料。

      uboot启动流程如下:

      1)设置CPU为管理模式

      2)关看门狗

      3)关中断

      4)设置时钟频率

      5)关mmu,初始化各个bank

      6)进入board_init_f()函数 (初始化定时器,GPIO,串口等,划分内存区域)

      7)重定位 复制uboot,然后修改SDRAM上的uboot链接地址)

      8)清bss

      9)跳转到board_init_r()函数,启动流程结束

    -----------------------------------------------------------------------------------------------

      1.首先来安装arm-linux-gcc-4.3.2交叉编译器

    mkdir  arm-linux-gcc-4.3.2                 //创建目录
    
    tar -xjf  arm-linux-gcc-4.3.2.tar.bz2 -C arm-linux-gcc-4.3.2/  //解压到arm-linux-gcc-4.3.2目录下

      然后添加环境变量:

      有两种方法,第一种只是临时修改,重启虚拟机便会复位:

    export PATH=/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin:/usr/sbin:/usr/bin... ...
                 //将arm-linux-gcc-4.3.2添加到环境变量

      第二种,重启不复位:

    vi /etc/environment
    添加:
    PATH=/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin:/usr/sbin:/usr/bin... ...
                       //将arm-linux-gcc-4.3.2添加到环境变量

      2.然后进入ftp://ftp.denx.de/pub/u-boot/来下载u-boot-2012.04.01

      2.1.创建source insight工程,来看代码

      1)在board 目录下只添加:

    board/samsung/smdk2410/               // (2410单板文件)

      2)在arch 目录下只添加:

    arch/arm/cpu/arm920t/                //(只添加这个目录下的*.c,*.S公用文件)                
    
    arch/arm/cpu/arm920t/s3c24x0/        //(24x0架构所有文件)
    
    arch/arm/include/asm/                //(只添加这个目录下的*.h公用头文件)
    
    arch/arm/include/asm/proc-armv/      //(arm架构的文件)
    
    arch/arm/include/asm/arch-s3c24x0/   //(24x0架构头文件)
    
    arch/arm/lib/                        //(与arm相关的库文件)

      3)在include/configs目录下只添加:

    include/configs/smdk2410.h              // (用来配置2410单板的头文件)

      2.2编译烧写:

    tar xjf u-boot-2012.04.01.tar.bz2
    
    cd u-boot-2012.04.01                 //进入解压后文件目录
    
    make smdk2410_config                 //由于该uboot不支持2440板卡,所以只有配置2410板卡
    
    make                                 //编译,生成u-boot.bin 

      3.最后烧写u-boot.bin,发现无法启动,接下来便来分析uboot的启动流程

      4.首先查看arch/arm/cpu/u-boot.lds链接脚本

      如下图所示,看到uboot最开始会进入_start:

      5. _start位于arch/arm/cpu/arm920t/start.S

      所以,我们从start.S开始分析uboot启动流程:

    .globl _start                                //声明_start全局符号,这个符号会被lds链接脚本用到
    _start:    
    b     start_code                            //跳转到start_code符号处,0x00
           ldr   pc, _undefined_instruction                    //0x04
           ldr   pc, _software_interrupt                       //0x08
           ldr   pc, _prefetch_abort                           //0x0c
           ldr   pc, _data_abort                               //0x10
           ldr   pc, _not_used                                 //0x14
           ldr   pc, _irq                                      //0x18
           ldr   pc, _fiq                                      //0x20
    
    _undefined_instruction:  .word undefined_instruction
               //定义_undefined_instruction指向undefined_instruction(32位地址)
    
    _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
    
       .balignl 16,0xdeadbeef        //balignl使用,参考http://www.cnblogs.com/lifexy/p/7171507.html

      其中符号保存的地址都在顶层目录/system.map中列出来了

      6. 从上面看到, _start会跳转到start_code处

    start_code:
    
        /*设置CPSR寄存器,让CPU进入管理模式*/
           mrs  r0, cpsr                 //读出cpsr的值
           bic   r0, r0, #0x1f           //清位
           orr   r0, r0, #0xd3          //位或
           msr  cpsr, r0                 //写入cpsr
    
    #if   defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
           /*
            * relocate exception table
            */
           ldr   r0, =_start            
           ldr   r1, =0x0                //r1等于异常向量基地址
           mov r2, #16
    copyex:
           subs       r2, r2, #1           //减16次,s表示每次减都要更新条件标志位
           ldr   r3, [r0], #4       
           str   r3, [r1], #4      //将_start标号后的16个符号存到异常向量基地址0x0~0x3c处
           bne  copyex             //直到r2减为0
    #endif
    
    #ifdef CONFIG_S3C24X0
    
           /* 关看门狗*/
    #  define pWTCON       0x53000000
    #  define INTMSK 0x4A000008    /* Interrupt-Controller base addresses */
    #  define INTSUBMSK  0x4A00001C
    #  define CLKDIVN       0x4C000014    /* clock divisor register */
    
           ldr   r0, =pWTCON       
           mov r1, #0x0        
           str   r1, [r0]           //关看门狗,使WTCON寄存器=0
    
           /*关中断*/
           mov r1, #0xffffffff
           ldr   r0, =INTMSK
           str   r1, [r0]                  //关闭所有中断
    # if defined(CONFIG_S3C2410)
           ldr   r1, =0x3ff
           ldr   r0, =INTSUBMSK
           str   r1, [r0]                  //关闭次级所有中断
    # endif
    
        /* 设置时钟频率, FCLK:HCLK:PCLK = 1:2:4 ,而FCLK默认为120Mhz*/
           ldr   r0, =CLKDIVN
           mov r1, #3
           str   r1, [r0]
    
     #ifndef CONFIG_SKIP_LOWLEVEL_INIT
           bl    cpu_init_crit                         //关闭mmu,并初始化各个bank
    
    #endif
    
    call_board_init_f:
           ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR) //CONFIG_SYS_INIT_SP_ADDR=0x30000f80
           bic   sp, sp, #7         //sp=0x30000f80
           ldr   r0,=0x00000000
           bl    board_init_f   

      上面的CONFIG_SYS_INIT_SP_ADDR =0x30000f80,是通过arm-linux-objdump -D u-boot>u-boot.dis生成反汇编,然后从u-boot.dis得到的,如下图所示:

     

      7.然后进入第一个C函数:board_init_f()

      该函数主要工作是:

      清空gd指向的结构体、通过init_sequence函数数组,来初始化各个函数以及逐步填充gd结构体,最后划分内存区域,将数据保存在gd里,然后调用relocate_code()对uboot重定位

      (gd是用来传递给内核的参数)

      1)具体代码如下所示:

    void board_init_f(ulong bootflag) // bootflag=0x00000000
    {
           bd_t *bd;
           init_fnc_t **init_fnc_ptr;         //函数指针
           gd_t *id;
           ulong addr, addr_sp;
    #ifdef CONFIG_PRAM
           ulong reg;
    #endif
    
           bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
           /* Pointer is writable since we allocated a register for it */
           gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

      其中gd是一个全局变量,用来传递给内核的参数用的,如下图所示,在arch/arn/include/asm/global_data.h中定义,*gd指向r8寄存器,所以r8专门提供给gd使用

      而CONFIG_SYS_INIT_SP_ADDR,在6节里得到=0x30000f80,所以gd=0x30000f80

      2)继续来看board_init_f():

          __asm__ __volatile__("": : :"memory");           //memory:让cpu重新读取内存的数据
    
          memset((void *)gd, 0, sizeof(gd_t));        //将0x30000f80地址上的gd_t结构体清0
    
          gd->mon_len = _bss_end_ofs;  
             // _bss_end_ofs =__bss_end__ - _start,在反汇编找到等于0xae4e0,所以mon_len等于uboot的数据长度
          gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob);
    
           for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
                //调用init_sequence[]数组里的各个函数
          {
                  if ((*init_fnc_ptr)() != 0)     //执行函数,若函数执行出错,则进入hang()
                 {               hang ();   //打印错误信息,然后一直while
                 }
    
           }

      上面的init_sequence[]数组里存了各个函数,比如有:

      board_early_init_f():设置系统时钟,设置各个GPIO引脚

      timer_init():初始化定时器

      env_init():设置gd的成员变量

      init_baudrate():设置波特率

      dram_init():设置gd->ram_size= 0x04000000(64MB)

      3)继续来看board_init_f():

    addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;  // addr=0x34000000 
    // CONFIG_SYS_SDRAM_BASE:  SDRAM基地址,为0X30000000
    // gd->ram_size:          等于0x04000000 
    
    
    #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
           /* reserve TLB table */
           addr -= (4096 * 4);        //addr=33FFC000
    
           addr &= ~(0x10000 - 1);  // addr=33FF0000,   
    
           gd->tlb_addr = addr;   //将64kB分配给TLB,所以TLB地址为33FF0000~33FFFFFF
    #endif
    
           /* round down to next 4 kB limit */
           addr &= ~(4096 - 1);                    //4kb对齐, addr=33FF0000
           debug("Top of RAM usable for U-Boot at: %08lx\n", addr);
           /*
            * reserve memory for U-Boot code, data & bss
            * round down to next 4 kB limit
            */
           addr -= gd->mon_len; // 在前面分析过gd->mon_len=0xae4e0,
                               //所以addr=33FF0000 -0xae4e0=33F41B20,
    
           addr &= ~(4096 - 1);  //4095=0xfff,4kb对齐, addr=33F41000
                                 //所以分配给uboot各个段的重定位地址为33F41000~33FFFFFF
           debug("Reserving %ldk for U-Boot at: %08lx\n", gd->mon_len >> 10, addr);
    
    #ifndef CONFIG_SPL_BUILD
           addr_sp = addr - TOTAL_MALLOC_LEN; //分配一段malloc空间给addr_sp
                           //TOTAL_MALLOC_LEN=1024*1024*4,所以malloc空间为33BF1000~33F40FFF
    
           addr_sp -= sizeof (bd_t);            //分配一段bd_t结构体大的空间
        bd = (bd_t *) addr_sp;               //bd指向刚刚分配出来的bd_t结构体
        gd->bd = bd;                         // 0x30000f80处的gd变量的成员bd等于bd_t基地址
    
        addr_sp -= sizeof (gd_t);              //分配一个gd_t结构体大的空间
        id = (gd_t *) addr_sp;                 //id指向刚刚分配的gd_t结构体
        gd->irq_sp = addr_sp;                 //0x30000f80处的gd变量的成员irq_sp等于gd_t基地址
        addr_sp -= 12;
        addr_sp &= ~0x07;
        ... ...
    
        relocate_code(addr_sp, id, addr);  //进入relocate_code()函数,重定位代码,以及各个符号
        // addr_sp: 栈顶,该栈顶向上的位置用来存放gd->irq_sp、id 、gd->bd、malloc、uboot、TLB(64kb),
        //id:       存放 gd_t结构体的首地址
        // addr:    等于存放uboot重定位地址33F41000
    }

      执行完board_init_f()后,最终内存会划分如下图所示:

      其实此时uboot还在flash中运行,然后会进入start.S的relocate_code()里进行uboot重定位

      8.接下来进入重定位

      1)start.S的relocate_code()代码如下所示

    relocate_code:
           mov r4, r0      /* save addr_sp */              // addr_sp栈顶值
           mov r5, r1      /* save addr of gd */           // id值
           mov r6, r2      /* save addr of destination */  // addr值:uboot重定位地址
    
           /* Set up the stack        */
    stack_setup:
           mov sp, r4                //设置栈addr_sp
           adr  r0, _start           //在顶层目录下system.map符号文件中找到_start =0,所以r0=0
           cmp r0, r6                //判断_start(uboot重定位之前的地址)和addr(重定位地址)是否一样
           beq clear_bss             /* skip relocation */ 
           mov r1, r6             /* r1 <- scratch for copy_loop */ //r1= addr(重定位地址)
           ldr   r3, _bss_start_ofs               //_bss_start_ofs=__bss_start - _start(uboot代码大小)
           add r2, r0, r3         /* r2 <- source end address*/   //r2= uboot重定位之前的结束地址
    
    copy_loop:
           ldmia      r0!, {r9-r10}  /* copy from source address [r0] */
                                  //将r0处的两个32位数据拷到r9-r10中,然后r0+=8
    
           stmia      r1!, {r9-r10}  /* copy to   target address [r1]*/
                                 //将拷出来的两个数据放入r1(重定位地址)处,然后r1+=8
    
           cmp r0, r2  /* until source end address [r2]*/   //判断拷贝的数据是否到结束地址
           blo  copy_loop

      上面只是把代码复制到SDRAM上,而链接地址内容却没有改变,比如异常向量0x04的代码内容还是0x1e0,

      我们以异常向量0x04为例,来看它的反汇编:

      如上图所示,即使uboot在SDRAM运行,由于代码没修改,PC也会跳到0x1e0(flash地址)上

      和之前老的uboot有很大区别,以前老的uboot直接是使用的SDRAM链接地址,如下图所示:

      所以,新的uboot采用了动态链接地址的方法,在链接脚本uboot.lds中,可以看到这两个段(.rel.dyn、.dynsym):

      该两个段里,便是保存了各个文件的相对动态信息(.rel.dyn)、动态链接地址的符号(.dynsym)

      以上图的.rel.dyn段为例来分析,找到__rel_dyn_start符号处:

      如上图所示,其中0x17表示的是符号的结束标志位,我们以0x20为例来讲解:

      在之前,我们讲过0x20里面保存的是异常向量0x04跳转的地址(0x1e0),如下图所示:

     

      所以,接下来的代码,便会根据0x20里的值0x1e0(flash地址),将SDRAM的33F41000+0x20的内容改为33F41000+0x1e0(SDRAM地址),来改变uboot的链接地址

      2)重定位的剩余代码,如下所示:

    #ifndef CONFIG_SPL_BUILD
           /*
            * fix .rel.dyn relocations
            */
           ldr   r0, _TEXT_BASE             /* r0 <- Text base */  //r0=text段基地址=0
           sub  r9, r6, r0         /* r9 <- relocation offset */   //r9= 重定位后的偏移值=33F41000
           ldr   r10, _dynsym_start_ofs  /* r10 <- sym table ofs */ 
                                              //_dynsym_start_ofs =__dynsym_start - _start=0x73608
                                              //所以r10=动态符号表的起始偏移值=0x73608
    
           add r10, r10, r0            /* r10 <- sym table in FLASH */
                                           //r10=flash上的动态符号表基地址=0x73608
    
           ldr   r2, _rel_dyn_start_ofs     /* r2 <- rel dyn start ofs */
                                              //r2=__rel_dyn_start - _start=0x6b568
                                              //所以r2=相对动态信息的起始偏移值=0x6b568
    
           add r2, r2, r0         /* r2 <- rel dyn start in FLASH */
                                          //r2=flash上的相对动态信息基地址=0x6b568
    
           ldr   r3, _rel_dyn_end_ofs      /* r3 <- rel dyn end ofs */
                                              // _rel_dyn_end_ofs=__rel_dyn_end - _start=00073608
                                              //所以r3=相对动态信息的结束偏移值=00073608
           add r3, r3, r0         /* r3 <- rel dyn end in FLASH */
                                        //r3=flash上的相对动态信息结束地址=0x6b568
    fixloop:
           ldr   r0, [r2]           /* r0 <- location to fix up, IN FLASH! */
                                   //以0x20为例,r0=0x6b568地址处的内容= 0x20
    
           add r0, r0, r9         /* r0 <- location to fix up in RAM */
                                         //r0=33F41000+0x20=33F41020
    
           ldr   r1, [r2, #4]             //r1= 33F41024地址处的内容=0x17
           and  r7, r1, #0xff       
           cmp r7, #23                  /* relative fixup? */  //0x17=23,所以相等
           beq fixrel                                       //跳到:fixerl
    
           cmp r7, #2                    /* absolute fixup? */
           beq fixabs
           /* ignore unknown type of fixup */
           b     fixnext
    fixabs:
           /* absolute fix: set location to (offset) symbol value */
           mov r1, r1, LSR #4         /* r1 <- symbol index in .dynsym */
           add r1, r10, r1              /* r1 <- address of symbol in table */
           ldr   r1, [r1, #4]             /* r1 <- symbol value */
           add r1, r1, r9         /* r1 <- relocated sym addr */
           b     fixnext
    
    fixrel:
           /* relative fix: increase location by offset */
           ldr   r1, [r0]                  //r1=33F41020地址处的内容=0x1e0
           add r1, r1, r9                //r1=0x1e0+33F41000= 33F411e0
    
    fixnext:
           str   r1, [r0]             //改变链接地址里的内容, 33F41020=33F411e0  (之前为0x1e0)   
           add r2, r2, #8             //r2等于下一个相对动态信息(0x24)的地址
           cmp r2, r3                //若没到尾部__rel_dyn_end,便继续执行: fixloop
           blo  fixloop                 
    #endif

      9.清除bss段

    /*重定位完成后,清除bss段*/
    clear_bss:
     #ifndef CONFIG_SPL_BUILD
           ldr   r0, _bss_start_ofs                        //获取flash上的bss段起始位置
           ldr   r1, _bss_end_ofs                          //获取flash上的bss段结束位置
           mov r4, r6                    /* reloc addr */     //获取r6(SDRAM上的uboot基地址)
           add r0, r0, r4                                  //加上重定位偏移值,得到SDRAM上的bss段起始位置
           add r1, r1, r4                                     //得到SDRAM上的bss段结束位置
           mov r2, #0x00000000           /* clear*/
    
    clbss_l:
        str    r2, [r0]           /* clear loop...       */                 //开始清除SDRAM上的bss段
           add r0, r0, #4
           cmp r0, r1
           bne  clbss_l
           bl coloured_LED_init
           bl red_led_on
    #endif

      9.1继续往下分析

    #ifdef CONFIG_NAND_SPL                   //未定义,所以不执行
      ... ...                          
    #else                                   //执行else
    
           ldr   r0, _board_init_r_ofs         //r0=flash上的board_init_r()函数地址偏移值
           adr  r1, _start                    //0
           add lr, r0, r1                     //返回地址lr=flash上的board_init_r()函数
           add lr, lr, r9                     //加上重定位偏移值(r9)后,lr=SDRAM上的board_init_r()函数
    
           /* setup parameters for board_init_r */
           mov r0, r5             /* gd_t */              //r0=id值
           mov r1, r6             /* dest_addr */         //r1=uboot重定位地址
           /* jump to it ... */
           mov pc, lr              //跳转:  board_init_r()函数
    
    _board_init_r_ofs:
           .word board_init_r - _start        //获取在flash上的board_init_r()函数地址偏移值
    
    #endif

      从上面代码看出, 接下来便会进入uboot的board_init_r()函数,该函数会对各个外设初始化、环境变量初始化等.

      uboot的启动过程到此便结束了.

    uboot视频资料:

    Uboot启劢流程分析

    http://www.makeru.com.cn/live/1392_1107.html?s=45051

     

    转自知乎:https://zhuanlan.zhihu.com/p/65853967

    转载于:https://www.cnblogs.com/QianD/p/10870439.html

    展开全文
  • UBoot启动流程

    2019-07-17 11:51:00
    1. UBoot启动流程可以分为两个阶段: (1)第一阶段 ① 硬件设备初始化 ② 加载UBoot第二阶段代码到RAM空间 ③ 设置好栈 ④ 跳转到第二阶段代码入口 (2)第二阶段 ① 初始化本阶段使用的硬件设备 ② 检测...

    1. UBoot启动流程可以分为两个阶段:

    (1)第一阶段

    ① 硬件设备初始化

    ② 加载UBoot第二阶段代码到RAM空间

    ③ 设置好栈

    ④ 跳转到第二阶段代码入口

    (2)第二阶段

    ① 初始化本阶段使用的硬件设备

    ② 检测系统内存映射

    ③ 将内核从Flash读取到RAM中

    ④ 为内核设置启动参数

    ⑤ 调用内核

     

    2. UBoot启动第一阶段

    根据链接器脚本cpu/arm920t/u-boot.lds中指定的链接方式,可以看出,u-boot代码段的第一个链接的是cpu/arm920t/start.o,入口标号是_start,因此u-boot的入口代码在对应源文件cpu/arm920t/start.S中

    (1)设置异常向量表:

    .globl _start
    _start:    b    start_code
        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
    
    _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
    
        .balignl 16,0xdeadbeef

    (2)CPU进入SVC模式

        /*
         * set the cpu to SVC32 mode
         */
        mrs    r0, cpsr
        bic    r0, r0, #0x1f
        orr    r0, r0, #0xd3
        msr    cpsr, r0

    (3)关闭MMU和Cache

    /*
         * flush v4 I/D caches
         */
        mov    r0, #0
        mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
        mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
    
        /*
         * disable MMU stuff and caches
         */
        mrc    p15, 0, r0, c1, c0, 0
        bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
        bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
        orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
        orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
        mcr    p15, 0, r0, c1, c0, 0

    (4)关闭看门狗

        /* 
         *turn off the watchdog 
         */
    #define pWTCON    0x53000000
    #define INTMSK    0x4A000008    /* Interupt-Controller base addresses */
    #define INTSUBMSK    0x4A00001C
        ldr    r0, =pWTCON
        mov    r1, #0x0
        str    r1, [r0]

    (5)屏蔽中断

        /*
         * mask all IRQs by setting all bits in the INTMR - default
         */
        mov    r1, #0xffffffff
        ldr    r0, =INTMSK
        str    r1, [r0]
        
        ldr    r1, =0x7fff
        ldr    r0, =INTSUBMSK
        str    r1, [r0]

    (6)设置MPLLCON、UPLLCON、CLKDIVN

    #define CLKDIVN            0x4C000014        /* Clock divisor register */
    #define CLK_CTL_BASE     0x4C000000
    #define MDIV_405         (0x7f << 12)    /* Default FCLK is 405 MHz! */
    #define PSDIV_405         0x21
    #define MDIV MDIV_405
    #define PSDIV PSDIV_405
    #define CLKDIV             0x05            /* FCLK:HCLK:PCLK = 1:4:8 */
        
        ldr    r0, =CLKDIVN
        mov    r1, #CLKDIV
        str    r1, [r0]
    
        /* Set arm920t to Asynchronous Clock Mode (405 MHz)*/
        mrc p15, 0, r1, c1, c0, 0
        orr r1, r1, #0xc0000000
        mcr p15, 0, r1, c1, c0, 0
        
        mov r1, #CLK_CTL_BASE
        mov r2, #MDIV
        add r2, r2, #PSDIV
        str r2, [r1, #0x04]        /* MPLLCON */

    (7)Nand初始化(Nand启动)

    ldr r0, =S3C2440_NAND_BASE
        ldr r1, =0x001210
        str r1, [r0, #NFCONF_OFFSET]
        
        mov r1, #0x03
        str r1, [r0, #NFCONT_OFFSET]
        
        mov pc, lr

    (8)存储控制器初始化(Memeory)

    /* memory control configuration */
        /* make r0 relative the current location so that it */
        /* reads SMRDATA out of FLASH rather than memory ! */
        ldr     r0, =SMRDATA
        ldr    r1, _TEXT_BASE
        sub    r0, r0, r1
        ldr    r1, =BWSCON    /* Bus Width Status Controller */
        add     r2, r0, #13*4
    0:
        ldr     r3, [r0], #4
        str     r3, [r1], #4
        cmp     r2, r0
        bne     0b
    
        mov    pc, lr
    
        .ltorg
    /* the literal pools origin */
    
    SMRDATA:
        .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
        .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
        .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
        .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
        .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
        .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
        .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
        .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
        .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
        .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
        .word 0x32
        .word 0x30
        .word 0x30

    (9)复制u-boot第二阶段的代码到RAM

    relocate:                /* relocate U-Boot to RAM        */
        adr    r0, _start        /* r0 <- current position of code   */
        ldr    r1, _TEXT_BASE        /* test if we run from flash or RAM */
        cmp    r0, r1            /* don't reloc during debug         */
        beq    stack_setup
        
        mov r2, #0
        str r2, [r2]
        ldr r2, [r2]
        cmp r2, #0
        bne copy_to_ram_from_nor
    
        mov sp, #0x1000
        bl copy_to_ram_from_nand
        b stack_setup
        
    copy_to_ram_from_nor:    
        ldr    r2, _armboot_start
        ldr    r3, _bss_start
        sub    r2, r3, r2        /* r2 <- size of armboot            */
        add    r2, r0, r2        /* r2 <- source end address         */
    
    copy_loop:
        ldmia    r0!, {r3-r10}        /* copy from source address [r0]    */
        stmia    r1!, {r3-r10}        /* copy to   target address [r1]    */
        cmp    r0, r2            /* until source end addreee [r2]    */
        ble    copy_loop

    (10)设置栈

    stack_setup:
        ldr    r0, _TEXT_BASE        /* upper 128 KiB: relocated uboot   */
        sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
        sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */

    (11)清除BSS段

    clear_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

    (12)跳转到第二阶段代码入口

    ldr    pc, _start_armboot

    (13)UBoot内存分配图

     

    3. UBoot启动第二阶段

    (1)gd_t结构体:存储全局数据区的数据

    typedef    struct    global_data {
        bd_t        *bd;
        unsigned long    flags;
        unsigned long    baudrate;
        unsigned long    have_console;    /* serial_init() was called */
        unsigned long    env_addr;    /* Address  of Environment struct */
        unsigned long    env_valid;    /* Checksum of Environment valid? */
        unsigned long    fb_base;    /* base address of frame buffer */
    #ifdef CONFIG_VFD
        unsigned char    vfd_type;    /* display type */
    #endif
    #ifdef CONFIG_FSL_ESDHC
        unsigned long    sdhc_clk;
    #endif
    #if 0
        unsigned long    cpu_clk;    /* CPU clock in Hz!        */
        unsigned long    bus_clk;
        phys_size_t    ram_size;    /* RAM size */
        unsigned long    reset_status;    /* reset status register at boot */
    #endif
        void        **jt;        /* jump table */
    } gd_t;

    ① u-boot使用了一个存储在寄存器中的指针gd来记录全局数据区的地址(指针存放在寄存器r8中)

    #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

    ② 根据u-boot内存分布图,可以计算gd的值

    gd = TEXT_BASE - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t)

    与start_armboot()函数中的计算方法一致

    gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));

    (2)bd_t结构:存放板级相关的全局数据

    typedef struct bd_info {
        int            bi_baudrate;    /* serial console baudrate */
        unsigned long    bi_ip_addr;    /* IP Address */
        struct environment_s           *bi_env;
        ulong            bi_arch_number;    /* unique id for this board */
        ulong            bi_boot_params;    /* where this board expects params */
        struct                /* RAM configuration */
        {
        ulong start;
        ulong size;
        }            bi_dram[CONFIG_NR_DRAM_BANKS];
    } bd_t;

    (3)init_sequence数组

    ① u-boot使用一个数组init_sequence来存储大多数开发板都要执行的初始化函数的函数指针

    init_fnc_t *init_sequence[] = {
    
        board_init,        /* basic board dependent setup */
    
        timer_init,        /* initialize timer */
        env_init,        /* initialize environment */
        init_baudrate,        /* initialze baudrate settings */
        serial_init,        /* serial communications setup */
        console_init_f,        /* stage 1 init of console */
        display_banner,        /* say that we are here */
    
        dram_init,        /* configure available RAM banks */
    
        display_dram_config,
        NULL,
    };

    ② board_init函数配置了MPLLCON、UPLLCON和部分GPIO寄存器的值,还设置了u-boot的机器码和内核启动参数地址

    gd->bd->bi_arch_number = MACH_TYPE_MINI2440 ;
    gd->bd->bi_boot_params = 0x30000100;

    ③ dram_init函数

    int dram_init (void)
    {
        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
        gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
    
        return 0;
    }

    (4)start_armboot()顺序分析

    void start_armboot (void)
    {
        init_fnc_t **init_fnc_ptr;
        char *s;
        ...
        /* Pointer is writable since we allocated a register for it */
        gd = (gd_t*)(_armboot_start - CONFIG_SYS_MALLOC_LEN - sizeof(gd_t));
        /* compiler optimization barrier needed for GCC >= 3.4 */
        __asm__ __volatile__("": : :"memory");
    
        memset ((void*)gd, 0, sizeof (gd_t));
        gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));
        memset (gd->bd, 0, sizeof (bd_t));
    
        gd->flags |= GD_FLG_RELOC;
    
        monitor_flash_len = _bss_start - _armboot_start;
    
        for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
            if ((*init_fnc_ptr)() != 0) {
                hang ();
            }
        }
    
        /* armboot_start is defined in the board-specific linker script */
        mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,
                CONFIG_SYS_MALLOC_LEN);
    
    #ifndef CONFIG_SYS_NO_FLASH
        /* configure available FLASH banks */
        display_flash_config (flash_init ());
    #endif /* CONFIG_SYS_NO_FLASH */
        ...
    #if defined(CONFIG_CMD_NAND)
        puts ("NAND:  ");
        nand_init();        /* go init the NAND */
    #endif
        ...
        /* initialize environment */
        env_relocate ();
        ...
        /* IP Address */
        gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");
    
        stdio_init ();    /* get the devices list going. */
    
        jumptable_init ();
        ...
        console_init_r ();    /* fully init console as a device */
        ...
        /* enable exceptions */
        enable_interrupts ();
        ...
    #if defined(CONFIG_CMD_NET)
    #if defined(CONFIG_NET_MULTI)
        puts ("Net:   ");
    #endif
        eth_initialize(gd->bd);
    #if defined(CONFIG_RESET_PHY_R)
        debug ("Reset Ethernet PHY\n");
        reset_phy();
    #endif
    #endif
        ...
        /* main_loop() can return to retry autoboot, if so just run it again. */
        for (;;) {
            main_loop ();
        }
    
        /* NOTREACHED - no way out of command loop except booting */
    }

    (5)main_loop函数分析

    ① 设置启动次数有关参数

    ② 启动Modem功能

    ③ 设置版本号、初始化命令自动完成功能

    ④ 启动延时和启动菜单

    ⑤ 执行命令循环

     

    转载于:https://www.cnblogs.com/wulei0630/p/10635669.html

    展开全文
  • 对于学习嵌入式的伙伴对于uboot都不陌生,今天我们就来了解一些关于uboot启动流程的一些相关知识,老样子本文结尾会有uboot启动流程的视频资料。 uboot启动流程如下: 1)设置CPU为管理模式 2)关看门狗 3)关中断 ...

    7466734aec81819d91894f11c8b2d936.png

    对于学习嵌入式的伙伴对于uboot都不陌生,今天我们就来了解一些关于uboot启动流程的一些相关知识,老样子本文结尾会有uboot启动流程的视频资料。

      uboot启动流程如下:

      1)设置CPU为管理模式

      2)关看门狗

      3)关中断

      4)设置时钟频率

      5)关mmu,初始化各个bank

      6)进入board_init_f()函数 (初始化定时器,GPIO,串口等,划分内存区域)

      7)重定位 复制uboot,然后修改SDRAM上的uboot链接地址)

      8)清bss

      9)跳转到board_init_r()函数,启动流程结束

    -----------------------------------------------------------------------------------------------

      1.首先来安装arm-linux-gcc-4.3.2交叉编译器

    mkdir  arm-linux-gcc-4.3.2                 //创建目录
    
    tar -xjf  arm-linux-gcc-4.3.2.tar.bz2 -C arm-linux-gcc-4.3.2/  //解压到arm-linux-gcc-4.3.2目录下

      然后添加环境变量:

      有两种方法,第一种只是临时修改,重启虚拟机便会复位:

    export PATH=/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin:/usr/sbin:/usr/bin... ...
                 //将arm-linux-gcc-4.3.2添加到环境变量

      第二种,重启不复位:

    vi /etc/environment
    添加:
    PATH=/arm-linux-gcc-4.3.2/usr/local/arm/4.3.2/bin:/usr/sbin:/usr/bin... ...
                       //将arm-linux-gcc-4.3.2添加到环境变量

      2.然后进入ftp://ftp.denx.de/pub/u-boot/来下载u-boot-2012.04.01

      2.1.创建source insight工程,来看代码

      1)在board 目录下只添加:

    board/samsung/smdk2410/               // (2410单板文件)

      2)在arch 目录下只添加:

    arch/arm/cpu/arm920t/                //(只添加这个目录下的*.c,*.S公用文件)                
    
    arch/arm/cpu/arm920t/s3c24x0/        //(24x0架构所有文件)
    
    arch/arm/include/asm/                //(只添加这个目录下的*.h公用头文件)
    
    arch/arm/include/asm/proc-armv/      //(arm架构的文件)
    
    arch/arm/include/asm/arch-s3c24x0/   //(24x0架构头文件)
    
    arch/arm/lib/                        //(与arm相关的库文件)

      3)在include/configs目录下只添加:

    include/configs/smdk2410.h              // (用来配置2410单板的头文件)

      2.2编译烧写:

    tar xjf u-boot-2012.04.01.tar.bz2
    
    cd u-boot-2012.04.01                 //进入解压后文件目录
    
    make smdk2410_config                 //由于该uboot不支持2440板卡,所以只有配置2410板卡
    
    make                                 //编译,生成u-boot.bin 

      3.最后烧写u-boot.bin,发现无法启动,接下来便来分析uboot的启动流程

      4.首先查看arch/arm/cpu/u-boot.lds链接脚本

      如下图所示,看到uboot最开始会进入_start:

    f6c3a768fdf389684b2303db989f7f48.png

      5. _start位于arch/arm/cpu/arm920t/start.S

      所以,我们从start.S开始分析uboot启动流程:

    .globl _start                                //声明_start全局符号,这个符号会被lds链接脚本用到
    _start:    
    b     start_code                            //跳转到start_code符号处,0x00
           ldr   pc, _undefined_instruction                    //0x04
           ldr   pc, _software_interrupt                       //0x08
           ldr   pc, _prefetch_abort                           //0x0c
           ldr   pc, _data_abort                               //0x10
           ldr   pc, _not_used                                 //0x14
           ldr   pc, _irq                                      //0x18
           ldr   pc, _fiq                                      //0x20
    
    _undefined_instruction:  .word undefined_instruction
               //定义_undefined_instruction指向undefined_instruction(32位地址)
    
    _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
    
       .balignl 16,0xdeadbeef        //balignl使用,参考http://www.cnblogs.com/lifexy/p/7171507.html

      其中符号保存的地址都在顶层目录/system.map中列出来了

      6. 从上面看到, _start会跳转到start_code处

    start_code:
    
        /*设置CPSR寄存器,让CPU进入管理模式*/
           mrs  r0, cpsr                 //读出cpsr的值
           bic   r0, r0, #0x1f           //清位
           orr   r0, r0, #0xd3          //位或
           msr  cpsr, r0                 //写入cpsr
    
    #if   defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
           /*
            * relocate exception table
            */
           ldr   r0, =_start            
           ldr   r1, =0x0                //r1等于异常向量基地址
           mov r2, #16
    copyex:
           subs       r2, r2, #1           //减16次,s表示每次减都要更新条件标志位
           ldr   r3, [r0], #4       
           str   r3, [r1], #4      //将_start标号后的16个符号存到异常向量基地址0x0~0x3c处
           bne  copyex             //直到r2减为0
    #endif
    
    #ifdef CONFIG_S3C24X0
    
           /* 关看门狗*/
    #  define pWTCON       0x53000000
    #  define INTMSK 0x4A000008    /* Interrupt-Controller base addresses */
    #  define INTSUBMSK  0x4A00001C
    #  define CLKDIVN       0x4C000014    /* clock divisor register */
    
           ldr   r0, =pWTCON       
           mov r1, #0x0        
           str   r1, [r0]           //关看门狗,使WTCON寄存器=0
    
           /*关中断*/
           mov r1, #0xffffffff
           ldr   r0, =INTMSK
           str   r1, [r0]                  //关闭所有中断
    # if defined(CONFIG_S3C2410)
           ldr   r1, =0x3ff
           ldr   r0, =INTSUBMSK
           str   r1, [r0]                  //关闭次级所有中断
    # endif
    
        /* 设置时钟频率, FCLK:HCLK:PCLK = 1:2:4 ,而FCLK默认为120Mhz*/
           ldr   r0, =CLKDIVN
           mov r1, #3
           str   r1, [r0]
    
     #ifndef CONFIG_SKIP_LOWLEVEL_INIT
           bl    cpu_init_crit                         //关闭mmu,并初始化各个bank
    
    #endif
    
    call_board_init_f:
           ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR) //CONFIG_SYS_INIT_SP_ADDR=0x30000f80
           bic   sp, sp, #7         //sp=0x30000f80
           ldr   r0,=0x00000000
           bl    board_init_f   

      上面的CONFIG_SYS_INIT_SP_ADDR =0x30000f80,是通过arm-linux-objdump -D u-boot>u-boot.dis生成反汇编,然后从u-boot.dis得到的,如下图所示:

    8a8e9a5d74b0e6fc581fef055c1b7b4a.png

      7.然后进入第一个C函数:board_init_f()

      该函数主要工作是:

      清空gd指向的结构体、通过init_sequence函数数组,来初始化各个函数以及逐步填充gd结构体,最后划分内存区域,将数据保存在gd里,然后调用relocate_code()对uboot重定位

      (gd是用来传递给内核的参数)

      1)具体代码如下所示:

    void board_init_f(ulong bootflag) // bootflag=0x00000000
    {
           bd_t *bd;
           init_fnc_t **init_fnc_ptr;         //函数指针
           gd_t *id;
           ulong addr, addr_sp;
    #ifdef CONFIG_PRAM
           ulong reg;
    #endif
    
           bootstage_mark_name(BOOTSTAGE_ID_START_UBOOT_F, "board_init_f");
           /* Pointer is writable since we allocated a register for it */
           gd = (gd_t *) ((CONFIG_SYS_INIT_SP_ADDR) & ~0x07);

      其中gd是一个全局变量,用来传递给内核的参数用的,如下图所示,在arch/arn/include/asm/global_data.h中定义,*gd指向r8寄存器,所以r8专门提供给gd使用

    3b8c93036028c1205e8bf5e55a79264b.png

      而CONFIG_SYS_INIT_SP_ADDR,在6节里得到=0x30000f80,所以gd=0x30000f80

      2)继续来看board_init_f():

          __asm__ __volatile__("": : :"memory");           //memory:让cpu重新读取内存的数据
    
          memset((void *)gd, 0, sizeof(gd_t));        //将0x30000f80地址上的gd_t结构体清0
    
          gd->mon_len = _bss_end_ofs;  
             // _bss_end_ofs =__bss_end__ - _start,在反汇编找到等于0xae4e0,所以mon_len等于uboot的数据长度
          gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, (uintptr_t)gd->fdt_blob);
    
           for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr)
                //调用init_sequence[]数组里的各个函数
          {
                  if ((*init_fnc_ptr)() != 0)     //执行函数,若函数执行出错,则进入hang()
                 {               hang ();   //打印错误信息,然后一直while
                 }
    
           }

      上面的init_sequence[]数组里存了各个函数,比如有:

      board_early_init_f():设置系统时钟,设置各个GPIO引脚

      timer_init():初始化定时器

      env_init():设置gd的成员变量

      init_baudrate():设置波特率

      dram_init():设置gd->ram_size= 0x04000000(64MB)

      3)继续来看board_init_f():

    addr = CONFIG_SYS_SDRAM_BASE + gd->ram_size;  // addr=0x34000000 
    // CONFIG_SYS_SDRAM_BASE:  SDRAM基地址,为0X30000000
    // gd->ram_size:          等于0x04000000 
    
    
    #if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
           /* reserve TLB table */
           addr -= (4096 * 4);        //addr=33FFC000
    
           addr &= ~(0x10000 - 1);  // addr=33FF0000,   
    
           gd->tlb_addr = addr;   //将64kB分配给TLB,所以TLB地址为33FF0000~33FFFFFF
    #endif
    
           /* round down to next 4 kB limit */
           addr &= ~(4096 - 1);                    //4kb对齐, addr=33FF0000
           debug("Top of RAM usable for U-Boot at: %08lxn", addr);
           /*
            * reserve memory for U-Boot code, data & bss
            * round down to next 4 kB limit
            */
           addr -= gd->mon_len; // 在前面分析过gd->mon_len=0xae4e0,
                               //所以addr=33FF0000 -0xae4e0=33F41B20,
    
           addr &= ~(4096 - 1);  //4095=0xfff,4kb对齐, addr=33F41000
                                 //所以分配给uboot各个段的重定位地址为33F41000~33FFFFFF
           debug("Reserving %ldk for U-Boot at: %08lxn", gd->mon_len >> 10, addr);
    
    #ifndef CONFIG_SPL_BUILD
           addr_sp = addr - TOTAL_MALLOC_LEN; //分配一段malloc空间给addr_sp
                           //TOTAL_MALLOC_LEN=1024*1024*4,所以malloc空间为33BF1000~33F40FFF
    
           addr_sp -= sizeof (bd_t);            //分配一段bd_t结构体大的空间
        bd = (bd_t *) addr_sp;               //bd指向刚刚分配出来的bd_t结构体
        gd->bd = bd;                         // 0x30000f80处的gd变量的成员bd等于bd_t基地址
    
        addr_sp -= sizeof (gd_t);              //分配一个gd_t结构体大的空间
        id = (gd_t *) addr_sp;                 //id指向刚刚分配的gd_t结构体
        gd->irq_sp = addr_sp;                 //0x30000f80处的gd变量的成员irq_sp等于gd_t基地址
        addr_sp -= 12;
        addr_sp &= ~0x07;
        ... ...
    
        relocate_code(addr_sp, id, addr);  //进入relocate_code()函数,重定位代码,以及各个符号
        // addr_sp: 栈顶,该栈顶向上的位置用来存放gd->irq_sp、id 、gd->bd、malloc、uboot、TLB(64kb),
        //id:       存放 gd_t结构体的首地址
        // addr:    等于存放uboot重定位地址33F41000
    }

      执行完board_init_f()后,最终内存会划分如下图所示:

    bc2d4a9f08240324ee858b28eb31ae2c.png

      其实此时uboot还在flash中运行,然后会进入start.S的relocate_code()里进行uboot重定位

      8.接下来进入重定位

      1)start.S的relocate_code()代码如下所示

    relocate_code:
           mov r4, r0      /* save addr_sp */              // addr_sp栈顶值
           mov r5, r1      /* save addr of gd */           // id值
           mov r6, r2      /* save addr of destination */  // addr值:uboot重定位地址
    
           /* Set up the stack        */
    stack_setup:
           mov sp, r4                //设置栈addr_sp
           adr  r0, _start           //在顶层目录下system.map符号文件中找到_start =0,所以r0=0
           cmp r0, r6                //判断_start(uboot重定位之前的地址)和addr(重定位地址)是否一样
           beq clear_bss             /* skip relocation */ 
           mov r1, r6             /* r1 <- scratch for copy_loop */ //r1= addr(重定位地址)
           ldr   r3, _bss_start_ofs               //_bss_start_ofs=__bss_start - _start(uboot代码大小)
           add r2, r0, r3         /* r2 <- source end address*/   //r2= uboot重定位之前的结束地址
    
    copy_loop:
           ldmia      r0!, {r9-r10}  /* copy from source address [r0] */
                                  //将r0处的两个32位数据拷到r9-r10中,然后r0+=8
    
           stmia      r1!, {r9-r10}  /* copy to   target address [r1]*/
                                 //将拷出来的两个数据放入r1(重定位地址)处,然后r1+=8
    
           cmp r0, r2  /* until source end address [r2]*/   //判断拷贝的数据是否到结束地址
           blo  copy_loop

      上面只是把代码复制到SDRAM上,而链接地址内容却没有改变,比如异常向量0x04的代码内容还是0x1e0,

      我们以异常向量0x04为例,来看它的反汇编:

    2ef413436e77a255fed9c589cd019580.png

      如上图所示,即使uboot在SDRAM运行,由于代码没修改,PC也会跳到0x1e0(flash地址)上

      和之前老的uboot有很大区别,以前老的uboot直接是使用的SDRAM链接地址,如下图所示:

    4a65ea7258716b9c8fe58e025f0dee8a.png

      所以,新的uboot采用了动态链接地址的方法,在链接脚本uboot.lds中,可以看到这两个段(.rel.dyn、.dynsym):

    b71114cdbab4ff09cd4af70f19925a90.png

      该两个段里,便是保存了各个文件的相对动态信息(.rel.dyn)、动态链接地址的符号(.dynsym)

      以上图的.rel.dyn段为例来分析,找到__rel_dyn_start符号处:

    c8bb1d004dfbc8279fe7d2cd57ca1351.png

      如上图所示,其中0x17表示的是符号的结束标志位,我们以0x20为例来讲解:

      在之前,我们讲过0x20里面保存的是异常向量0x04跳转的地址(0x1e0),如下图所示:

    e6be0c4acb4fdd583101efbdf929d171.png

      所以,接下来的代码,便会根据0x20里的值0x1e0(flash地址),将SDRAM的33F41000+0x20的内容改为33F41000+0x1e0(SDRAM地址),来改变uboot的链接地址

      2)重定位的剩余代码,如下所示:

    #ifndef CONFIG_SPL_BUILD
           /*
            * fix .rel.dyn relocations
            */
           ldr   r0, _TEXT_BASE             /* r0 <- Text base */  //r0=text段基地址=0
           sub  r9, r6, r0         /* r9 <- relocation offset */   //r9= 重定位后的偏移值=33F41000
           ldr   r10, _dynsym_start_ofs  /* r10 <- sym table ofs */ 
                                              //_dynsym_start_ofs =__dynsym_start - _start=0x73608
                                              //所以r10=动态符号表的起始偏移值=0x73608
    
           add r10, r10, r0            /* r10 <- sym table in FLASH */
                                           //r10=flash上的动态符号表基地址=0x73608
    
           ldr   r2, _rel_dyn_start_ofs     /* r2 <- rel dyn start ofs */
                                              //r2=__rel_dyn_start - _start=0x6b568
                                              //所以r2=相对动态信息的起始偏移值=0x6b568
    
           add r2, r2, r0         /* r2 <- rel dyn start in FLASH */
                                          //r2=flash上的相对动态信息基地址=0x6b568
    
           ldr   r3, _rel_dyn_end_ofs      /* r3 <- rel dyn end ofs */
                                              // _rel_dyn_end_ofs=__rel_dyn_end - _start=00073608
                                              //所以r3=相对动态信息的结束偏移值=00073608
           add r3, r3, r0         /* r3 <- rel dyn end in FLASH */
                                        //r3=flash上的相对动态信息结束地址=0x6b568
    fixloop:
           ldr   r0, [r2]           /* r0 <- location to fix up, IN FLASH! */
                                   //以0x20为例,r0=0x6b568地址处的内容= 0x20
    
           add r0, r0, r9         /* r0 <- location to fix up in RAM */
                                         //r0=33F41000+0x20=33F41020
    
           ldr   r1, [r2, #4]             //r1= 33F41024地址处的内容=0x17
           and  r7, r1, #0xff       
           cmp r7, #23                  /* relative fixup? */  //0x17=23,所以相等
           beq fixrel                                       //跳到:fixerl
    
           cmp r7, #2                    /* absolute fixup? */
           beq fixabs
           /* ignore unknown type of fixup */
           b     fixnext
    fixabs:
           /* absolute fix: set location to (offset) symbol value */
           mov r1, r1, LSR #4         /* r1 <- symbol index in .dynsym */
           add r1, r10, r1              /* r1 <- address of symbol in table */
           ldr   r1, [r1, #4]             /* r1 <- symbol value */
           add r1, r1, r9         /* r1 <- relocated sym addr */
           b     fixnext
    
    fixrel:
           /* relative fix: increase location by offset */
           ldr   r1, [r0]                  //r1=33F41020地址处的内容=0x1e0
           add r1, r1, r9                //r1=0x1e0+33F41000= 33F411e0
    
    fixnext:
           str   r1, [r0]             //改变链接地址里的内容, 33F41020=33F411e0  (之前为0x1e0)   
           add r2, r2, #8             //r2等于下一个相对动态信息(0x24)的地址
           cmp r2, r3                //若没到尾部__rel_dyn_end,便继续执行: fixloop
           blo  fixloop                 
    #endif

      9.清除bss段

    /*重定位完成后,清除bss段*/
    clear_bss:
     #ifndef CONFIG_SPL_BUILD
           ldr   r0, _bss_start_ofs                        //获取flash上的bss段起始位置
           ldr   r1, _bss_end_ofs                          //获取flash上的bss段结束位置
           mov r4, r6                    /* reloc addr */     //获取r6(SDRAM上的uboot基地址)
           add r0, r0, r4                                  //加上重定位偏移值,得到SDRAM上的bss段起始位置
           add r1, r1, r4                                     //得到SDRAM上的bss段结束位置
           mov r2, #0x00000000           /* clear*/
    
    clbss_l:
        str    r2, [r0]           /* clear loop...       */                 //开始清除SDRAM上的bss段
           add r0, r0, #4
           cmp r0, r1
           bne  clbss_l
           bl coloured_LED_init
           bl red_led_on
    #endif

      9.1继续往下分析

    #ifdef CONFIG_NAND_SPL                   //未定义,所以不执行
      ... ...                          
    #else                                   //执行else
    
           ldr   r0, _board_init_r_ofs         //r0=flash上的board_init_r()函数地址偏移值
           adr  r1, _start                    //0
           add lr, r0, r1                     //返回地址lr=flash上的board_init_r()函数
           add lr, lr, r9                     //加上重定位偏移值(r9)后,lr=SDRAM上的board_init_r()函数
    
           /* setup parameters for board_init_r */
           mov r0, r5             /* gd_t */              //r0=id值
           mov r1, r6             /* dest_addr */         //r1=uboot重定位地址
           /* jump to it ... */
           mov pc, lr              //跳转:  board_init_r()函数
    
    _board_init_r_ofs:
           .word board_init_r - _start        //获取在flash上的board_init_r()函数地址偏移值
    
    #endif

      从上面代码看出, 接下来便会进入uboot的board_init_r()函数,该函数会对各个外设初始化、环境变量初始化等.

      uboot的启动过程到此便结束了.

    uboot视频资料:

    Uboot启劢流程分析

    展开全文
  • 1、前言Linux系统的启动需要一个bootloader程序,该bootloader程序会先初始化DDR等外设,然后将Linux内核从Flash中拷贝到DDR中,最后启动...接下来,将会进行简单的uboot启动流程分析,uboot的源码为uboot-imx-rel_i...
  • Uboot启动流程

    2012-04-02 20:50:58
    U-boot(universal bootloader)是德国DENX小组开发的用于多嵌入式CPU的bootloader程序,遵循GPL条款。  以s3c2410为例Uboot的启动过程大体可分为两个部分,第一部分是初始化系统为第二... 下面是uboot启动流程
  • uboot 启动流程

    2018-02-23 14:41:56
    经过了上一篇的配置,我们已经执行make就可以编译出一个uboot.bin,但这还不够,首先,此时的uboot并不符合三星芯片对bootloader的格式要求,同时,此时的...在三星的SoC中, 启动流程可以分为三个阶段BL0, BL1, BL2...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,362
精华内容 544
关键字:

uboot启动流程