基于U-BOOT-2010.09移植OK6410开发版记录(三)

本文介绍如何在完成BL1部分初始化后,通过修改nand_boot函数将BL2阶段的代码从NAND复制到RAM中。由于原版函数与OK6410 NAND不兼容,文中采用OK6410原版的搬移代码,并进行了必要的调整。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搬移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镜像
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值