TQ210 —— s5pv210 lowlevel_init.S分析(uboot第一阶段)

/*
 * Memory Setup stuff - taken from blob memsetup.S
 *
 * Copyright (C) 1999 2000 2001 Erik Mouw ([email protected]) and
 *                     Jan-Derk Bakker ([email protected])
 *
 * Modified for the Samsung SMDK2410 by
 * (C) Copyright 2002
 * David Mueller, ELSOFT AG, <[email protected]>
 *
 * 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,
 * MA 02111-1307 USA
 */


#include <config.h>
#include <version.h>

#include <s5pv210.h>
#include "tq210_val.h"

@ 讲start.S的时候已经说过这个TEXT_BASE了
_TEXT_BASE:
	.word	TEXT_BASE

	.globl lowlevel_init
lowlevel_init:
	push	{lr}   @ 将上一个函数的返回地址压入栈中

	/* check reset status  */ 
	@ 检查复位标志,如果是睡眠唤醒,跳过接下来的初始化
	
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) @ 跳转到目的地Reset Control Register的地址传送给r0 Address = 0xE010_A000 =0xE010_0000+0xA000
	ldr	r1, [r0]  @ 将存储器地址为 R0(内存储的值) 的字数据读入寄存器 R1
	bic	r1, r1, #0xfff6ffff   @将r1与0xfff6ffff的反码按位进行与运算(既和0xfff6ffff进行与非运算),并写入r1;结合上一步,可知,这一步的作用是16和19bit置一,其他位清零
	cmp	r1, #0x10000  @ 判断16bit是不是等于1
	beq	wakeup_reset_pre  @ 如果是从睡眠状态唤醒,就跳转到wakeup_reset_pre,既跳过接下来的初始化
    cmp r1, #0x80000    @ 判断是不是从深度空闲(Deep-IDLE)状态唤醒
	beq	wakeup_reset_from_didle   @ 如果是,就跳转到wakeup_reset_from_didle

	/* IO Retention release */
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)  @ 将跳转目的地址MISC Register的地址传送给r0   Address = 0xE010_E000 =0xE010_0000+0xE000
	ldr	r1, [r0]  @ 将存储器地址为 R0(内存储的值) 的字数据读入寄存器 R1
	ldr	r2, =IO_RET_REL  @将IO_RET_REL( ((1 << 31) | (1 << 29) | (1 << 28)) )存入r2
    orr r1, r1, r2  @ 将r1和r2的值进行或运算,结果存入r1
	str	r1, [r0]  @ 将r1的值写入以r0内的值为地址的内存空间

	/* Disable Watchdog */
	@ 关闭看门狗
	ldr	r0, =ELFIN_WATCHDOG_BASE	/* 0xE2700000 */
	mov	r1, #0
	str	r1, [r0]

	/* SRAM(2MB) init for SMDKC110 */
	/* GPJ1 SROM_ADDR_16to21 */
	@ 配置sram引脚,16位数据宽度,22位地址宽度
	ldr	r0, =ELFIN_GPIO_BASE
	
	ldr	r1, [r0, #GPJ1CON_OFFSET]
	bic	r1, r1, #0xFFFFFF
	ldr	r2, =0x444444
	orr	r1, r1, r2
	str	r1, [r0, #GPJ1CON_OFFSET]

	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 */
	@ 设置PMIC(Power Management IC)控制引脚,既电源管理ic引脚(基于I2C)
	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 be configured before U-Boot
	 * is running in ram.
	 */
	 /*下面的代码事实上只是判断pc和_TEXT_BASE(0X23e00000)的最高两位是否相同*/
     /* 根据s5pv210的数据手册可知,首先,系统会运行固化在irom的BL0,紧接着会从外部nand
      * 或sdcard等设备读取前16K的BL1代码到IRAM中的0xD0020000处。然后从0xD0020010处运行(因为前16byte是校验和的值)
      * BL1的作用是初始化DRAM,拷贝BL2到<span style="font-family: Arial, Helvetica, sans-serif;">DRAM</span>中_TEXT_BASE(0X23e00000)处,然后跳到DRAM中运行
      * 因此可以通过最高两位来判断代码是在哪里运行
      * 同时可知,当代码已经就在DRAM中运行时,就必须跳过DRAM的初始化
     */
	ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */
	ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp     r1, r2                  /* compare r0, r1                  */
	beq     1f			/* r0 == r1 then skip sdram init   */

	/* init PMIC chip */
#ifdef CONFIG_TQ210_IIC_PM_CHIP
	bl PMIC_InitIp
#endif

	/* init system clock */
	@ 时钟初始化 PLL初始化,要想看懂此汇编,请查看datsheet中,clk control章节
	bl system_clock_init

	/* Memory initialize */
	@ 内存初始化
	bl mem_ctrl_asm_init
	
1:
	/* for UART */
	@ 串口初始化,要看懂此汇编, 请查看datsheet中, 请查看串口章节
	bl uart_asm_init

	bl tzpc_init

	@ 这段不执行
#if defined(CONFIG_ONENAND)
	bl onenandcon_init
#endif

    @ nand初始化
#if defined(CONFIG_NAND)
	/* simple init for NAND */
	bl nand_asm_init
#endif

	/* check reset status  */
	
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
	ldr	r1, [r0]
	bic	r1, r1, #0xfffeffff
	cmp	r1, #0x10000
	beq	wakeup_reset_pre

	/* ABB disable */
	ldr	r0, =0xE010C300
	orr	r1, r1, #(0x1<<23)
	str	r1, [r0]

	/* Print 'K' */
	ldr	r0, =ELFIN_UART_CONSOLE_BASE
	ldr	r1, =0x4b4b4b4b
	str	r1, [r0, #UTXH_OFFSET]

	pop	{pc} @ 返回到start.S

wakeup_reset_from_didle: @ 从深度睡眠中唤醒
	/* Wait when APLL is locked */
	ldr	r0, =ELFIN_CLOCK_POWER_BASE
lockloop:
	ldr	r1, [r0, #APLL_CON0_OFFSET]
	and	r1, r1, #(1<<29)
	cmp	r1, #(1<<29)
	bne 	lockloop @ 这里使用循环
	beq	exit_wakeup

wakeup_reset_pre:
	mrc	p15, 0, r1, c1, c0, 1	@Read CP15 Auxiliary control register
	and	r1, r1, #0x80000000	@Check L2RD is disable or not
	cmp	r1, #0x80000000		
	bne	wakeup_reset		@if L2RD is not disable jump to wakeup_reset 
	
	bl	disable_l2cache
	bl	v7_flush_dcache_all
	/* L2 cache enable at sleep.S of kernel
	 * bl	enable_l2cache 
	 */
#ifdef CONFIG_TQ210
	bl	enable_l2cache
#endif

wakeup_reset:
	/* init system clock */
	bl system_clock_init
	bl mem_ctrl_asm_init
	bl tzpc_init
#if defined(CONFIG_ONENAND)
	bl onenandcon_init
#endif
#if defined(CONFIG_NAND)
	bl nand_asm_init
#endif

exit_wakeup:
	/*Load return address and jump to kernel*/
	ldr	r0, =(INF_REG_BASE+INF_REG0_OFFSET)
	ldr	r1, [r0]	/* r1 = physical address of s5pc110_cpu_resume function*/

	mov	pc, r1		/*Jump to kernel */
	nop
	nop

/*
 * system_clock_init: Initialize core clock and bus clock.
 * void system_clock_init(void)
 */
system_clock_init:
   /* 这一段的作用是将Clock Source Control Registers值清空
    * 具体的作用是将VPLL_SEL、EPLL_SEL、MPLL_SEL和APLL_SEL的时钟源设置为FINVPLL,将MUX_MSYS_SEL、MUX_DSYS_SEL和MUX_PSYS_SEL时钟源设置为SCLKMPLL
    * 将ONENAND_SEL时钟源设置为HCLK_PSYS
    * 为什么这样设置,因为未设置 PLL 和各种分频系数之前,我们不能使用 PLL,为了保险起见,暂时直接使用频率较低
    * 的外接的 24MHz 晶振,待设置好 PLL 和分频系数后再重新设置各种时钟开关
    */
	ldr	r0, =ELFIN_CLOCK_POWER_BASE	@0xe0100000

	/* Set Mux to FIN */
	ldr	r1, =0x0
	str	r1, [r0, #CLK_SRC0_OFFSET]

	ldr	r1,	=APLL_LOCKTIME_VAL   @将APLL_LOCKTIME_VAL(0x2cf)装入r1
	str	r1,	[r0, #APLL_LOCK_OFFSET]  @将r1内的值装入地址为(r0内的值+CLK_SRC0_OFFSET = 0xe0100000)的内存,即设置APLL的锁定周期

    /*
	 * A PLL requires locking period when input frequency is changed or frequency division (multiplication) values are
     * changed.PLL_LOCK register specifies this locking period, which is based on PLL’s source clock. During this
     * period, output will be low state
    */
	/* Disable PLL */
#if defined(CONFIG_CHECK_MPLL_LOCK)
retryloop:
#endif
	ldr	r1, =0x0
	str	r1, [r0, #APLL_CON0_OFFSET]  @ 将APLL控制寄存器的值清空,这个寄存器的第31位置零关闭APLL 25-16bit配置MDIV的分频 
	@ 13-8bit配置PDIV的分频 2-0bit配置SDIV的分频
	ldr	r1, =0x0
	str	r1, [r0, #MPLL_CON_OFFSET]   @ 配置MPLL

	ldr	r1, =0x0
	str	r1, [r0, #MPLL_CON_OFFSET]   @ 重复配置MPLL,确保MPLL配置成功
 
	ldr   	r1, [r0, #CLK_DIV0_OFFSET] @ Clock Divider Control Register(0xe0100300)
	ldr	r2, =CLK_DIV0_MASK             @ CLK_DIV0_MASK(0x7fffffff)
	bic	r1, r1, r2                     @ 首先清零

	ldr	r2, =CLK_DIV0_VAL              @ CLK_DIV0_VAL
	orr	r1, r1, r2
	str	r1, [r0, #CLK_DIV0_OFFSET]
	
    /*
    *CLK_DIV0_VAL = ((0<<APLL_RATIO)|(4<<A2M_RATIO)|(4<<HCLK_MSYS_RATIO)|(1<<PCLK_MSYS_RATIO)\
    *   |(3<<HCLK_DSYS_RATIO)|(1<<PCLK_DSYS_RATIO)|(4<<HCLK_PSYS_RATIO)|(1<<PCLK_PSYS_RATIO))
    *#define APLL_RATIO         0
    *#define A2M_RATIO          4
    *#define HCLK_MSYS_RATIO    8
    *#define PCLK_MSYS_RATIO    12
    *#define HCLK_DSYS_RATIO    16
    *#define PCLK_DSYS_RATIO    20
    *#define HCLK_PSYS_RATIO    24
    *#define PCLK_PSYS_RATIO    28
    */
	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]
#if defined(CONFIG_EVT1)
	ldr	r1, =AFC_ON
	str	r1, [r0, #APLL_CON1_OFFSET]
#endif
	mov	r1, #0x10000
1:	subs	r1, r1, #1    @ 延时 将r1-1的值存入r1
	bne	1b                @ 如果运算结果不等零(即CPSR寄存器标志位Z不等于一),退回到前面标签“1”处执行  当 CPSR 寄存器中的 Z 
                          @ 条件码置位时(即前面的计算结果为零),则顺序执行(即运行接下来的:ldr   r1, [r0, #CLK_SRC0_OFFSET])
                          @ 当计算结果为零时,Z为1

#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
	orr	r1, r1, r2
	str	r1, [r0, #CLK_SRC0_OFFSET]

#if defined(CONFIG_MCP_AC)  @ 210没有定义,暂时不分析

	/* 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_N)
	/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
	ldr	r1, [r0, #CLK_SRC6_OFFSET]
	mov	r1, #0x00000000
	str	r1, [r0, #CLK_SRC6_OFFSET]

	/* CLK_DIV6[31:28] -> 0=1/1 */
	ldr	r1, [r0, #CLK_DIV6_OFFSET]
	mov	r1, #0x00000000
	str	r1, [r0, #CLK_DIV6_OFFSET]


#elif defined (CONFIG_MCP_H)

	/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
	ldr	r1, [r0, #CLK_SRC6_OFFSET]
	bic	r1, r1, #(0x3<<24)
	orr	r1, r1, #0x00000000
	str	r1, [r0, #CLK_SRC6_OFFSET]

	/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
	ldr	r1, [r0, #CLK_DIV6_OFFSET]
	bic	r1, r1, #(0xF<<28)
	bic	r1, r1, #(0x7<<12)	@; ONENAND_RATIO: 0
	orr	r1, r1, #0x00000000
	str	r1, [r0, #CLK_DIV6_OFFSET]	

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

	/* CLK_SRC6[25:24] -> OneDRAM clock sel = 00:SCLKA2M, 01:SCLKMPLL */
	ldr	r1, [r0, #CLK_SRC6_OFFSET]
	bic	r1, r1, #(0x3<<24)
	orr	r1, r1, #0x01000000
	str	r1, [r0, #CLK_SRC6_OFFSET]

	/* CLK_DIV6[31:28] -> 4=1/5, 3=1/4(166MHZ@667MHz), 2=1/3 */
	ldr	r1, [r0, #CLK_DIV6_OFFSET]
	bic	r1, r1, #(0xF<<28)
	bic	r1, r1, #(0x7<<12)	@; ONENAND_RATIO: 0
	orr	r1, r1, #0x30000000
	str	r1, [r0, #CLK_DIV6_OFFSET]

#elif defined (CONFIG_MCP_SINGLE) @ 这段定义了,分析分析

	/* CLK_DIV6 */
	ldr	r1, [r0, #CLK_DIV6_OFFSET]  @ 设置分频   Clock Divider Control Register(0xe0100318)
	bic	r1, r1, #(0x7<<12)	@; ONENAND_RATIO: 0  @ 0DIVFLASH clock divider ratio,计算公式:SCLK_ONENAND = MOUTFLASH / (ONENAND_RATIO + 1)
	str	r1, [r0, #CLK_DIV6_OFFSET]

#endif	

	mov	pc, lr @ 返回到start.S


/*
 * uart_asm_init: Initialize UART in asm mode, 115200bps fixed.
 * void uart_asm_init(void)
 */
uart_asm_init:

	/* set GPIO(GPA) to enable UART */
	@ GPIO setting for UART
	@ 串口引脚复用设置
	ldr	r0, =ELFIN_GPIO_BASE
	ldr	r1, =0x22222222
	str   	r1, [r0, #GPA0CON_OFFSET]

	ldr     r1, =0x2222
	str     r1, [r0, #GPA1CON_OFFSET]

	// HP V210 use. SMDK not use.
#if defined(CONFIG_VOGUES)
	ldr    r1, =0x100
	str    r1, [r0, #GPC0CON_OFFSET]

	ldr    r1, =0x4
	str    r1, [r0, #GPC0DAT_OFFSET]
#endif

	ldr	r0, =ELFIN_UART_CONSOLE_BASE		@0xEC000000
	mov	r1, #0x0
	str	r1, [r0, #UFCON_OFFSET]
	str	r1, [r0, #UMCON_OFFSET]

	mov	r1, #0x3
	str	r1, [r0, #ULCON_OFFSET]

	ldr	r1, =0x3c5
	str	r1, [r0, #UCON_OFFSET]

	ldr	r1, =UART_UBRDIV_VAL
	str	r1, [r0, #UBRDIV_OFFSET]

	ldr	r1, =UART_UDIVSLOT_VAL
	str	r1, [r0, #UDIVSLOT_OFFSET]

	ldr	r1, =0x4f4f4f4f
	str	r1, [r0, #UTXH_OFFSET]		@'O'

	mov	pc, lr

/*
 * Nand Interface Init for SMDKC110
 */
nand_asm_init:

	/* Setting GPIO for NAND */
	/* This setting is NAND initialze code at booting time in iROM. */
    @ 设置IO BASE
	ldr		r0, =ELFIN_GPIO_BASE
	
	ldr		r1, [r0, #MP01CON_OFFSET]
	bic		r1, r1, #(0xf<<8)
	orr		r1, r1, #(0x3<<8)
	str		r1, [r0, #MP01CON_OFFSET]

	ldr		r1, [r0, #MP01PUD_OFFSET]
	bic		r1, r1, #(0x3<<4)
	str		r1, [r0, #MP01PUD_OFFSET]

	ldr		r1, [r0, #MP03CON_OFFSET]
	bic		r1, r1, #0xFFFFFF
	ldr		r2, =0x22222222
	orr		r1, r1, r2
	str		r1, [r0, #MP03CON_OFFSET]

	ldr		r1, [r0, #MP03PUD_OFFSET]
	ldr		r2, =0x3fff
	bic		r1, r1, r2
	str		r1, [r0, #MP03PUD_OFFSET]

	ldr		r0, =ELFIN_NAND_BASE

	ldr		r1, [r0, #NFCONF_OFFSET]
	ldr		r2, =0x777F
	bic		r1, r1, r2
	ldr		r2, =NFCONF_VAL
	orr		r1, r1, r2
	str		r1, [r0, #NFCONF_OFFSET]

	ldr		r1, [r0, #NFCONT_OFFSET]
	ldr		r2, =0x707C7
	bic		r1, r1, r2
	ldr		r2, =NFCONT_VAL
	orr		r1, r1, r2
	str		r1, [r0, #NFCONT_OFFSET]

	ldr		r1, [r0, #NFCONF_OFFSET]
	orr		r1, r1, #0x70
	orr		r1, r1, #0x7700
	str		r1, [r0, #NFCONF_OFFSET]

	ldr		r1, [r0, #NFCONT_OFFSET]
	orr		r1, r1, #0x03
	str		r1, [r0, #NFCONT_OFFSET]

	mov		pc, lr

/*
 * Setting TZPC[TrustZone Protection Controller]
 */
tzpc_init:

	ldr	r0, =ELFIN_TZPC0_BASE
 	mov	r1, #0x0
 	str	r1, [r0]
 	mov	r1, #0xff
 	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
 	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET] 	

 	ldr 	r0, =ELFIN_TZPC1_BASE
 	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
 	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET] 	

 	ldr	r0, =ELFIN_TZPC2_BASE
 	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
 	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET]
	str	r1, [r0, #TZPC_DECPROT3SET_OFFSET] 

 	ldr	r0, =ELFIN_TZPC3_BASE
 	str	r1, [r0, #TZPC_DECPROT0SET_OFFSET]
 	str	r1, [r0, #TZPC_DECPROT1SET_OFFSET]
	str	r1, [r0, #TZPC_DECPROT2SET_OFFSET] 	

 	mov	pc, lr

/*
 * OneNAND Interface Init
 */
onenandcon_init:

	@; GPIO setting for OneNAND
	ldr	r0, =ELFIN_GPIO_BASE	@0xE0200000
	ldr	r1, [r0, #MP01CON_OFFSET]
	orr	r1, r1, #0x00550000
	str	r1, [r0, #MP01CON_OFFSET]

	ldr	r1, [r0, #MP03CON_OFFSET]
	orr	r1, r1, #0x0550
	orr	r1, r1, #0x00550000
	str	r1, [r0, #MP03CON_OFFSET]

	ldr	r1, =0xFFFF
	str	r1, [r0, #MP01DRV_SR_OFFSET]
	str	r1, [r0, #MP03DRV_SR_OFFSET]
	str	r1, [r0, #MP06DRV_SR_OFFSET]
	str	r1, [r0, #MP07DRV_SR_OFFSET]

wait_orwb:
	@; Read ONENAND_IF_STATUS
	ldr	r0, =ELFIN_ONENANDCON_BASE	@; 0xB0600000
	ldr	r1, [r0, #ONENAND_IF_STATUS_OFFSET]
	bic	r1, r1, #0xFFFFFFFE
	cmp	r1, #0x0

	@; ORWB != 0x0
	bne	wait_orwb

	@; write new configuration to onenand system configuration1 register
	ldr	r1, =0xF006			@; Sync.
	ldr	r2, =(ELFIN_ONENAND_BASE+0x1E442)	@; 0x1E442(REG_SYS_CONF1)
	strh	r1, [r2]

	@; read one dummy halfword
	ldrh	r1, [r2]
	ldrh	r1, [r2]

	@; write new configuration to ONENAND_IF_CTRL
	ldr	r0, =ELFIN_ONENANDCON_BASE	@; 0xB0600000
	@;ldr	r1, =0x2F006			@; ONENAND_IF_CTRL_REG_VAL (GCE off)
	ldr	r1, =0x402F006			@; ONENAND_IF_CTRL_REG_VAL (GCE on)
	str	r1, [r0, #ONENAND_IF_CTRL_OFFSET]

	mov	pc, lr


#ifdef CONFIG_ENABLE_MMU @ uboot没有开启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
	.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 0x200 - 0x100
	.word 0x00000000
	.endr
#ifdef CONFIG_TQ210_1G
	.set __base,0x200
	// should be accessed
	.rept 0x600 - 0x200
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr
#else
	.set __base,0x200
	// should be accessed
	.rept 0x600 - 0x200
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr
/*
	.set __base,0x400
	// should be accessed
	.rept 0x500 - 0x400
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr*/ 
#endif /* CONFIG_TQ210_1G */
	.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
#ifdef CONFIG_TQ210_1G
	.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
	.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	
#endif /* CONFIG_TQ210_1G */
	#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

#if defined(CONFIG_MCP_N)
	.set __base,0x300
	// should be accessed
	.rept 0x400 - 0x300
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr
#else
	.set __base,0x300
	// should be accessed
	.rept 0x350 - 0x300
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr

	// Not Allowed
	.rept 0x400 - 0x350
	.word 0x00000000
	.endr
#endif

	.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

#if defined(CONFIG_MCP_N)
	.set __base,0x300
	// 256MB for SDRAM with cacheable
	.rept 0xD00 - 0xC00
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr
#else
	.set __base,0x300
	// 80MB for SDRAM with cacheable
	.rept 0xC50 - 0xC00
	FL_SECTION_ENTRY __base,3,0,1,1
	.set __base,__base+1
	.endr

	// Not Allowed
	.rept 0xD00 - 0xC50
	.word 0x00000000
	.endr
#endif

	.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

你可能感兴趣的:(uboot,TQ210,s5pv210,uboot分析,lowlwvwl_init.S)