lowlevel.init函数分析

原创 2018年04月15日 15:33:22

/*

 *Memory Setup stuff - taken from blob memsetup.S

 *

 *Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and

 *                     Jan-Derk Bakker(J.D.Bakker@its.tudelft.nl)

 *

 *Modified for the Samsung SMDK2410 by

 *(C) Copyright 2002

 *David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>

 *

 *See file CREDITS for list of people who contributed to this

 *project.

 *

 *This program is free software; you can redistribute it and/or

 *modify it under the terms of the GNU General Public License as

 *published by the Free Software Foundation; either version 2 of

 *the License, or (at your option) any later version.

 *

 *This program is distributed in the hope that it will be useful,

 *but WITHOUT ANY WARRANTY; without even the implied warranty of

 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

 *GNU General Public License for more details.

 *

 *You should have received a copy of the GNU General Public License

 *along with this program; if not, write to the Free Software

 *Foundation, Inc., 59 Temple Place, Suite 330, Boston,

 * MA02111-1307 USA

 */

//lowlevel_init.S总共所做的事:检查复位状态,IO恢复,观看门狗,开发板锁存,时钟初始化,DDR初始化,串口初始化并打印“O”,TZPC初始化,打印“K”

//其中值得关注的是:关看门狗,开发板供电锁存,时钟初始化,DDR初始化,打印“ok”

 

#include <config.h>

#include <version.h>

 

#include <s5pc110.h>

#include "smdkc110_val.h"

 

_TEXT_BASE:

   .word    TEXT_BASE

 

   .globl lowlevel_init

