1. 启动方式
6410支持SD/MMC Card, OneNand, Nand启动方式。由于我手上的这款开发板采用的MLC2的Nand Flash(K9GAG08U0E),适合1KBytes/12 bit 硬件ECC校验,而6410 最大支持 512 Bytes/8 bit 硬件ECC校验,所以S3C6410在硬件上根本就不支K9GAG08U0E,友善之臂采用了软件和硬件结合的ECC校验,没有提供开源代码。所以我也不打算折腾采用Nand启动的方式启动u-boot,而采用SD卡启动u-boot,然后使用TFTP下载linux内核,最后使用NFS启动文件系统。
2. 代码实现
上一篇文章已经基于s3c6400对Tiny6410的单板进行了复制,现在要在此基础上进行修改代码,实现SD卡启动u-boot。u-boot-2012.10支持spl,即将u-boot.bin分割成两部分,前4k被称作spl(nand-spl或者mmc-spl),前4k放在BL1, 整个u-boot.bin则放在BL2。系统上电时,由iROM里面的启动代码(BL0)自动将其复制到启动设备(SD卡或者Nand Flash)。然后由这4k代码(BL1)实现将u-boot.bin(BL2)移动到SDRAM中,最后跳转到起始地址进行u-boot的启动。
2.1 仿照nand-spl复制mmc-spl
u-boot-2012.10默认为nand-spl启动,没有提供mmc-spl的启动。因此需要仿照nand-spl复制mmc-spl。
[wf@localhost u-boot-2012.10]$ ls
api config.mk drivers lib nand_spl snapshot.commit
arch COPYING dts MAINTAINERS net spl
board CREDITS examples MAKEALL post test
boards.cfg disk fs Makefile README tools
common doc include mkconfig rules.mk
[wf@localhost u-boot-2012.10]$ cp -a nand_spl mmc_spl
[wf@localhost u-boot-2012.10]$ ls
api config.mk drivers lib mmc_spl rules.mk
arch COPYING dts MAINTAINERS nand_spl snapshot.commit
board CREDITS examples MAKEALL net spl
boards.cfg disk fs Makefile post test
common doc include mkconfig README tools
然后删除根nand相关的文件,并新建一个mmc_boot.c, 用于实现将u-boot的代码从SD卡复制到SDRAM中。
[wf@localhost mmc_spl]$ ls
board nand_boot.c nand_boot_fsl_elbc.c nand_boot_fsl_ifc.c nand_boot_fsl_nfc.c
[wf@localhost mmc_spl]$ rm *.c
[wf@localhost mmc_spl]$ ls
board
[wf@localhost mmc_spl]$ touch mmc_boot.c
[wf@localhost mmc_spl]$ ls
board mmc_boot.c
三星Internal ROM Application Note提供了启动设备的复制函数:
根据手册,SD卡的复制函数如下:
/**
**This Function copies SD/MMC Card Data to memory.
**Always use EPLL clock.
**@param channel(z): HSMMC Controller channel number
**@param StartBlkAddress(a): Source card(SD/MMC) Address.(It must be block address)
**@param blockSize(b): Number of block to copy.
**@param memoryPtr(c): Buffer to copy from.
**@param with init(e): reinitialize or not
**@return bool(unsigned char) - success or failure
*/
#define CopyMMCtoMem(z,a,b,c,e) ((((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool)) (*((unsigned int *)0x0C004008))))(z,a,b,c,e)
代码实现:
© Copyright 2011
Tekkaman Ninja, tekkamanninja at gmail.com
/*
* Copyright (C) 2011 Samsung Electronics
*
* (C) Copyright 2011
* Tekkaman Ninja, <tekkamanninja at gmail.com>
*
* 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 <asm/types.h>
#include <asm/io.h>
#include <config.h>
/* TCM function for bl2 load */
#if defined(CONFIG_S3C6400)
#define copy_sd_mmc_to_mem(a,b,c,d,e) \
(((int(*)(uint, ushort, uint *, uint, int))(*((uint *)(TCM_BASE + 0x8))))(a,b,c,d,e))
#elif defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
#define copy_sd_mmc_to_mem(a,b,c,d,e) \
(((int(*)(int, uint, ushort, uint *, int))(*((uint *)(TCM_BASE + 0x8))))(a,b,c,d,e))
#endif
void copy_uboot_to_ram(void)
{
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_UBOOT_POS, MMC_UBOOT_BLKCNT, (uint *)(CONFIG_SYS_MMC_U_BOOT_START),
MMC_INIT_REQUIRED);
#ifdef CONFIG_MMC_ENV_DST
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_ENV_POS, MMC_ENV_BLKCNT, (uint *)CONFIG_MMC_ENV_DST,
MMC_INIT_REQUIRED);
#ifdef CONFIG_MMC_OFFSET_REDUND
copy_sd_mmc_to_mem(MMC_BOOT_CHANNEL,
MMC_ENV_POS_REDUND, MMC_ENV_BLKCNT, (uint *)CONFIG_MMC_ENV_DST+ CONFIG_ENV_SIZE,
MMC_INIT_REQUIRED);
#endif
#endif
}
void mmc_boot_copy(void)
{
volatile u32 *mmc_control4;
__attribute__((noreturn)) void (*uboot)(void);
if (MMC_BOOT_CHANNEL == 0) {
mmc_control4 = (volatile u32 *)0x7C20008C;
} else if (MMC_BOOT_CHANNEL == 1) {
mmc_control4 = (volatile u32 *)0x7C30008C;
} else if (MMC_BOOT_CHANNEL == 2) {
mmc_control4 = (volatile u32 *)0x7C40008C;
}
writel(readl(mmc_control4) | (0x3 << 16), mmc_control4);
copy_uboot_to_ram();
/*
* Jump to U-Boot image
*/
uboot = (void *)(CONFIG_SYS_MMC_U_BOOT_START);
(*uboot)();
}
这里解释一下这个函数:
这个函数将512K的u-boot(实际的u-boot.bin小于512K)从MMC卡复制到SRAM。 MMC的地址必须为块地址。
MMC_BOOT_CHANNEL = 0
配置从MMC控制器的通道
TCM_BASE = 0x0C004000
0x0C004000 是启动设备复制函数的基地址
MMC_TOTAL_BLKCNT = TCM_BASE - 0x4 = 0XC003FFC
根据“6410 Internal Rom Application Note”, 如果MMC用于启动设备,MMC的信息必须存储再特殊区域。 地址0XC003FFC用于存储MMC的块总计数。因此,本函数中MMC_TOTAL_BLKCNT就是MMC的总块数。
MMC_UBOOT_POS_BACKWARD = 0x300000
在MMC中给U-BOOT留出0x300000 Bytes(3MB)的空间
MMC_BLKSIZE = 512
MMC一个块的大小为512 Bytes
CONFIG_SYS_MMC_U_BOOT_SIZE = (512 * 1024)
配置u-boot的大小为512KB
MMC_UBOOT_POS
= (MMC_TOTAL_BLKCNT-(MMC_UBOOT_POS_BACKWARD/MMC_BLKSIZE))
= (MMC_TOTAL_BLKCNT - (3M/512))
= (MMC_TOTAL_BLKCNT - 6144)我使用的8GB SDHC的总块数为15523840
IROM所认为的总块数MMC_TOTAL_BLKCNT=15522816(15523840-1024)
所以nand_spl/u-boot-spl-16k.bin烧写的位置是15522798块(15522816-18)
u-boot.bin烧写的位置是15516672块(15522816-6144(3MB))
MMC_UBOOT_BLKCNT
= (CONFIG_SYS_MMC_U_BOOT_SIZE / MMC_BLKSIZE)
= (512 * 1024) / 512
配置的u-boot的大小为512KB, 除以512,算出UBOOT在MMC所需要占的块数。
CONFIG_SYS_MMC_U_BOOT_START
= CONFIG_SYS_PHY_UBOOT_BASE
= CONFIG_SYS_SDRAM_BASE + 0x07e00000
将U-BOOT从MMC复制到SDRAM的地址。
修改u-boot-2012.10/mmc_spl/board/samsung/tiny6410/Makefile:
#
# (C) Copyright 2006-2007
# Stefan Roese, DENX Software Engineering, sr@denx.de.
#
# (C) Copyright 2008
# Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
#
# 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
#
CONFIG_MMC_SPL = y
include $(TOPDIR)/config.mk
include $(TOPDIR)/mmc_spl/board/$(BOARDDIR)/config.mk
mmcobj := $(OBJTREE)/mmc_spl/
LDSCRIPT= $(TOPDIR)/mmc_spl/board/$(BOARDDIR)/u-boot.lds
LDFLAGS := -T $(mmcobj)u-boot.lds -Ttext $(CONFIG_SYS_TEXT_BASE) $(LDFLAGS) \
$(LDFLAGS_FINAL) -gc-sections
AFLAGS += -DCONFIG_MMC_SPL -DCONFIG_SPL_BUILD
CFLAGS += -DCONFIG_MMC_SPL -DCONFIG_SPL_BUILD -ffunction-sections
SOBJS = start.o cpu_init.o lowlevel_init.o
COBJS = mmc_boot.o tiny6410_mmc_spl.o
SRCS := $(addprefix $(obj),$(SOBJS:.o=.S) $(COBJS:.o=.c))
OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
__OBJS := $(SOBJS) $(COBJS)
LNDIR := $(mmcobj)board/$(BOARDDIR)
ALL = $(mmcobj)u-boot-spl $(mmcobj)u-boot-spl.bin $(mmcobj)u-boot-spl-16k.bin
all: $(obj).depend $(ALL)
$(mmcobj)u-boot-spl-16k.bin: $(mmcobj)u-boot-spl
$(OBJCOPY) ${OBJCFLAGS} --pad-to=$(PAD_TO) -O binary $< $@
$(mmcobj)u-boot-spl.bin: $(mmcobj)u-boot-spl
$(OBJCOPY) ${OBJCFLAGS} -O binary $< $@
$(mmcobj)u-boot-spl: $(OBJS) $(mmcobj)u-boot.lds
cd $(LNDIR) && $(LD) $(LDFLAGS) $(__OBJS) \
-Map $(mmcobj)u-boot-spl.map \
-o $(mmcobj)u-boot-spl
$(mmcobj)u-boot.lds: $(LDSCRIPT)
$(CPP) $(CPPFLAGS) $(LDPPFLAGS) -ansi -D__ASSEMBLY__ -P - <$^ >$@
# create symbolic links for common files
# from cpu directory
$(obj)start.S:
@rm -f $@
@ln -s $(TOPDIR)/arch/arm/cpu/arm1176/start.S $@
# from SoC directory
$(obj)cpu_init.S:
@rm -f $@
@ln -s $(TOPDIR)/arch/arm/cpu/arm1176/s3c64xx/cpu_init.S $@
# from board directory
$(obj)lowlevel_init.S:
@rm -f $@
@ln -s $(TOPDIR)/board/samsung/tiny6410/lowlevel_init.S $@
# from mmc_spl directory
$(obj)mmc_boot.c:
@rm -f $@
@ln -s $(TOPDIR)/mmc_spl/mmc_boot.c $@
$(obj)tiny6410_mmc_spl.c:
@rm -f $@
@ln -s $(TOPDIR)/board/samsung/tiny6410/tiny6410_mmc_spl.c $@
#########################################################################
$(obj)%.o: $(obj)%.S
$(CC) $(AFLAGS) -c -o $@ $<
$(obj)%.o: $(obj)%.c
$(CC) $(CFLAGS) -c -o $@ $<
# defines $(obj).depend target
include $(SRCTREE)/rules.mk
sinclude $(obj).depend
#########################################################################
修改u-boot-2012.10/mmc_spl/board/samsung/tiny6410/u-boot.lds, 将nand_boot.o修改为mmc_boot.o
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
start.o (.text)
cpu_init.o (.text)
mmc_boot.o (.text)
*(.text)
}
进入u-boot-2012.10/board/samsung/tiny6410/目录,将tiny6410_nand_spl.c复制并重命名为tiny6410_mmc_spl.c
[wf@localhost u-boot-2012.10]$ cd board/samsung/tiny6410/
[wf@localhost tiny6410]$ ls
config.mk Makefile tiny6410_nand_spl.c
lowlevel_init.S tiny6410.c u-boot-nand.lds
[wf@localhost tiny6410]$ cp tiny6410_nand_spl.c tiny6410_mmc_spl.c
[wf@localhost tiny6410]$ ls
config.mk Makefile tiny6410_mmc_spl.c u-boot-nand.lds
lowlevel_init.S tiny6410.c tiny6410_nand_spl.c
修改u-boot-2012.10/Makefile,增加对mmc的配置:
#########################################################################
## ARM1176 Systems
#########################################################################
smdk6400_noUSB_config \
smdk6400_config : unconfig
@mkdir -p $(obj)include $(obj)board/samsung/smdk6400
@mkdir -p $(obj)nand_spl/board/samsung/smdk6400
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
@if [ -z "$(findstring smdk6400_noUSB_config,$@)" ]; then \
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
else \
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/smdk6400/config.tmp;\
fi
@$(MKCONFIG) smdk6400 arm arm1176 smdk6400 samsung s3c64xx
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
tiny6410_noUSB_config \
tiny6410_nand_config : unconfig
@mkdir -p $(obj)include $(obj)board/samsung/tiny6410
@mkdir -p $(obj)nand_spl/board/samsung/tiny6410
@echo "#define CONFIG_NAND_U_BOOT" > $(obj)include/config.h
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
@if [ -z "$(findstring tiny6410_noUSB_config,$@)" ]; then \
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/tiny6410/config.tmp;\
else \
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/tiny6410/config.tmp;\
fi
@$(MKCONFIG) tiny6410 arm arm1176 tiny6410 samsung s3c64xx
@echo "CONFIG_NAND_U_BOOT = y" >> $(obj)include/config.mk
/*add config of mmc*/
tiny6410_noUSB_config \
tiny6410_mmc_config : unconfig
@mkdir -p $(obj)include $(obj)board/samsung/tiny6410
@mkdir -p $(obj)mmc_spl/board/samsung/tiny6410
@echo "#define CONFIG_MMC_U_BOOT" > $(obj)include/config.h
@echo "CONFIG_MMC_U_BOOT = y" >> $(obj)include/config.mk
@if [ -z "$(findstring tiny6410_noUSB_config,$@)" ]; then \
echo "RAM_TEXT = 0x57e00000" >> $(obj)board/samsung/tiny6410/config.tmp;\
else \
echo "RAM_TEXT = 0xc7e00000" >> $(obj)board/samsung/tiny6410/config.tmp;\
fi
@$(MKCONFIG) tiny6410 arm arm1176 tiny6410 samsung s3c64xx
@echo "CONFIG_MMC_U_BOOT = y" >> $(obj)include/config.mk
#########################################################################
#########################################################################
2.2 修改start.S文件,增加对mmc_spl的支持
[wf@localhost u-boot-2012.10]$ cd arch/arm/cpu/arm1176/
[wf@localhost arm1176]$ ls
bcm2835 cpu.c libarm1176.o s3c64xx start.S
config.mk cpu.o Makefile start.o tnetv107x
/*
* armboot - Startup Code for ARM1176 CPU-core
*
* Copyright (c) 2007 Samsung Electronics
*
* Copyright (C) 2008
* Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
*
* 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
*
* 2007-09-21 - Restructured codes by jsgood (jsgood.yang@samsung.com)
* 2007-09-21 - Added MoviNAND and OneNAND boot codes by
* jsgood (jsgood.yang@samsung.com)
* Base codes by scsuh (sc.suh)
*/
#include <asm-offsets.h>
#include <config.h>
#include <version.h>
#include <asm/arch/s3c6400.h>
#ifdef CONFIG_ENABLE_MMU
#include <asm/proc/domain.h>
#endif
#if !defined(CONFIG_ENABLE_MMU) && !defined(CONFIG_SYS_PHY_UBOOT_BASE)
#define CONFIG_SYS_PHY_UBOOT_BASE CONFIG_SYS_UBOOT_BASE
#endif
/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/
.globl _start
_start: b reset
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
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
_pad:
.word 0x12345678 /* now 16*4=64 */
#else
. = _start + 64
#endif
.global _end_vect
_end_vect:
.balignl 16,0xdeadbeef
/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* setup Memory and board specific bits prior to relocation.
* relocate armboot to ram
* setup stack
*
*************************************************************************
*/
.globl _TEXT_BASE
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
/*
* Below variable is very important because we use MMU in U-Boot.
* Without it, we cannot run code correctly before MMU is ON.
* by scsuh.
*/
_TEXT_PHY_BASE:
.word CONFIG_SYS_PHY_UBOOT_BASE
/*
* These are defined in the board-specific linker script.
* Subtracting _start from them lets the linker put their
* relative position in the executable instead of leaving
* them null.
*/
.globl _bss_start_ofs
_bss_start_ofs:
.word __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.word __bss_end__ - _start
.globl _end_ofs
_end_ofs:
.word _end - _start
/* IRQ stack memory (calculated at run-time) + 8 bytes */
.globl IRQ_STACK_START_IN
IRQ_STACK_START_IN:
.word 0x0badc0de
/*
* the actual reset code
*/
reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0, cpsr
bic r0, r0, #0x3f
orr r0, r0, #0xd3
msr cpsr, r0
/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
cpu_init_crit:
/*
* When booting from NAND - it has definitely been a reset, so, no need
* to flush caches and disable the MMU
*/
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
/*
* 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
/* Prepare to disable the MMU */
adr r2, mmu_disable_phys
sub r2, r2, #(CONFIG_SYS_PHY_UBOOT_BASE - CONFIG_SYS_TEXT_BASE)
b mmu_disable
.align 5
/* Run in a single cache-line */
mmu_disable:
mcr p15, 0, r0, c1, c0, 0
nop
nop
mov pc, r2
mmu_disable_phys:
#ifdef CONFIG_DISABLE_TCM
/*
* Disable the TCMs
*/
mrc p15, 0, r0, c0, c0, 2 /* Return TCM details */
cmp r0, #0
beq skip_tcmdisable
mov r1, #0
mov r2, #1
tst r0, r2
mcrne p15, 0, r1, c9, c1, 1 /* Disable Instruction TCM if present*/
tst r0, r2, LSL #16
mcrne p15, 0, r1, c9, c1, 0 /* Disable Data TCM if present*/
skip_tcmdisable:
#endif
#endif
#ifdef CONFIG_PERIPORT_REMAP
/* Peri port setup */
ldr r0, =CONFIG_PERIPORT_BASE
orr r0, r0, #CONFIG_PERIPORT_SIZE
mcr p15,0,r0,c15,c2,4
#endif
/*
* Go setup Memory and board specific bits prior to relocation.
*/
bl lowlevel_init /* go setup pll,mux,memory */
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr sp, =(CONFIG_SYS_INIT_SP_ADDR)
bic sp, sp, #7 /* 8-byte alignment for ABI compliance */
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
ldr r0,=0x00000000
bl board_init_f
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
*/
.globl relocate_code
relocate_code:
mov r4, r0 /* save addr_sp */
mov r5, r1 /* save addr of gd */
mov r6, r2 /* save addr of destination */
ldr r9, =0x00000000
/* Set up the stack */
stack_setup:
mov sp, r4
adr r0, _start
cmp r0, r6
beq fixsym /* skip relocation */
#if defined(CONFIG_TINY6410_LED)
/* if relocate the u-boot code, LEDS will on.*/
ldr r1, =ELFIN_GPIO_BASE
ldr r2, =0x11111111
str r2, [r1, #GPKCON0_OFFSET]
ldr r2, =0x0000AAAA
str r2, [r1, #GPKPUD_OFFSET]
ldr r2, =0x00
str r2, [r1, #GPKDAT_OFFSET]
#endif
mov r1, r6 /* r1 <- scratch for copy_loop */
ldr r3, _bss_start_ofs
add r2, r0, r3 /* r2 <- source end address */
copy_loop:
ldmia r0!, {r9-r10} /* copy from source address [r0] */
stmia r1!, {r9-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end address [r2] */
blo copy_loop
#ifndef CONFIG_SPL_BUILD
/*
* fix .rel.dyn relocations
*/
fixsym:
ldr r0, _TEXT_BASE /* r0 <- Text base */
sub r9, r6, r0 /* r9 <- relocation offset */
ldr r10, _dynsym_start_ofs /* r10 <- sym table ofs */
add r10, r10, r0 /* r10 <- sym table in FLASH */
ldr r2, _rel_dyn_start_ofs /* r2 <- rel dyn start ofs */
add r2, r2, r0 /* r2 <- rel dyn start in FLASH */
ldr r3, _rel_dyn_end_ofs /* r3 <- rel dyn end ofs */
add r3, r3, r0 /* r3 <- rel dyn end in FLASH */
fixloop:
ldr r0, [r2] /* r0 <- location to fix up, IN FLASH! */
add r0, r0, r9 /* r0 <- location to fix up in RAM */
ldr r1, [r2, #4]
and r7, r1, #0xff
cmp r7, #23 /* relative fixup? */
beq fixrel
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]
add r1, r1, r9
fixnext:
str r1, [r0]
add r2, r2, #8 /* each rel.dyn entry is 8 bytes */
cmp r2, r3
blo fixloop
#endif
#endif
#ifdef CONFIG_ENABLE_MMU
enable_mmu:
/* enable domain access */
ldr r5, =0x0000ffff
mcr p15, 0, r5, c3, c0, 0 /* load domain access register */
/* Set the TTB register */
ldr r0, _mmu_table_base
ldr r1, =CONFIG_SYS_PHY_UBOOT_BASE
ldr r2, =0xfff00000
bic r0, r0, r2
orr r1, r0, r1
mcr p15, 0, r1, c2, c0, 0
/* Enable the MMU */
mrc p15, 0, r0, c1, c0, 0
orr r0, r0, #1 /* Set CR_M to enable MMU */
/* Prepare to enable the MMU */
adr r1, skip_hw_init
and r1, r1, #0x3fc
ldr r2, _TEXT_BASE
ldr r3, =0xfff00000
and r2, r2, r3
orr r2, r2, r1
b mmu_enable
.align 5
/* Run in a single cache-line */
mmu_enable:
mcr p15, 0, r0, c1, c0, 0
nop
nop
mov pc, r2
skip_hw_init:
#endif
clear_bss:
#ifndef CONFIG_SPL_BUILD
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r4, r6 /* reloc addr */
add r0, r0, r4
add r1, r1, r4
mov r2, #0x00000000 /* clear */
clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #4
cmp r0, r1
bne clbss_l
#if (defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
bl coloured_LED_init
bl red_led_on
#endif
#endif
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
#if (defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
#if defined(CONFIG_BOOT_AUTODETECT)
/*check boot status */
#define MEM_CFG_STAT 0x7E00F12C
ldr r1, =MEM_CFG_STAT /* address of reg MEM_CFG_STAT*/
ldr r0, [r1]
mov r1, #0x60
and r1, r0, r1 /*r1 = MEM_CFG_STAT & CFG_BOOT_LOC */
cmp r1, #0x60 /*Internal ROM*/
beq boot_from_irom
cmp r1, #0x00 /*Stepping Stone area in NFCON*/
beq boot_from_nand
b reset
#endif
#if (defined(CONFIG_MMC_SPL) || defined(CONFIG_BOOT_AUTODETECT))
boot_from_irom:
/*TINY6410 boot from Internal ROM-->MMC boot*/
#if defined(CONFIG_TINY6410_LED)
/* R/W, Pull-up disable register */
ldr r1, =ELFIN_GPIO_BASE
ldr r2, =0x11111111
str r2, [r1, #GPKCON0_OFFSET]
ldr r2, =0x0000AAAA
str r2, [r1, #GPKPUD_OFFSET]
ldr r2, =0xAA
str r2, [r1, #GPKDAT_OFFSET]
#endif
b mmc_boot_copy
#endif
#if (defined(CONFIG_NAND_SPL) || defined(CONFIG_BOOT_AUTODETECT))
boot_from_nand:
/*TINY6410 boot from Nand Flash*/
#if defined(CONFIG_TINY6410_LED)
/* R/W, Pull-up disable register */
ldr r1, =ELFIN_GPIO_BASE
ldr r2, =0x11111111
str r2, [r1, #GPKCON0_OFFSET]
ldr r2, =0x0000AAAA
str r2, [r1, #GPKPUD_OFFSET]
ldr r2, =0x55
str r2, [r1, #GPKDAT_OFFSET]
#endif
b nand_boot
#endif
#else
ldr r0, _board_init_r_ofs
adr r1, _start
add lr, r0, r1
add lr, lr, r9
/* setup parameters for board_init_r */
mov r0, r5 /* gd_t */
mov r1, r6 /* dest_addr */
/* jump to it ... */
mov pc, lr
_board_init_r_ofs:
.word board_init_r - _start
_rel_dyn_start_ofs:
.word __rel_dyn_start - _start
_rel_dyn_end_ofs:
.word __rel_dyn_end - _start
_dynsym_start_ofs:
.word __dynsym_start - _start
#endif
#ifdef CONFIG_ENABLE_MMU
_mmu_table_base:
.word mmu_table
#endif
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
/*
* we assume that cache operation is done before. (eg. cleanup_before_linux())
* actually, we don't need to do anything about cache if not use d-cache in
* U-Boot. So, in this function we clean only MMU. by scsuh
*
* void theLastJump(void *kernel, int arch_num, uint boot_params);
*/
#ifdef CONFIG_ENABLE_MMU
.globl theLastJump
theLastJump:
mov r9, r0
ldr r3, =0xfff00000
ldr r4, _TEXT_PHY_BASE
adr r5, phy_last_jump
bic r5, r5, r3
orr r5, r5, r4
mov pc, r5
phy_last_jump:
/*
* disable MMU stuff
*/
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
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
mov r0, #0
mov pc, r9
#endif
/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72
#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52
#define S_IP 48
#define S_FP 44
#define S_R10 40
#define S_R9 36
#define S_R8 32
#define S_R7 28
#define S_R6 24
#define S_R5 20
#define S_R4 16
#define S_R3 12
#define S_R2 8
#define S_R1 4
#define S_R0 0
#define MODE_SVC 0x13
#define I_BIT 0x80
/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
*/
.macro bad_save_user_regs
/* carve out a frame on current user stack */
sub sp, sp, #S_FRAME_SIZE
/* Save user registers (now in svc mode) r0-r12 */
stmia sp, {r0 - r12}
ldr r2, IRQ_STACK_START_IN
/* get values for "aborted" pc and cpsr (into parm regs) */
ldmia r2, {r2 - r3}
/* grab pointer to old stack */
add r0, sp, #S_FRAME_SIZE
add r5, sp, #S_SP
mov r1, lr
/* save sp_SVC, lr_SVC, pc, cpsr */
stmia r5, {r0 - r3}
/* save current stack into r0 (param register) */
mov r0, sp
.endm
.macro get_bad_stack
ldr r13, IRQ_STACK_START_IN @ setup our mode stack
/* save caller lr in position 0 of saved stack */
str lr, [r13]
/* get the spsr */
mrs lr, spsr
/* save spsr in position 1 of saved stack */
str lr, [r13, #4]
/* prepare SVC-Mode */
mov r13, #MODE_SVC
@ msr spsr_c, r13
/* switch modes, make sure moves will execute */
msr spsr, r13
/* capture return pc */
mov lr, pc
/* jump to next instruction & switch modes. */
movs pc, lr
.endm
.macro get_bad_stack_swi
/* space on current stack for scratch reg. */
sub r13, r13, #4
/* save R0's value. */
str r0, [r13]
ldr r13, IRQ_STACK_START_IN @ setup our mode stack
/* save caller lr in position 0 of saved stack */
str lr, [r0]
/* get the spsr */
mrs r0, spsr
/* save spsr in position 1 of saved stack */
str lr, [r0, #4]
/* restore r0 */
ldr r0, [r13]
/* pop stack entry */
add r13, r13, #4
.endm
/*
* exception handlers
*/
.align 5
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction
.align 5
software_interrupt:
get_bad_stack_swi
bad_save_user_regs
bl do_software_interrupt
.align 5
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl do_prefetch_abort
.align 5
data_abort:
get_bad_stack
bad_save_user_regs
bl do_data_abort
.align 5
not_used:
get_bad_stack
bad_save_user_regs
bl do_not_used
.align 5
irq:
get_bad_stack
bad_save_user_regs
bl do_irq
.align 5
fiq:
get_bad_stack
bad_save_user_regs
bl do_fiq
#endif /* CONFIG_NAND_SPL || CONFIG_MMC_SPL */
2.3 修改u-boot-2012.10/include/configs/tiny6410.h, 增加对mmc的支持
/*
* (C) Copyright 2002
* Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Marius Groeger <mgroeger@sysgo.de>
* Gary Jennejohn <garyj@denx.de>
* David Mueller <d.mueller@elsoft.ch>
*
* (C) Copyright 2008
* Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
*
* Configuation settings for the SAMSUNG SMDK6400(mDirac-III) board.
*
* 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
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_S3C6410 1 /* in a SAMSUNG S3C6410 SoC */
#define CONFIG_S3C64XX 1 /* in a SAMSUNG S3C64XX Family */
#define CONFIG_TINY6410 1 /* on a SAMSUNG TINY6410 Board */
#define CONFIG_TINY6410_LED 1
#define CONFIG_PERIPORT_REMAP
#define CONFIG_PERIPORT_BASE 0x70000000
#define CONFIG_PERIPORT_SIZE 0x13
#define CONFIG_SYS_IRAM_BASE 0x0c000000 /* Internal SRAM base address */
#define CONFIG_SYS_IRAM_SIZE 0x2000 /* 8 KB of internal SRAM memory */
#define CONFIG_SYS_IRAM_END (CONFIG_SYS_IRAM_BASE + CONFIG_SYS_IRAM_SIZE)
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_IRAM_END - GENERATED_GBL_DATA_SIZE)
#define CONFIG_SYS_SDRAM_BASE 0x50000000
/* input clock of PLL: SMDK6400 has 12MHz input clock */
#define CONFIG_SYS_CLK_FREQ 12000000
#if !defined(CONFIG_NAND_SPL) && (CONFIG_SYS_TEXT_BASE >= 0xc0000000)
#define CONFIG_ENABLE_MMU
#endif
#if !defined(CONFIG_MMC_SPL) && (CONFIG_SYS_TEXT_BASE >= 0xc0000000)
#define CONFIG_ENABLE_MMU
#endif
#define CONFIG_SETUP_MEMORY_TAGS
#define CONFIG_CMDLINE_TAG
#define CONFIG_INITRD_TAG
/*
* Architecture magic and machine type
*/
#define CONFIG_MACH_TYPE 2520
#define CONFIG_DISPLAY_CPUINFO
#define CONFIG_DISPLAY_BOARDINFO
/*
* Size of malloc() pool
*/
#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 1024 * 1024)
/*
* Hardware drivers
*/
#define CONFIG_CS8900 /* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE 0x18800300
#define CONFIG_CS8900_BUS16 /* follow the Linux driver */
/*
* select serial console configuration
*/
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on SMDK6400 */
#define CONFIG_SYS_HUSH_PARSER /* use "hush" command parser */
#define CONFIG_CMDLINE_EDITING
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/***********************************************************
* Command definition
***********************************************************/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_REGINFO
#define CONFIG_CMD_LOADS
#define CONFIG_CMD_LOADB
#define CONFIG_CMD_SAVEENV
//#define CONFIG_CMD_NAND
//#if defined(CONFIG_BOOT_ONENAND)
//#define CONFIG_CMD_ONENAND
//#endif
#define CONFIG_CMD_PING
#define CONFIG_CMD_ELF
#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_BOOTDELAY 3
#define CONFIG_ZERO_BOOTDELAY_CHECK
#if (CONFIG_COMMANDS & CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CONFIG_SYS_LONGHELP /* undef to save memory */
#define CONFIG_SYS_PROMPT "TINY6410 # " /* Monitor Command Prompt */
#define CONFIG_SYS_CBSIZE 256 /* Console I/O Buffer Size */
#define CONFIG_SYS_PBSIZE 384 /* Print Buffer Size */
#define CONFIG_SYS_MAXARGS 16 /* max number of command args */
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE /* Boot Argument Buffer Size */
#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE /* memtest works on */
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x7e00000) /* 126MB in DRAM */
#define CONFIG_SYS_LOAD_ADDR CONFIG_SYS_SDRAM_BASE /* default load address */
#define CONFIG_SYS_HZ 1000
/**********************************
Support Clock Settings
**********************************
Setting SYNC ASYNC
----------------------------------
667_133_66 X O
533_133_66 O O
400_133_66 X O
400_100_50 O O
**********************************/
#define CONFIG_CLK_667_133_66
/*#define CONFIG_CLK_533_133_66*/
/*
#define CONFIG_CLK_400_100_50
#define CONFIG_CLK_400_133_66
#define CONFIG_SYNC_MODE
*/
/* SMDK6400 has 2 banks of DRAM, but we use only one in U-Boot */
#define CONFIG_NR_DRAM_BANKS 1
#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x10000000 /* 256 MB in Bank #1 */
#define CONFIG_SYS_FLASH_BASE 0x10000000
#define CONFIG_SYS_MONITOR_BASE 0x00000000
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_SYS_MAX_FLASH_BANKS 1 /* max number of memory banks */
/* AM29LV160B has 35 sectors, AM29LV800B - 19 */
#define CONFIG_SYS_MAX_FLASH_SECT 40
#define CONFIG_AMD_LV800
#define CONFIG_SYS_FLASH_CFI 1 /* Use CFI parameters (needed?) */
/* Use drivers/cfi_flash.c, even though the flash is not CFI-compliant */
#define CONFIG_FLASH_CFI_DRIVER 1
#define CONFIG_SYS_FLASH_CFI_WIDTH FLASH_CFI_16BIT
#define CONFIG_FLASH_CFI_LEGACY
#define CONFIG_SYS_FLASH_LEGACY_512Kx16
/* timeout values are in ticks */
#define CONFIG_SYS_FLASH_ERASE_TOUT (5 * CONFIG_SYS_HZ) /* Timeout for Flash Erase */
#define CONFIG_SYS_FLASH_WRITE_TOUT (5 * CONFIG_SYS_HZ) /* Timeout for Flash Write */
#define CONFIG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */
/*
* TINY6410 board specific data
*/
#define CONFIG_IDENT_STRING " for TINY6410"
/* base address for uboot */
#define CONFIG_SYS_PHY_UBOOT_BASE (CONFIG_SYS_SDRAM_BASE + 0x07e00000)
/* total memory available to uboot */
#define CONFIG_SYS_UBOOT_SIZE (1024 * 1024)
/* Put environment copies after the end of U-Boot owned RAM */
#define CONFIG_NAND_ENV_DST (CONFIG_SYS_UBOOT_BASE + CONFIG_SYS_UBOOT_SIZE)
#ifdef CONFIG_ENABLE_MMU
#define CONFIG_SYS_MAPPED_RAM_BASE 0xc0000000
#define CONFIG_BOOTCOMMAND "nand read 0xc0018000 0x60000 0x1c0000;" \
"bootm 0xc0018000"
#else
#define CONFIG_SYS_MAPPED_RAM_BASE CONFIG_SYS_SDRAM_BASE
#define CONFIG_BOOTCOMMAND "nand read 0x50018000 0x60000 0x1c0000;" \
"bootm 0x50018000"
#endif
/* NAND U-Boot load and start address */
#define CONFIG_SYS_UBOOT_BASE (CONFIG_SYS_MAPPED_RAM_BASE + 0x07e00000)
#define CONFIG_ENV_OFFSET 0x0040000
/* NAND configuration */
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x70200010
#define CONFIG_SYS_S3C_NAND_HWECC
#define CONFIG_SYS_NAND_SKIP_BAD_DOT_I 1 /* ".i" read skips bad blocks */
#define CONFIG_SYS_NAND_WP 1
#define CONFIG_SYS_NAND_YAFFS_WRITE 1 /* support yaffs write */
#define CONFIG_SYS_NAND_BBT_2NDPAGE 1 /* bad-block markers in 1st and 2nd pages */
#define CONFIG_SYS_NAND_U_BOOT_DST CONFIG_SYS_PHY_UBOOT_BASE /* NUB load-addr */
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_NAND_U_BOOT_DST /* NUB start-addr */
#define CONFIG_SYS_NAND_U_BOOT_OFFS (4 * 1024) /* Offset to RAM U-Boot image */
#define CONFIG_SYS_NAND_U_BOOT_SIZE (252 * 1024) /* Size of RAM U-Boot image */
/* NAND chip page size */
#define CONFIG_SYS_NAND_PAGE_SIZE 2048
/* NAND chip block size */
#define CONFIG_SYS_NAND_BLOCK_SIZE (128 * 1024)
/* NAND chip page per block count */
#define CONFIG_SYS_NAND_PAGE_COUNT 64
/* Location of the bad-block label */
#define CONFIG_SYS_NAND_BAD_BLOCK_POS 0
/* Extra address cycle for > 128MiB */
#define CONFIG_SYS_NAND_5_ADDR_CYCLE
/* Size of the block protected by one OOB (Spare Area in Samsung terminology) */
#define CONFIG_SYS_NAND_ECCSIZE CONFIG_SYS_NAND_PAGE_SIZE
/* Number of ECC bytes per OOB - S3C6400 calculates 4 bytes ECC in 1-bit mode */
#define CONFIG_SYS_NAND_ECCBYTES 4
/* Size of a single OOB region */
#define CONFIG_SYS_NAND_OOBSIZE 64
/* ECC byte positions */
#define CONFIG_SYS_NAND_ECCPOS {40, 41, 42, 43, 44, 45, 46, 47, \
48, 49, 50, 51, 52, 53, 54, 55, \
56, 57, 58, 59, 60, 61, 62, 63}
/* Boot configuration (define only one of next 3) */
#define CONFIG_BOOT_NAND 0
/* None of these are currently implemented. Left from the original Samsung
* version for reference
#define CONFIG_BOOT_NOR
#define CONFIG_BOOT_MOVINAND
#define CONFIG_BOOT_ONENAND
*/
#define CONFIG_NAND
#define CONFIG_NAND_S3C64XX
/* Unimplemented or unsupported. See comment above.
#define CONFIG_ONENAND
#define CONFIG_MOVINAND
*/
/* Settings as above boot configuration */
#define CONFIG_ENV_IS_IN_NAND 0
#define CONFIG_BOOTARGS "console=ttySAC,115200"
#if !defined(CONFIG_ENABLE_MMU)
#define CONFIG_CMD_USB 1
#define CONFIG_USB_S3C64XX
#define CONFIG_USB_OHCI_NEW 1
#define CONFIG_SYS_USB_OHCI_REGS_BASE 0x74300000
#define CONFIG_SYS_USB_OHCI_SLOT_NAME "s3c6400"
#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 3
#define CONFIG_SYS_USB_OHCI_CPU_INIT 1
#define CONFIG_USB_STORAGE 1
#endif
#define CONFIG_DOS_PARTITION 1
#if defined(CONFIG_USB_OHCI_NEW) && defined(CONFIG_ENABLE_MMU)
# error "usb_ohci.c is currently broken with MMU enabled."
#endif
/* MMC */
#define CONFIG_GENERIC_MMC 1
#define CONFIG_MMC 1
#define CONFIG_S3C64X0_MMC 1
#define CONFIG_CMD_MMC /* MMC support */
#define CONFIG_ENV_IS_IN_MMC 1
#define CONFIG_SYS_MMC_ENV_DEV 0
/* MMC_BOOT */
//#define CONFIG_SYS_MMC_U_BOOT_OFFS (4 * 1024) /* Offset to RAM U-Boot image */
#define CONFIG_SYS_MMC_U_BOOT_SIZE (512 * 1024) /* Size of RAM U-Boot image */
#define MMC_BOOT_CHANNEL 0
#define MMC_INIT_REQUIRED 0
#define TCM_BASE (0x0C004000)
/* size information */
#define BL1_SIZE (8 * 1024)
#define eFUSE_SIZE (1 * 1024) // 0.5k eFuse, 0.5k reserved
/* movinand definitions */
#define MMC_BLKSIZE (512)
#define MMC_TOTAL_BLKCNT (*((volatile unsigned int*)(TCM_BASE - 0x4)))
#define MMC_HIGH_CAPACITY (*((volatile unsigned int*)(TCM_BASE - 0x8)))
#define MMC_UBOOT_POS_BACKWARD (0x300000)
#define MMC_ENV_POS_BACKWARD (0x280000)
#define MMC_BACKGROUND_POS_BACKWARD (0x260000)
#define MMC_UBOOT_POS (MMC_TOTAL_BLKCNT - (MMC_UBOOT_POS_BACKWARD/MMC_BLKSIZE))
#define MMC_ENV_POS (MMC_TOTAL_BLKCNT - (MMC_ENV_POS_BACKWARD/MMC_BLKSIZE))
#define MMC_UBOOT_BLKCNT (CONFIG_SYS_MMC_U_BOOT_SIZE / MMC_BLKSIZE)
#define MMC_ENV_BLKCNT (CONFIG_ENV_SIZE / MMC_BLKSIZE)
#define CONFIG_MMC_ENV_DST (CONFIG_SYS_UBOOT_BASE + CONFIG_SYS_UBOOT_SIZE)
#define CONFIG_SYS_MMC_U_BOOT_DST CONFIG_SYS_PHY_UBOOT_BASE /* NUB load-addr */
#define CONFIG_SYS_MMC_U_BOOT_START CONFIG_SYS_MMC_U_BOOT_DST /* NUB start-addr */
#endif /* __CONFIG_H */
2.4 修改u-boot-2012.10/board/samsung/tiny6410/config.mk, 配置CONFIG_MMC_SPL的TXT_BASE
sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp
ifndef CONFIG_NAND_SPL
ifndef CONFIG_MMC_SPL
CONFIG_SYS_TEXT_BASE = $(RAM_TEXT)
else
CONFIG_SYS_TEXT_BASE = 0
endif
else
CONFIG_SYS_TEXT_BASE = 0
endif
2.5 修改u-boot-2012.10/board/samsung/tiny6410/lowlevel_init.S, 增加对6410和mmc_spl的支持:
/*
* 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>
*
* (C) Copyright 2008
* Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de>
*
* 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 <asm/arch/s3c6400.h>
#ifdef CONFIG_SERIAL1
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART0_OFFSET)
#elif defined(CONFIG_SERIAL2)
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART1_OFFSET)
#else
#define ELFIN_UART_CONSOLE_BASE (ELFIN_UART_BASE + ELFIN_UART2_OFFSET)
#endif
_TEXT_BASE:
.word CONFIG_SYS_TEXT_BASE
.globl lowlevel_init
lowlevel_init:
mov r12, lr
/* 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) */
mvn r3, #0x0
str r3, [r0, #oINTMSK]
str r3, [r1, #oINTMSK]
/* Set all interrupts as 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
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
/* for UART */
bl uart_asm_init
#endif
#ifdef CONFIG_BOOT_NAND
/* simple init for NAND */
bl nand_asm_init
#endif
/* Memory subsystem address 0x7e00f120 */
ldr r0, =ELFIN_MEM_SYS_CFG
/* Xm0CSn2 = NFCON CS0, Xm0CSn3 = NFCON CS1 */
mov r1, #S3C64XX_MEM_SYS_CFG_NAND
str r1, [r0]
#if defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL)
bl mem_ctrl_asm_init
#endif
/* Wakeup support. Don't know if it's going to be used, untested. */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + RST_STAT_OFFSET)
ldr r1, [r0]
bic r1, r1, #0xfffffff7
cmp r1, #0x8
beq wakeup_reset
1:
mov lr, r12
mov pc, lr
wakeup_reset:
/* Clear wakeup status register */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + WAKEUP_STAT_OFFSET)
ldr r1, [r0]
str r1, [r0]
/* Load return address and jump to kernel */
ldr r0, =(ELFIN_CLOCK_POWER_BASE + INF_REG0_OFFSET)
/* r1 = physical address of s3c6400_cpu_resume function */
ldr r1, [r0]
/* Jump to kernel (sleep-s3c6400.S) */
mov pc, r1
nop
nop
/*
* system_clock_init: Initialize core clock and bus clock.
* void system_clock_init(void)
*/
system_clock_init:
ldr r0, =ELFIN_CLOCK_POWER_BASE /* 0x7e00f000 */
#ifdef CONFIG_SYNC_MODE
ldr r1, [r0, #OTHERS_OFFSET]
mov r2, #0x40
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]
nop
nop
nop
nop
nop
ldr r2, =0x80
orr r1, r1, r2
str r1, [r0, #OTHERS_OFFSET]
check_syncack:
ldr r1, [r0, #OTHERS_OFFSET]
ldr r2, =0xf00
and r1, r1, r2
cmp r1, #0xf00
bne check_syncack
#else /* ASYNC Mode */
nop
nop
nop
nop
nop
/*
* This was unconditional in original Samsung sources, but it doesn't
* seem to make much sense on S3C6400.
*/
#if !defined(CONFIG_S3C6400) && !defined(CONFIG_S3C6410)
ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0xC0
orr r1, r1, #0x40
str r1, [r0, #OTHERS_OFFSET]
wait_for_async:
ldr r1, [r0, #OTHERS_OFFSET]
and r1, r1, #0xf00
cmp r1, #0x0
bne wait_for_async
#endif
ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0x40
str r1, [r0, #OTHERS_OFFSET]
#endif
mov r1, #0xff00
orr r1, r1, #0xff
str r1, [r0, #APLL_LOCK_OFFSET]
str r1, [r0, #MPLL_LOCK_OFFSET]
/* Set Clock Divider */
ldr r1, [r0, #CLK_DIV0_OFFSET]
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]
/* FOUT of EPLL is 96MHz */
/*
ldr r1, =0x200203
str r1, [r0, #EPLL_CON0_OFFSET]
*/
ldr r1, =0x0
str r1, [r0, #EPLL_CON1_OFFSET]
ldr r1, =0x80200103 /* FOUT of EPLL is 48MHz , enable it for MMC*/
str r1, [r0, #EPLL_CON0_OFFSET]
/* APLL, MPLL, EPLL select to Fout */
ldr r1, [r0, #CLK_SRC_OFFSET]
orr r1, r1, #0x7
str r1, [r0, #CLK_SRC_OFFSET]
/* wait at least 200us to stablize all clock */
mov r1, #0x10000
1: subs r1, r1, #1
bne 1b
/* Synchronization for VIC port */
#if defined(CONFIG_SYNC_MODE)
ldr r1, [r0, #OTHERS_OFFSET]
orr r1, r1, #0x20
str r1, [r0, #OTHERS_OFFSET]
#elif !defined(CONFIG_S3C6400) && !defined(CONFIG_S3C6410)
/* According to 661558um_S3C6400X_rev10.pdf 0x20 is reserved */
ldr r1, [r0, #OTHERS_OFFSET]
bic r1, r1, #0x20
str r1, [r0, #OTHERS_OFFSET]
#endif
mov pc, lr
#if !(defined(CONFIG_NAND_SPL) || defined(CONFIG_MMC_SPL))
/*
* uart_asm_init: Initialize UART's pins
*/
uart_asm_init:
/* set GPIO to enable UART */
ldr r0, =ELFIN_GPIO_BASE
ldr r1, =0x220022
str r1, [r0, #GPACON_OFFSET]
mov pc, lr
#endif
#ifdef CONFIG_BOOT_NAND
/*
* NAND Interface init for SMDK6400
*/
nand_asm_init:
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, #0x07
str r1, [r0, #NFCONT_OFFSET]
mov pc, lr
#endif
#ifdef CONFIG_ENABLE_MMU
/*
* MMU Table for TINY6410
*/
/* 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
3. 编译、烧写
[wf@localhost u-boot-2012.10]$ make tiny6410_mmc_config
Makefile:783: warning: overriding recipe for target `tiny6410_noUSB_config'
Makefile:769: warning: ignoring old recipe for target `tiny6410_noUSB_config'
Makefile:783: warning: overriding recipe for target `tiny6410_noUSB_config'
Makefile:769: warning: ignoring old recipe for target `tiny6410_noUSB_config'
warning: Please migrate to boards.cfg. Failure to do so will
mean removal of your board in the next release.
Configuring for tiny6410 board...
[wf@localhost u-boot-2012.10]$ make
编译成功,在u-boot-2012.10目录生成u-boot.bin文件
在u-boot-2012.10/mmc_spl目录生成u-boot-spl-16k.bin文件
然后使用dd命令分别将u-boot-spl-16k.bin和u-boot.bin拷到sd卡的BL1和BL2, 我使用的SDHC卡(8GB), BL1代码应该拷贝到 -1024 - 18 block, BL2拷到-1024 - 6144 block, 由于要经常烧写,会频繁用来dd命令,制作一个bash脚本程序来完成:
[wf@localhost u-boot-2012.10]$ gedit burnsd.sh
echo "copying u-boot-spl-16k.bin to sd card..."
sudo dd iflag=dsync oflag=dsync if=mmc_spl/u-boot-spl-16k.bin of=/dev/sdb seek=15522798 bs=512
echo "copying u-boot.bin to sd card..."
sudo dd iflag=dsync oflag=dsync if=u-boot.bin of=/dev/sdb seek=15516672 bs=512
用chmod命令给burnsd.sh脚本赋予执行权限:
运行burnsd.sh脚本,将程序写入sd卡:
[root@localhost u-boot-2012.10]# ./burnsd.sh
copying u-boot-spl-16k.bin to sd card...
8+0 records in
8+0 records out
4096 bytes (4.1 kB) copied, 0.119196 s, 34.4 kB/s
copying u-boot.bin to sd card...
411+1 records in
411+1 records out
210668 bytes (211 kB) copied, 10.0554 s, 21.0 kB/s
4. 测试
将sd卡插入tiny6410开发板,开关拨到SDBOOT, 上电,串口打印如下:
U-Boot 2012.10 (Apr 14 2020 - 20:02:02) for TINY6410
CPU: S3C6400@667MHz
Fclk = 667MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6400
DRAM: 256 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###
原因为Flash初始化失败, 程序进入hang()函数无限循环了。
编辑arch/arm/lib/board.c,屏蔽掉hang()函数。
# endif /* CONFIG_SYS_FLASH_CHECKSUM */
} else {
puts(failed);
//hang();
printf("\r\nPlease check codes for flash...\r\n");
}
#endif
重新编译并烧写,重启开发板,串口打印信息如下:
U-Boot 2012.10 (Apr 17 2020 - 21:36:21) for TINY6410
CPU: S3C6400@667MHz
Fclk = 667MHz, Hclk = 133MHz, Pclk = 66MHz (ASYNC Mode)
Board: SMDK6400
DRAM: 256 MiB
WARNING: Caches not enabled
Flash: *** failed ***
Please check codes for flash...
MMC:
MMC Device 0 not found
No MMC card found
Using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
Hit any key to stop autoboot: 0
Unknown command 'nand' - try 'help'
Wrong Image Format for bootm command
ERROR: can't get kernel image!
TINY6410 # mmcinfo
No MMC device available
TINY6410 #
命令提示符TINY6410 #出现,u-boot的基本移植完成。后面需要增加mmc、dm9000、lcd的支持。