u-boot-2012.10移植(二)MMC启动

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提供了启动设备的复制函数:
Device Copy Function Pointer
Definition MMC Block Copy Function
根据手册,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的总块数。

mmcexample

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.bin
在u-boot-2012.10/mmc_spl目录生成u-boot-spl-16k.bin文件
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
运行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的支持。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
u-boot-2016.11.tar.bz2是一个开源软件项目的压缩文件。该压缩文件是u-boot引导加载程序的源代码和相关文件的打包形式。u-boot(Universal Bootloader)是一款用于嵌入式系统的开源引导加载程序,用于初始化硬件并启动操作系统。 u-boot-2016.11.tar.bz2文件的扩展名.tar.bz2表示它是使用tar和bzip2两种工具进行压缩的。.tar是一个常用的文件打包工具,它可以将多个文件和目录打包成一个文件。.bz2是一个压缩工具,可以将文件进行高效压缩。 要使用u-boot-2016.11.tar.bz2文件,首先需要将其解压缩。可以使用tar命令进行解压缩,命令为tar -xjf u-boot-2016.11.tar.bz2。这将解压缩文件,并将源代码和其他相关文件提取到当前目录下。 解压缩后,可以在提取出的文件中找到u-boot引导加载程序的源代码和相关文件。可以根据需要进行定制和编译,生成适合特定硬件平台的引导加载程序。u-boot支持多种处理器架构和开发板,可以根据需要进行配置。 根据u-boot-2016.11.tar.bz2文件的版本号来看,它是2016年11月发布的版本。这意味着该版本已经存在一段时间,并可能具有稳定性和经过验证的特性。对于需要使用u-boot的开发者和嵌入式系统制造商,这个版本可以作为一个可靠的基础进行开发和定制。 总之,u-boot-2016.11.tar.bz2是u-boot引导加载程序的源代码和相关文件的压缩包。解压缩后,可以通过定制和编译源代码,生成适合特定硬件平台的引导加载程序。这个版本已经存在一段时间,并可能具有可靠的特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值