搬移BL2代码
在完成了BL1部分的初始化后,start.S会跳转到nand_spl/board/samsung/smdk6410/nand_boot.c 中的nand_boot函数,将NAND中BL2阶段的代码复制到RAM中。不过原版的nand_boot函数跟OK6410的NAND无法兼容,搬移功能不可用。本想修改一下的,但是没深入学习过NAND,ECC校检部分实在没看懂…所以就把OK6410原版中的搬移代码拿过来用好了。
添加nand_cp.c文件
在OK6410原版1.1.6uboot代码的\cpu\s3c64xx目录下找到nand_cp.c文件,拷贝到nand_spl/board/samsung/smdk6410/下。修改Makefile,添加新的编译目标:
COBJS = nand_boot.o nand_ecc.o s3c64xx.o nand_cp.o
这个原版的拷贝代码是直接写死了拷贝区域,需要进行修改使其达到可以按照NAND基地址,RAM基地址文件,拷贝大小三个参数进行传参的。代码如下:
#include <common.h>
#include <asm/io.h>
#include <linux/mtd/nand.h>
#include <asm/arch/s3c6410.h>
/*
* address format
* 17 16 9 8 0
* --------------------------------------------
* | block(12bit) | page(5bit) | offset(9bit) |
* --------------------------------------------
*/
#define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
#define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
static int nandll_read_page (uchar *buf, ulong addr, int large_block)
{
int i;
int page_size = 512;
if (large_block==1)
page_size = 2048;
if (large_block==2)
page_size = 4096;
if(large_block==3)
page_size = 8192;
NAND_ENABLE_CE();
NFCMD_REG = NAND_CMD_READ0;
/* Write Address */
NFADDR_REG = 0;
if (large_block)
NFADDR_REG = 0;
NFADDR_REG = (addr) & 0xff;
NFADDR_REG = (addr >> 8) & 0xff;
NFADDR_REG = (addr >> 16) & 0xff;
if (large_block)
NFCMD_REG = NAND_CMD_READSTART;
NF_TRANSRnB();
/* for compatibility(2460). u32 cannot be used. by scsuh */
for(i=0; i < page_size; i++) {
*buf++ = NFDATA8_REG;
}
NAND_DISABLE_CE();
return 0;
}
/*
* Read data from NAND.
*/
static int nandll_read_blocks (ulong nand_addr, ulong dst_addr, ulong size, int large_block)
{
uchar *buf = (uchar *)dst_addr;
int i, nand_kb;
uint page_shift = 9;
if (large_block==1)
page_shift = 11;
if(large_block==2)
page_shift = 12;
if(large_block==3)
page_shift =13;
nand_kb= nand_addr / 1024;
if(large_block == 2)
{
if(nand_kb < 8) //要读取的NAND地址小于8K
{ /* Read pages */
for (i = nand_kb/2; i < 4; i++, buf+=(1<<(page_shift-1))) {
nandll_read_page(buf, i, large_block);
}
/* Read pages */
for (i = 4; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
else
{
/* Read pages */
for (i = 4+(nand_kb-8)/4; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
}else if(large_block == 3) //K9GAG08U0E
{
/* Read pages */
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-2))) {
nandll_read_page(buf, i, large_block);
}
/* Read pages */
for (i = 4; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
else
{
for (i = 0; i < (size>>page_shift); i++, buf+=(1<<page_shift)) {
nandll_read_page(buf, i, large_block);
}
}
return 0;
}
int copy_uboot_to_ram (unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
int large_block = 0;
int i;
vu_char id;
NAND_ENABLE_CE();
NFCMD_REG=NAND_CMD_RESET;
NF_TRANSRnB();
NFCMD_REG = NAND_CMD_READID;
NFADDR_REG = 0x00;
NF_TRANSRnB();
/* wait for a while */
for (i=0; i<200; i++);
int factory = NFDATA8_REG;
id = NFDATA8_REG;
int cellinfo=NFDATA8_REG;
int tmp= NFDATA8_REG;
//int childType=tmp & 0x03; //Page size
int childType=cellinfo; //Page size
if (id > 0x80)
{
large_block = 1;
}
if(id == 0xd5 && childType==0x94 )//K9GAG08U0D
{
large_block = 2;
}
if(id == 0xd5 && childType==0x14 )//K9GAG08U0M
{
large_block = 2;
}
if(id == 0xd5 && childType==0x84 )//K9GAG08U0E
{
large_block = 3;
}
if(id==0xd7)//K9LBG08U0D
{
large_block = 2;
}
if(factory==0x2c && id == 0x48) //MT29F16G08ABACAWP
{
large_block = 2;
}if(factory==0x2c && id == 0x38) //MT29F8G08ABABAWP
{
large_block = 2;
}
//smdk6410 1G+256M版本 large_block = 2;
/* read NAND Block. 0x3c000
*/
return nandll_read_blocks(nand_start, ddr_start, len, large_block);
}
#if 1
#define REG_GPFCON (0x7F0080A0)
#define REG_GPFDAT (0x7F0080A4)
void beep(void)
{
uint reg_f_cfg=readl(REG_GPFCON) & 0x3FFFFFFF | (1<<30);
writel(reg_f_cfg,REG_GPFCON);
uint reg_f_on=readl(REG_GPFDAT) & 0xFFFF7FFF | (1<<15);
uint reg_f_off=readl(REG_GPFDAT) & 0xFFFF7FFF;
writel(reg_f_on,REG_GPFDAT);
}
#else
void beep(void)
{
}
#endif
修改nand_boot.c文件
修改完nand的拷贝函数后,将nand_boot.c文件中原来的启动代码:
ret = nand_load(&nand_info, CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_SIZE,
(uchar *)CONFIG_SYS_NAND_U_BOOT_DST);
#ifdef CONFIG_NAND_ENV_DST
nand_load(&nand_info, CONFIG_ENV_OFFSET, CONFIG_ENV_SIZE,
(uchar *)CONFIG_NAND_ENV_DST);
#endif
替换为:
copy_uboot_to_ram(CONFIG_SYS_NAND_U_BOOT_OFFS, CONFIG_SYS_NAND_U_BOOT_DST,
CONFIG_SYS_NAND_U_BOOT_SIZE);
#ifdef CONFIG_NAND_ENV_DST
copy_uboot_to_ram(CONFIG_ENV_OFFSET, CONFIG_NAND_ENV_DST,
CONFIG_ENV_SIZE);
#endif
同时在lowleveinit.S和cpu_init.S中NAND初始化部分按照原版1.1.6的初始代码修改对应smdk6410.h中的宏。
重新编译后,烧录u-boot-nand.bin到开发版上,重启后就可以看见串口输出了。
存在缺陷
虽然串口终于有打印了,但还存在很多缺陷:
- 默认是cs8900的网卡驱动,需要移植OK6410使用DM9000网卡驱动
- nand虽然已能正常搬移,但是进入BL2后使用的仍是默认的NAND驱动,无法操作NAND,需要进一步修改
- 暂未添加zImage支持,无法引导zImage的Linux镜像