lowlevel_init:

   push    {lr}      //先将lr压栈保存

 

   /* check reset status  */    //检测复位状态:现在复杂cpu有多种复位状态(冷上电,热启动,低功耗唤醒等。。。。。),所以先判断

   //哪种情况复位,意义:冷上电时ddr需要初始化才能用,热启动或者低功耗复位,则不需要再次初始化ddr

   ldr    r0,=(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)

   ldr    r1, [r0]

   bic    r1, r1, #0xfff6ffff

   cmp    r1, #0x10000

   beq    wakeup_reset_pre

   cmp    r1, #0x80000

   beq    wakeup_reset_from_didle

 

   /* IO Retention release */    //IO复位(这部分跟复位的部分代码跟主线无关,可以不看)

   ldr    r0,=(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)

   ldr    r1, [r0]

   ldr    r2, =IO_RET_REL

   orr    r1, r1, r2

   str    r1, [r0]

 

   /* Disable Watchdog */    //观看门狗、为什么要关看门狗?怎么关?

   ldr    r0,=ELFIN_WATCHDOG_BASE    /* 0xE2700000 */

   mov    r1, #0

   str    r1, [r0]

 

   /* SRAM(2MB) init for SMDKC110 */

   /* GPJ1 SROM_ADDR_16to21 */                 //这部分也与主线无关

   ldr    r0, =ELFIN_GPIO_BASE

 

   ldr    r1, [r0, #GPJ1CON_OFFSET]

   bic    r1, r1, #0xFFFFFF

   ldr    r2, =0x444444

   orr    r1, r1, r2

   str    r1, [r0, #GPJ1CON_OFFSET]

 

   ldr    r1, [r0, #GPJ1PUD_OFFSET]

   ldr    r2, =0x3ff

   bic    r1, r1, r2

   str    r1, [r0, #GPJ1PUD_OFFSET]

 

   /* GPJ4 SROM_ADDR_16to21 */

   ldr    r1, [r0, #GPJ4CON_OFFSET]

   bic    r1, r1, #(0xf<<16)

   ldr    r2, =(0x4<<16)

   orr    r1, r1, r2

   str    r1, [r0, #GPJ4CON_OFFSET]

 

   ldr    r1, [r0, #GPJ4PUD_OFFSET]

   ldr    r2, =(0x3<<8)

   bic    r1, r1, r2

   str    r1, [r0, #GPJ4PUD_OFFSET]

 

   /* CS0 - 16bit sram, enable nBE, Byte base address */

   ldr    r0, =ELFIN_SROM_BASE    /* 0xE8000000 */    //非法立即数,分两部分写

   mov    r1, #0x1

   str    r1, [r0]

 

   /* PS_HOLD pin(GPH0_0) set to high */    //开发板供电锁存,怎么实现?

   ldr    r0,=(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)

   ldr    r1, [r0]

   orr    r1, r1, #0x300

   orr    r1, r1, #0x1

   str    r1, [r0]

 

   /* when we already run in ram, we don't need to relocate U-Boot.

     * and actually, memory controller must beconfigured before U-Boot

    * is running in ram.

    *///以下几行比较重要 : 代码的作用,就是判定当前代码执行的位置在sram中还是ddr中:为什么要判断:原因:

   ldr    r0, =0xff000fff           //BL1(uboot的前一部分)在sram ,ddr都有存在,因此,如果是冷启动,那么当前代码应该在sram

    bic    r1, pc, r0        /* r0 <- current base addr of code*/  //中运行的BL1,如果是低功耗状态的复位这时候应该在ddr中运行(低功耗启动,证明之前有启动成功过,那么ddr就已经初始化过,所以再次搞就应该在ddr)

   ldr    r2, _TEXT_BASE        /* r1 <- original base addr in ram*///原因2:我们判断当前代码的运行地址是有用的,可以指导后面的代码运行,

   bic    r2, r2, r0        /* r0 <- current base addr of code*///譬如在lowlevel_init.S中判断当前代码的运行地址,就是为了确定要不要执行

   cmp     r1, r2   //r1,r2相等,说明在ddr,不等在sram  /* compare r0, r1                  *///时钟初始化和初始化ddr的代码,如果当前代码是在sram中,说明冷启动,那么时钟

   beq     1f            /* r0 == r1 then skip sdram init   *///和ddr都需要初始化,如果在ddr中,那么说明热启动,则时钟和ddr都不用再次初始化

//beq    1f    意思是:如果r1,r2相等就跳转,找1标号,f表示向后找,就是往后找1(下面有个1,所以相等时就不初始化时钟跟ddr),1b就是往前找1,然后执行1处的代码

//判定代码执行的位置的技术:1:比对链接地址和运行地址,(运行地址我们不知道的,链接是我们指定的)(裸机重定位时的做法)

//   bic    r1, pc, r0    这句代码意思:将pc的值中的某些bit位清零,剩下一些特殊的bit位赋值给r1(就是r0中为1的那些位清零)

//相等于:r1=pc & ~(ff000fff).   ldr    r2, _TEXT_BASE    加载链接地址到r2,然后将r2的相应位清零剩下特定位

//bic   r2, r2, r0     与上面一样解释,3:最后比较r1,r2

//总结:这一段代码是通过读取当前运行地址和链接地址,然后处理两个地址后比对是否相等,来判定当前运行是在sram中(不相等)

//还是在ddr 中(相等),从而决定是否跳过下面的时钟和ddr 初始化(在这里与裸机重定位时的不同在于:裸机重定位的比较是对运行地址

//和链接地址一开始就比对,就是代码没有执行多少之前就将两个地址进行比对,而这里是将代码执行了一些,然后利用当前运行的地址

//与makefile 中指定的链接地址进行比对,方法是将当前运行到哪的地址的这个地址取出来,然后用清后4kB做法,将当前运行地址的末尾

//一点偏移地址去掉,然后再跟链接地址比对),比对用意:就是判断当前运行地址在sram 还是ddr中,然后决定是否执行初始化时钟跟ddr

 

   /* init system clock */   //初始化时钟

   bl system_clock_init

 

   /* Memory initialize */  //初始化ddr动态内存,源代码在uboot/cpu/s5pv11x/s5pv110/cpu_init.S

   bl mem_ctrl_asm_init

 

1:

   /* for UART */

   bl uart_asm_init      //串口初始化,结合裸机课程,分析这三个初始化,把汇编代码看懂

//最后一步发送大写的o,串口输出有这个说明uboot目前没出错

   bl tzpc_init    //没搞过,不懂

 

#if defined(CONFIG_ONENAND)

   bl onenandcon_init

#endif

 

#if defined(CONFIG_NAND)

   /* simple init for NAND */

   bl nand_asm_init

#endif

 

   /* check reset status  */

 

   ldr    r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)

   ldr    r1, [r0]

   bic    r1, r1, #0xfffeffff

   cmp    r1, #0x10000

   beq    wakeup_reset_pre

 

   /* ABB disable */

   ldr    r0, =0xE010C300

   orr    r1, r1, #(0x1<<23)

   str    r1, [r0]

 

    /*Print 'K' */

   ldr    r0,=ELFIN_UART_CONSOLE_BASE

   ldr    r1, =0x4b4b4b4b                 //打印k,结合之前串口函数先执行打印出的o,可知:lowlevel_init.S执行完如果没有错

   str    r1, [r0, #UTXH_OFFSET]          //就会在串口打印出“OK”字样,这应该是我们uboot中看到的最早的输出信息。用于调试

 

   pop    {pc}

 

wakeup_reset_from_didle:

   /* Wait when APLL is locked */

   ldr    r0, =ELFIN_CLOCK_POWER_BASE

lockloop:

   ldr    r1, [r0, #APLL_CON0_OFFSET]

   and    r1, r1, #(1<<29)

   cmp    r1, #(1<<29)

   bne     lockloop

   beq    exit_wakeup

 

wakeup_reset_pre:

   mrc    p15, 0, r1, c1, c0, 1    @Read CP15 Auxiliary control register

   and    r1, r1, #0x80000000    @Check L2RD is disable or not

   cmp    r1, #0x80000000

   bne    wakeup_reset        @if L2RD is not disable jump towakeup_reset

 

   bl    disable_l2cache

   bl    v7_flush_dcache_all

   /* L2 cache enable at sleep.S of kernel

    * bl    enable_l2cache

    */

 

wakeup_reset:

   /* init system clock */

   bl system_clock_init

   bl mem_ctrl_asm_init

   bl tzpc_init

#if defined(CONFIG_ONENAND)

   bl onenandcon_init

#endif

#if defined(CONFIG_NAND)

   bl nand_asm_init

#endif

 

exit_wakeup:

   /*Load return address and jump to kernel*/

   ldr    r0,=(INF_REG_BASE+INF_REG0_OFFSET)

   ldr    r1, [r0]    /* r1 = physical address of s5pc110_cpu_resumefunction*/

 

   mov    pc, r1        /*Jump to kernel */

   nop

   nop

 

/*

 *system_clock_init: Initialize core clock and bus clock.

 *void system_clock_init(void)

 */

system_clock_init:     //初始化时钟 直到396行,以下的宏定义在x210_sd.h中的300行到428行,所以代码不用动,

//要查看各个宏定义的值是多少,所以移植时根本不用动代码,改x210_sd.h的宏的值才对

   ldr    r0,=ELFIN_CLOCK_POWER_BASE    @0xe0100000

 

   /* Set Mux to FIN */

   ldr    r1, =0x0

   str    r1, [r0, #CLK_SRC0_OFFSET]

 

   ldr    r1,    =APLL_LOCKTIME_VAL

   str    r1,    [r0, #APLL_LOCK_OFFSET]

 

   /********lxg added*********************/

   ldr    r0,=ELFIN_CLOCK_POWER_BASE    @0xe0100000

 

   ldr    r1,    =MPLL_LOCKTIME_VAL

   str    r1,    [r0, #MPLL_LOCK_OFFSET]

   /********end*********************/

 

   /* Disable PLL */

#if defined(CONFIG_CHECK_MPLL_LOCK)

retryloop:

#endif

   ldr    r1, =0x0

   str    r1, [r0, #APLL_CON0_OFFSET]

   ldr    r1, =0x0

   str    r1, [r0, #MPLL_CON_OFFSET]

 

   ldr    r1, =0x0

   str    r1, [r0, #MPLL_CON_OFFSET]

 

   ldr       r1, [r0, #CLK_DIV0_OFFSET]

   ldr    r2, =CLK_DIV0_MASK

   bic    r1, r1, r2

 

   ldr    r2, =CLK_DIV0_VAL

   orr    r1, r1, r2

   str    r1, [r0, #CLK_DIV0_OFFSET]

 

   ldr    r1, =APLL_VAL

   str    r1, [r0, #APLL_CON0_OFFSET]

 

   ldr    r1, =MPLL_VAL

   str    r1, [r0, #MPLL_CON_OFFSET]

 

   ldr    r1, =VPLL_VAL

   str    r1, [r0, #VPLL_CON_OFFSET]

 

   /*******lxg added***********************/

   ldr    r1, =EPLL_VAL

   str    r1, [r0, #EPLL_CON_OFFSET]

 

   /*******lxg added***********************/

    ldr       r1, [r0, #CLK_DIV1_OFFSET]

   ldr    r2, =CLK_DIV1_MASK

   bic    r1, r1, r2

 

   ldr    r2, =CLK_DIV1_VAL

   orr    r1, r1, r2

   str    r1, [r0, #CLK_DIV1_OFFSET]

 

   ldr       r1, [r0,#CLK_DIV2_OFFSET]

   ldr    r2, =CLK_DIV2_MASK

    bic    r1, r1, r2

 

   ldr    r2, =CLK_DIV2_VAL

   orr    r1, r1, r2

   str    r1, [r0, #CLK_DIV2_OFFSET]

 

   ldr       r1, [r0,#CLK_DIV4_OFFSET]

   ldr    r2, =CLK_DIV4_MASK

   bic    r1, r1, r2

 

   ldr    r2, =CLK_DIV4_VAL

   orr    r1, r1, r2

    str   r1, [r0, #CLK_DIV4_OFFSET]

 

   ldr       r1, [r0,#CLK_DIV6_OFFSET]

   ldr    r2, =CLK_DIV6_MASK

   bic    r1, r1, r2

 

   ldr    r2, =CLK_DIV6_VAL

   orr    r1, r1, r2

   str    r1, [r0, #CLK_DIV6_OFFSET]

   /*******end*****************/

    /*******end*****************/

#if defined(CONFIG_EVT1)

   ldr    r1, =AFC_ON

   str    r1, [r0, #APLL_CON1_OFFSET]

#endif

   mov    r1, #0x10000

1:   subs    r1, r1, #1

   bne    1b

 

#if defined(CONFIG_CHECK_MPLL_LOCK)

   /* MPLL software workaround */

   ldr    r1, [r0, #MPLL_CON_OFFSET]

   orr     r1, r1, #(1<<28)

   str    r1, [r0, #MPLL_CON_OFFSET]

 

   mov    r1, #0x100

1:   subs    r1, r1, #1

   bne    1b

 

   ldr    r1, [r0, #MPLL_CON_OFFSET]

   and    r1, r1, #(1<<29)

   cmp    r1, #(1<<29)

   bne     retryloop

 

   /* H/W lock detect disable */

   ldr    r1, [r0, #MPLL_CON_OFFSET]

   bic     r1, r1, #(1<<28)

   str    r1, [r0, #MPLL_CON_OFFSET]

#endif

 

   ldr    r1, [r0, #CLK_SRC0_OFFSET]

   //ldr    r2, =0x10001111 //lxgchanged.

      ldr    r2, =0x00000111

   orr    r1, r1, r2

   str    r1, [r0, #CLK_SRC0_OFFSET]

 

   // added by terry 2012.12.4 for camera

   ldr r1, [r0, #CLK_SRC1_OFFSET]

   bic r1, r1, #(0xf<<12)

   orr r1, r1, #(0x1<<12) //0001 XusbXTI

   str r1, [r0, #CLK_SRC1_OFFSET]

 

#if defined(CONFIG_MCP_AC)

 

   /* CLK_SRC6[25:24] -> OneDRAM clock sel = MPLL */

   ldr    r1, [r0, #CLK_SRC6_OFFSET]

   bic    r1, r1, #(0x3<<24)

   orr    r1, r1, #0x01000000

   str    r1, [r0, #CLK_SRC6_OFFSET]

 

   /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */

   ldr    r1, [r0, #CLK_DIV6_OFFSET]

   bic    r1, r1, #(0xF<<28)

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

   orr    r1, r1, #0x30000000

   str    r1, [r0, #CLK_DIV6_OFFSET]

 

#elif defined (CONFIG_MCP_H)

 

   /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */

   ldr    r1, [r0, #CLK_SRC6_OFFSET]

   bic    r1, r1, #(0x3<<24)

   orr    r1, r1, #0x00000000

   str    r1, [r0, #CLK_SRC6_OFFSET]

 

   /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */

   ldr    r1, [r0, #CLK_DIV6_OFFSET]

   bic    r1, r1, #(0xF<<28)

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

   orr    r1, r1, #0x00000000

   str    r1, [r0, #CLK_DIV6_OFFSET]

 

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

 

   /* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */

   ldr    r1, [r0, #CLK_SRC6_OFFSET]

   bic    r1, r1, #(0x3<<24)

   orr    r1, r1, #0x01000000

   str    r1, [r0, #CLK_SRC6_OFFSET]

 

   /* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */

   ldr    r1, [r0, #CLK_DIV6_OFFSET]

   bic    r1, r1, #(0xF<<28)

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

   orr    r1, r1, #0x30000000

   str    r1, [r0, #CLK_DIV6_OFFSET]

 

#elif defined (CONFIG_MCP_SINGLE)

 

   /* CLK_DIV6 */

   /*ldr    r1, [r0,#CLK_DIV6_OFFSET]

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

   str    r1, [r0,#CLK_DIV6_OFFSET]*/ //lxg mask

 

#endif

 

   mov    pc, lr

 

/*

 *uart_asm_init: Initialize UART in asm mode, 115200bps fixed.

 *void uart_asm_init(void)

 */

uart_asm_init:          //初始化串口

 

   /* set GPIO(GPA) to enable UART */

    @GPIO setting for UART

   ldr    r0, =ELFIN_GPIO_BASE

   ldr    r1, =0x22222222

   str       r1, [r0,#GPA0CON_OFFSET]

 

   ldr     r1, =0x2222

   str     r1, [r0, #GPA1CON_OFFSET]

 

   // HP V210 use. SMDK not use.

#if defined(CONFIG_VOGUES)

   ldr    r1, =0x100

   str    r1, [r0, #GPC0CON_OFFSET]

 

   ldr    r1, =0x4

   str    r1, [r0, #GPC0DAT_OFFSET]

#endif

 

   ldr    r0, =ELFIN_UART_CONSOLE_BASE        @0xEC000000

   mov    r1, #0x0

   str    r1, [r0, #UFCON_OFFSET]

   str    r1, [r0, #UMCON_OFFSET]

 

   mov    r1, #0x3

   str    r1, [r0, #ULCON_OFFSET]

 

   ldr    r1, =0x3c5

   str    r1, [r0, #UCON_OFFSET]

 

   ldr    r1, =UART_UBRDIV_VAL

   str    r1, [r0, #UBRDIV_OFFSET]

 

   ldr    r1, =UART_UDIVSLOT_VAL

   str    r1, [r0, #UDIVSLOT_OFFSET]

 

   ldr    r1, =0x4f4f4f4f               //初始化完后,在这里向串口发送O,如果有发送则可判断之前的代码没问题

   str    r1, [r0, #UTXH_OFFSET]        @'O'

 

   mov    pc, lr

 

/*

 *Nand Interface Init for SMDKC110

 */

nand_asm_init:

 

   /* Setting GPIO for NAND */

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

 

   ldr    r0, =ELFIN_GPIO_BASE

 

   ldr    r1, [r0, #MP01CON_OFFSET]

    bic    r1, r1, #(0xf<<8)

   orr    r1, r1, #(0x3<<8)

   str    r1, [r0, #MP01CON_OFFSET]

 

   ldr    r1, [r0, #MP01PUD_OFFSET]

   bic    r1, r1, #(0x3<<4)

   str    r1, [r0, #MP01PUD_OFFSET]

 

   ldr    r1, [r0, #MP03CON_OFFSET]

   bic    r1, r1, #0xFFFFFF

   ldr    r2, =0x22222222

   orr    r1, r1, r2

   str    r1, [r0, #MP03CON_OFFSET]

 

   ldr    r1, [r0, #MP03PUD_OFFSET]

   ldr    r2, =0x3fff

   bic    r1, r1, r2

   str    r1, [r0, #MP03PUD_OFFSET]

 

   ldr    r0, =ELFIN_NAND_BASE

 

   ldr    r1, [r0, #NFCONF_OFFSET]

   ldr    r2, =0x777F

   bic    r1, r1, r2

   ldr    r2, =NFCONF_VAL

   orr    r1, r1, r2

   str    r1, [r0, #NFCONF_OFFSET]

 

   ldr    r1, [r0, #NFCONT_OFFSET]

   ldr    r2, =0x707C7

   bic    r1, r1, r2

   ldr    r2, =NFCONT_VAL

   orr    r1, r1, r2

   str    r1, [r0, #NFCONT_OFFSET]

 

   ldr    r1, [r0, #NFCONF_OFFSET]

   orr    r1, r1, #0x70

   orr    r1, r1, #0x7700

   str     r1, [r0, #NFCONF_OFFSET]

 

   ldr    r1, [r0, #NFCONT_OFFSET]

   orr    r1, r1, #0x03

   str     r1, [r0, #NFCONT_OFFSET]

 

   mov    pc, lr

 

/*

 *Setting TZPC[TrustZone Protection Controller]

 */

tzpc_init:

 

   ldr    r0, =ELFIN_TZPC0_BASE

    mov    r1, #0x0

    str    r1, [r0]

    mov    r1, #0xff

    str    r1, [r0, #TZPC_DECPROT0SET_OFFSET]

    str    r1, [r0,#TZPC_DECPROT1SET_OFFSET]

   str    r1, [r0,#TZPC_DECPROT2SET_OFFSET]

 

    ldr     r0, =ELFIN_TZPC1_BASE

    str    r1, [r0,#TZPC_DECPROT0SET_OFFSET]

    str    r1, [r0,#TZPC_DECPROT1SET_OFFSET]

   str    r1, [r0, #TZPC_DECPROT2SET_OFFSET]

 

    ldr    r0, =ELFIN_TZPC2_BASE

    str    r1, [r0,#TZPC_DECPROT0SET_OFFSET]

    str    r1, [r0,#TZPC_DECPROT1SET_OFFSET]

   str    r1, [r0,#TZPC_DECPROT2SET_OFFSET]

   str    r1, [r0,#TZPC_DECPROT3SET_OFFSET]

 

    ldr    r0, =ELFIN_TZPC3_BASE

    str    r1, [r0,#TZPC_DECPROT0SET_OFFSET]

    str    r1, [r0,#TZPC_DECPROT1SET_OFFSET]

   str    r1, [r0,#TZPC_DECPROT2SET_OFFSET]

 

    mov    pc, lr

 

/*

 *OneNAND Interface Init

 */

onenandcon_init:

 

   @; GPIO setting for OneNAND

   ldr    r0, =ELFIN_GPIO_BASE    @0xE0200000

   ldr    r1, [r0, #MP01CON_OFFSET]

   orr    r1, r1, #0x00550000

   str    r1, [r0, #MP01CON_OFFSET]

 

   ldr    r1, [r0, #MP03CON_OFFSET]

   orr    r1, r1, #0x0550

   orr    r1, r1, #0x00550000

   str    r1, [r0, #MP03CON_OFFSET]

 

   ldr    r1, =0xFFFF

   str    r1, [r0,#MP01DRV_SR_OFFSET]

   str    r1, [r0,#MP03DRV_SR_OFFSET]

   str    r1, [r0,#MP06DRV_SR_OFFSET]

   str    r1, [r0,#MP07DRV_SR_OFFSET]

 

wait_orwb:

   @; Read ONENAND_IF_STATUS

   ldr    r0,=ELFIN_ONENANDCON_BASE    @; 0xB0600000

   ldr    r1, [r0,#ONENAND_IF_STATUS_OFFSET]

   bic    r1, r1, #0xFFFFFFFE

   cmp    r1, #0x0

 

   @; ORWB != 0x0

   bne    wait_orwb

 

   @; write new configuration to onenand system configuration1 register

   ldr    r1, =0xF006            @; Sync.

   ldr    r2,=(ELFIN_ONENAND_BASE+0x1E442)    @;0x1E442(REG_SYS_CONF1)

   strh    r1, [r2]

 

   @; read one dummy halfword

   ldrh    r1, [r2]

   ldrh    r1, [r2]

 

   @; write new configuration to ONENAND_IF_CTRL

   ldr    r0,=ELFIN_ONENANDCON_BASE    @; 0xB0600000

   @;ldr    r1, =0x2F006            @; ONENAND_IF_CTRL_REG_VAL (GCEoff)

   ldr    r1, =0x402F006            @; ONENAND_IF_CTRL_REG_VAL (GCE on)

   str    r1, [r0, #ONENAND_IF_CTRL_OFFSET]

 

   mov    pc, lr

 

#ifdef CONFIG_ENABLE_MMU

 

   #ifdef CONFIG_MCP_SINGLE

/*

 *MMU Table for SMDKC110

 *0x0000_0000 -- 0xBFFF_FFFF => Not Allowed

 *0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF

 *0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF

 *0xC800_0000 -- 0xDFFF_FFFF => Not Allowed

 *0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF

 */

 

   /* form a first-level section entry */

.macro FL_SECTION_ENTRY base,ap,d,c,b   //.macro是汇编定义宏的关键字,FL_SECTION_ENTRY宏名,base,ap,d,c,b宏的参数,.word 是宏的值

   .word (\base << 20) | (\ap << 10) | \    //这些数就是在构建表项

         (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) |(1<<1)

.endm   //宏定义结束标志

.section .mmudata, "a"

   .align 14

   // the following alignment creates the mmu table at address 0x4000.

   .globl mmu_table

mmu_table:               //MMU的转换表 665行结束  //建立这个表,从宏观上理解这个表:整个转换表可以看作是一个int类型的数组,数组中的一个元素

   .set __base,0        //就是一个表索引和表项的单元,数组中的元素值就是表项,这个元素的数组下标就是表索引,

   // Access for iRAM   //ARM 段式映射中的长度为1MB,因此一个映射单元只能管1MB的内存块,而整个就需要4G/1MB=4096个映射单元,也就是

   .rept 0x100    //这个是循环的开始的标志(总共循环0x100次,产生0x100个单元映射)       //这个数组的元素个数是4096个,实际上我们处理的时候是没有单个处理这4096个单元,而是把4096个分成几个部分,

   FL_SECTION_ENTRY __base,3,0,0,0     //然后每部分用for循环做相同的处理。//这两部分是循环体

   .set __base,__base+1

   .endr      //循环结束的标志

 

   // Not Allowed

   .rept 0x200 - 0x100

   .word 0x00000000

   .endr      //c0000000-d0000000   映射到30000000-400000000这4G就是我们想要的,我们可用的物理地址就是30000000-4FFFFFFF(DRAM的范围即DMC0和DMC1)

                   //虚拟地址映射只是把虚拟地址的C0000000开头的256MB映射到了DMC0的30000000开头的256MB物理内存上去了,

   .set __base,0x200   //其他的虚拟地址空间根本没动,还是原样的映射

   // should be accessed     //MMU开启后只能用虚拟地址了,不能物理地址

   .rept 0x600 - 0x200    //思考:为什么配置时将链接地址设置为c3e00000,因为这个地址将来会被映射到33e00000这个物理地址上去

   FL_SECTION_ENTRY __base,3,0,1,1

   .set __base,__base+1

   .endr

 

   .rept 0x800 - 0x600

   .word 0x00000000

   .endr

 

   .set __base,0x800

   // should be accessed

   .rept 0xb00 - 0x800

   FL_SECTION_ENTRY __base,3,0,0,0

   .set __base,__base+1

   .endr

 

/*   .rept 0xc00 - 0xb00

   .word 0x00000000

   .endr */

 

   .set __base,0xB00

   .rept 0xc00 - 0xb00

   FL_SECTION_ENTRY __base,3,0,0,0

   .set __base,__base+1

   .endr

 

   // 0xC000_0000鏄犲皠鍒?x2000_0000

   .set __base,0x300

   //.set __base,0x200

   // 256MB for SDRAM with cacheable

   .rept 0xD00 - 0xC00

   FL_SECTION_ENTRY __base,3,0,1,1

   .set __base,__base+1

   .endr

 

   // access is not allowed.

   @.rept 0xD00 - 0xC80

   @.word 0x00000000

   @.endr

 

   .set __base,0xD00

    //1:1 mapping for debugging with non-cacheable

   .rept 0x1000 - 0xD00

   FL_SECTION_ENTRY __base,3,0,0,0

   .set __base,__base+1

   .endr

 

   #else    // CONFIG_MCP_AC,CONFIG_MCP_H, CONFIG_MCP_B

 

/*

 *MMU Table for SMDKC110

 *0x0000_0000 -- 0xBFFF_FFFF => Not Allowed

 *0xB000_0000 -- 0xB7FF_FFFF => A:0xB000_0000 -- 0xB7FF_FFFF

 *0xC000_0000 -- 0xC7FF_FFFF => A:0x3000_0000 -- 0x37FF_FFFF

 *0xC800_0000 -- 0xDFFF_FFFF => Not Allowed

 *0xE000_0000 -- 0xFFFF_FFFF => A:0xE000_0000 -- 0XFFFF_FFFF

 */

 

   /* form a first-level section entry */

.macro FL_SECTION_ENTRY base,ap,d,c,b

   .word (\base << 20) | (\ap << 10) | \

         (\d << 5) | (1<<4) | (\c << 3) | (\b << 2) |(1<<1)

.endm

.section .mmudata, "a"

   .align 14

   // the following alignment creates the mmu table at address 0x4000.

   .globl mmu_table

mmu_table:

   .set __base,0

   // Access for iRAM

   .rept 0x100

   FL_SECTION_ENTRY __base,3,0,0,0

   .set __base,__base+1

   .endr

 

   // Not Allowed

   .rept 0x300 - 0x100

   .word 0x00000000

   .endr

 

   .set __base,0x300

   // should be accessed

   .rept 0x400 - 0x300

   //.rept 0x350 - 0x300

   FL_SECTION_ENTRY __base,3,0,1,1

   .set __base,__base+1

   .endr

 

   // Not Allowed

   //.rept 0x400 - 0x350

   //.word 0x00000000

   //.endr

 

   // DRAM - DMC1 area - used for STL_write : djpark (20090729)

   .set __base,0x400

   // should be accessed

   .rept 0x500 - 0x400

   FL_SECTION_ENTRY __base,3,0,1,1

   .set __base,__base+1

   .endr

 

   .rept 0x800 - 0x500

    .word 0x00000000

   .endr

 

   .set __base,0x800

   // should be accessed

   .rept 0xb00 - 0x800

   FL_SECTION_ENTRY __base,3,0,0,0

   .set __base,__base+1

   .endr

 

   .set __base,0xB00

   .rept 0xc00 - 0xb00

   FL_SECTION_ENTRY __base,3,0,0,0

    .set __base,__base+1

   .endr

 

   .set __base,0x300

   // 80MB for SDRAM with cacheable

   .rept 0xd00 - 0xC00

   //.rept 0xC50 - 0xC00

   FL_SECTION_ENTRY __base,3,0,1,1

   .set __base,__base+1

   .endr

 

   // Not Allowed

   @.rept 0xD00 - 0xC80

   @.word 0x00000000

   @.endr

 

   // Not Allowed

   //.rept 0xD00 - 0xC50

   //.word 0x00000000

   //.endr

 

   .set __base,0xD00

   // 1:1 mapping for debugging with non-cacheable

   .rept 0x1000 - 0xD00

   FL_SECTION_ENTRY __base,3,0,0,0

    .set __base,__base+1

   .endr

   #endif

#endif

收藏助手
不良信息举报
您举报文章:lowlevel.init函数分析
举报原因:
原因补充:

(最多只允许输入30个字)