在分析start_armboot 之前先来解决上节遗留下来的两个问题。
一、lowlevel_init 对哪些设备进行了初始化
二、copy_uboot_to_ram 如何复制UBoot
先上代码
- #include <config.h>
- #include <version.h>
- #include <s3c6410.h>
- #include "mini6410_val.h"
- _TEXT_BASE:
- .word TEXT_BASE
- .globl lowlevel_init
- lowlevel_init:
- mov r12, lr
- /* LED on only #8 */
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x55540000
- str r1, [r0, #GPNCON_OFFSET]
- ldr r1, =0x55555555
- str r1, [r0, #GPNPUD_OFFSET]
- ldr r1, =0xf000
- str r1, [r0, #GPNDAT_OFFSET]
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x1
- str r1, [r0, #GPECON_OFFSET]
- ldr r1, =0x0
- str r1, [r0, #GPEDAT_OFFSET]
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x2A5AAAAA
- str r1, [r0, #GPPCON_OFFSET]
- ldr r1, =0x0
- str r1, [r0, #GPPDAT_OFFSET]
- ldr r1, =0x55555555
- str r1, [r0, #MEM1DRVCON_OFFSET]
- /* Disable Watchdog */ /*关看门狗*/
- ldr r0, =0x7e000000 @0x7e004000
- orr r0, r0, #0x4000
- mov r1, #0
- str r1, [r0]
- @ External interrupt pending clear /*清外部中断标志位*/
- ldr r0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET) /*EINTPEND*/
- ldr r1, [r0]
- str r1, [r0]
- ldr r0, =ELFIN_VIC0_BASE_ADDR @0x71200000
- ldr r1, =ELFIN_VIC1_BASE_ADDR @0x71300000
- @ Disable all interrupts (VIC0 and VIC1) /*禁用VIC0、VIC1*/
- mvn r3, #0x0
- str r3, [r0, #oINTMSK]
- str r3, [r1, #oINTMSK]
- @ Set all interrupts as IRQ /*设置所有中断为IRQ*/
- mov r3, #0x0
- str r3, [r0, #oINTMOD]
- str r3, [r1, #oINTMOD]
- @ Pending Interrupt Clear /*清中断标志位*/
- mov r3, #0x0
- str r3, [r0, #oVECTADDR]
- str r3, [r1, #oVECTADDR]
- /* init system clock */ /*初始化系统时钟*/
- bl system_clock_init
- /* for UART */ /*串口初始化*/
- bl uart_asm_init
- #if defined(CONFIG_NAND) /*初始化NAND*/
- /* simple init for NAND */
- bl nand_asm_init
- #endif
- bl mem_ctrl_asm_init /*初始化DRAM*/
- #if 1
- ldr r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET) /*RST_STAT Check*/
- ldr r1, [r0]
- bic r1, r1, #0xfffffff7
- cmp r1, #0x8
- beq wakeup_reset /*Reset by SLEEP mode wake-up */
- #endif
- 1:
- ldr r0, =ELFIN_UART_BASE /*输出 'K'*/
- ldr r1, =0x4b4b4b4b
- str r1, [r0, #UTXH_OFFSET]
- // ldr r0, =ELFIN_UART_BASE
- // ldr r1, =0x4b4b4b4b
- // str r1, [r0, #UTXH_OFFSET]
- mov lr, r12
- mov pc, lr /*跳回start.s*/
- #if 1
- wakeup_reset:
- /*Clear wakeup status register*/
- ldr r0, =(ELFIN_CLOCK_POWER_BASE+WAKEUP_STAT_OFFSET)
- ldr r1, [r0]
- str r1, [r0]
- /*LED test*/
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x3000
- str r1, [r0, #GPNDAT_OFFSET]
- /*Load return address and jump to kernel*/
- ldr r0, =(ELFIN_CLOCK_POWER_BASE+INF_REG0_OFFSET)
- ldr r1, [r0] /* r1 = physical address of s3c6400_cpu_resume function*/
- mov pc, r1 /*Jump to kernel (sleep-s3c6400.S)*/
- nop
- nop
- #endif
- /*
- * system_clock_init: Initialize core clock and bus clock.
- * void system_clock_init(void)
- */
- system_clock_init:
- ldr r0, =ELFIN_CLOCK_POWER_BASE @0x7e00f000
- ldr r1, [r0, #OTHERS_OFFSET] @0x7e00f900
- mov r2, #0x40
- orr r1, r1, r2
- str r1, [r0, #OTHERS_OFFSET] /*SYS CLOCK SELECT IN CMU 1 : DOUTAPLL*/
- nop
- nop
- nop
- nop
- nop
- ldr r2, =0x80
- orr r1, r1, r2
- str r1, [r0, #OTHERS_OFFSET] /*SYNCMODEREQ to ARM 1: Synchronous mode */
- check_syncack:
- ldr r1, [r0, #OTHERS_OFFSET]
- ldr r2, =0xf00
- and r1, r1, r2
- cmp r1, #0xf00
- bne check_syncack /*SYNC mode acknowledge (Read Only) */
- mov r1, #0xff00
- orr r1, r1, #0xff
- str r1, [r0, #APLL_LOCK_OFFSET] /*Required period to generate a stable clock output*/
- str r1, [r0, #MPLL_LOCK_OFFSET]
- str r1, [r0, #EPLL_LOCK_OFFSET]
- /* CLKUART(=66.5Mhz) = CLKUART_input(532/2=266Mhz) / (UART_RATIO(3)+1) */
- /* CLKUART(=50Mhz) = CLKUART_input(400/2=200Mhz) / (UART_RATIO(3)+1) */
- /* Now, When you use UART CLK SRC by EXT_UCLK1, We support 532MHz & 400MHz value */
- #if defined(CONFIG_CLKSRC_CLKUART)
- ldr r1, [r0, #CLK_DIV2_OFFSET]
- bic r1, r1, #0x70000
- orr r1, r1, #0x30000
- str r1, [r0, #CLK_DIV2_OFFSET]
- #endif
- ldr r1, [r0, #CLK_DIV0_OFFSET] /*Set Clock Divider*/
- bic r1, r1, #0x30000
- bic r1, r1, #0xff00
- bic r1, r1, #0xff
- ldr r2, =CLK_DIV_VAL
- orr r1, r1, r2
- str r1, [r0, #CLK_DIV0_OFFSET]
- ldr r1, =APLL_VAL
- str r1, [r0, #APLL_CON_OFFSET]
- ldr r1, =MPLL_VAL
- str r1, [r0, #MPLL_CON_OFFSET]
- ldr r1, =0x80200203 /* FOUT of EPLL is 96MHz */
- str r1, [r0, #EPLL_CON0_OFFSET]
- ldr r1, =0x0
- str r1, [r0, #EPLL_CON1_OFFSET]
- ldr r1, [r0, #CLK_SRC_OFFSET] /* APLL, MPLL, EPLL select to Fout */
- #if defined(CONFIG_CLKSRC_CLKUART)
- ldr r2, =0x2007
- #else
- ldr r2, =0x7
- #endif
- orr r1, r1, r2
- str r1, [r0, #CLK_SRC_OFFSET]
- /* wait at least 200us to stablize all clock */
- mov r1, #0x10000
- 1: subs r1, r1, #1
- bne 1b
- #ifdef CONFIG_SYNC_MODE /* Synchronization for VIC port */
- ldr r1, [r0, #OTHERS_OFFSET]
- orr r1, r1, #0x20
- str r1, [r0, #OTHERS_OFFSET]
- mov pc, lr
- /*
- * uart_asm_init: Initialize UART in asm mode, 115200bps fixed.
- * void uart_asm_init(void)
- */
- uart_asm_init:
- /* set GPIO to enable UART */
- @ GPIO setting for UART
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, =0x22222222
- str r1, [r0, #GPACON_OFFSET]
- ldr r1, =0x2222
- str r1, [r0, #GPBCON_OFFSET]
- ldr r0, =ELFIN_UART_CONSOLE_BASE @0x7F005000
- mov r1, #0x0
- str r1, [r0, #UFCON_OFFSET]
- str r1, [r0, #UMCON_OFFSET]
- mov r1, #0x3 @was 0.
- str r1, [r0, #ULCON_OFFSET]
- #if defined(CONFIG_CLKSRC_CLKUART)
- ldr r1, =0xe45 /* UARTCLK SRC = 11 => EXT_UCLK1*/
- #else
- ldr r1, =0x245 /* UARTCLK SRC = x0 => PCLK */
- #endif
- str r1, [r0, #UCON_OFFSET]
- #if defined(CONFIG_UART_50)
- ldr r1, =0x1A
- #elif defined(CONFIG_UART_66)
- ldr r1, =0x22
- #else
- ldr r1, =0x1A
- #endif
- str r1, [r0, #UBRDIV_OFFSET]
- #if defined(CONFIG_UART_50)
- ldr r1, =0x3
- #elif defined(CONFIG_UART_66)
- ldr r1, =0x1FFF
- #else
- ldr r1, =0x3
- #endif
- str r1, [r0, #UDIVSLOT_OFFSET]
- ldr r1, =0x4f4f4f4f
- str r1, [r0, #UTXH_OFFSET] @'O' /*串口输出'O'*/
- mov pc, lr
- /*
- * Nand Interface Init for SMDK6400 */
- nand_asm_init: /*NAND Flash Configuration register*/
- ldr r0, =ELFIN_NAND_BASE
- 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
- #ifdef CONFIG_ENABLE_MMU
- /*
- * MMU Table for SMDK6400
- */
- /* 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
- // 1:1 mapping for debugging
- .rept 0xA00
- FL_SECTION_ENTRY __base,3,0,0,0
- .set __base,__base+1
- .endr
- // access is not allowed.
- .rept 0xC00 - 0xA00
- .word 0x00000000
- .endr
- // 128MB for SDRAM 0xC0000000 -> 0x50000000
- .set __base, 0x500
- .rept 0xC80 - 0xC00
- FL_SECTION_ENTRY __base,3,0,1,1
- .set __base,__base+1
- .endr
- // access is not allowed.
- .rept 0x1000 - 0xc80
- .word 0x00000000
- .endr
- #endif
下面来看另一个代码 copy_uboot_to_ram
- int copy_uboot_to_ram (void)
- {
- int large_block = 0;
- int i;
- vu_char id;
- NAND_ENABLE_CE(); /*Enable nandchip select*/
- NFCMD_REG = NAND_CMD_READID; /*read id*/
- NFADDR_REG = 0x00;
- /* wait for a while */
- for (i=0; i<200; i++);
- id = NFDATA8_REG;
- id = NFDATA8_REG;
- if (id > 0x80)
- large_block = 1;
- /* read NAND Block.
- * 128KB ->240KB because of U-Boot size increase. by scsuh
- * So, read 0x3c000 bytes not 0x20000(128KB).
- */
- return nandll_read_blocks(CFG_PHY_UBOOT_BASE, UBOOTBINSIZE, large_block); /** Read data from NAND.*/
- } static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
- {
- uchar *buf = (uchar *)dst_addr;
- int i;
- <span style="white-space: pre; "> </span>uint page_shift = 9; /* 512bytes/page */
- <span style="white-space: pre; "> </span>if (large_block)
- <span style="white-space: pre; "> </span>page_shift = 11; /* 2k/page */
- /* Read pages */
- for (i = 0; i < (UBOOTBINSIZE>>page_shift); i++, buf+=(1<<page_shift)) {
- // for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift)) {
- nandll_read_page(buf, i, large_block);
- }
- return 0;
- }