您的位置:首页 > 运维架构 > 网站架构

FL2440的U-boot-2009.08移植(五)uboot架构中NAND Flash驱动修改

2015-10-24 12:32 639 查看
移植NAND花了我一下午的时间才把他弄明白,解决错误的途中,我也学到了更多的东西,希望大家自己要尝试亲手移植,不要老是用别人的补丁文件,自己你懂手做了才真正是你的东西。



分析了一下Uboot中Nandflash的驱动,u-boot-2009.08使用的是和Linux内核一样的MTD(内存技术设备)架构。在Uboot下对Nand的支持体现在命令行下实现对nand flash的操作,为:nand info,nand device,nand read,nand write,nand erease,nand
bad。用到的主要数据结构有:struct nand_flash_dev,struct nand_chip。前者包括主要的芯片型号,存储容量,设备ID,I/O总线宽度等信息;后者是具体对nand flash进行操作时用到的信息。

u-boot启动到第二个阶段后,在/cpu/arm920t/board.c这个文件中start_armboot函数里,有下面的代码:

#if defined(CONFIG_CMD_NAND)

puts ("NAND: ");

nand_init(); /* go init the NAND */

#endif

所以,我们只要定义了CONFIG_CMD_NAND这个宏,就会开始nand初始化。通过用Source Insight来做代码分析来一步步地查看函数执行过程,得出下面的nand执行流程:

1./cpu/arm920t/board.c文件中的start_armboot函数调用/drivers/mtd/nand/nand.c文件中的nand_init函数;

2.nand_init调用同文件下的nand_init_chip函数;

3.nand_init_chip函数调用/drivers/mtd/nand/s3c2410_nand.c文件下的board_nand_init函数,然后再调用/drivers/mtd/nand/nand_base.c函数中的nand_scan函数;

4.s3c2410_nand.c就是我们做移植需要实现的文件,是与具体的硬件密切相关的。

5.nand_scan函数会调用同文件下的nand_scan_ident等函数。

从这里我们得知,我们要把nand移植到2440上,就要修改s3c2410_nand.c这个文件!因为对nand flash的操作,实际上就是对nand控制器的操作,而2440的nand控制器和2410相比,有很大的不同!我们的修改工作量主要也是在这里。在这里我就在源文件上修改了。

首先在include/configs/fl2440.h中相应位置增加必要的宏定义:

#define CONFIG_CMD_NAND

/* NAND flash settings */

#if defined(CONFIG_CMD_NAND)

#define CONFIG_SYS_NAND_BASE 0x4E000000

#define CONFIG_SYS_MAX_NAND_DEVICE 1

#define CONFIG_MTD_NAND_VERIFY_WRITE 1

#define NAND_SAMSUNG_LP_OPTIONS 1 /*注意,这个定义很重要,因为我们用的是大块nand!! */

#undef CONFIG_ENV_IS_IN_FLASH

#define CONFIG_ENV_IS_IN_NAND 1 /* 环境变量的保存位置 */

#endif

修改/drivers/mtd/nand/Makefile,在其中添加:

COBJS-y
+= s3c2410_nand.o

COBJS-$(CONFIG_NAND_S3C2440) += s3c2410_nand.o
下面的工作主要是修改drivers/mtd/nand/s3c2410_nand.c文件,首先修改27行如下

#if 0

#define NFCONF __REGi(NF_BASE + 0x0)

#define NFCMD __REGb(NF_BASE + 0x4)

#define NFADDR __REGb(NF_BASE + 0x8)

#define NFDATA __REGb(NF_BASE + 0xc)

#define NFSTAT __REGb(NF_BASE + 0x10)

#define NFECC0 __REGb(NF_BASE + 0x14)

#define NFECC1 __REGb(NF_BASE + 0x15)

#define NFECC2 __REGb(NF_BASE + 0x16)

#endif

#define NFCONF __REGi(NF_BASE + 0x0)

#define NFCONT __REGi(NF_BASE + 0x4)

#define NFCMD __REGb(NF_BASE + 0x8)

#define NFADDR __REGb(NF_BASE + 0xc)

#define NFDATA __REGb(NF_BASE + 0x10)

#define NFMECCD0 __REGi(NF_BASE + 0x14)

#define NFMECCD1 __REGi(NF_BASE + 0x18)

#define NFSECCD __REGi(NF_BASE + 0x1C)

#define NFSTAT __REGb(NF_BASE + 0x20)

#define NFSTAT0 __REGi(NF_BASE + 0x24)

#define NFSTAT1 __REGi(NF_BASE + 0x28)

#define NFMECC0 __REGi(NF_BASE + 0x2C)

#define NFMECC1 __REGi(NF_BASE + 0x30)

#define NFSECC __REGi(NF_BASE + 0x34)

#define NFSBLK __REGi(NF_BASE + 0x38)

#define NFEBLK __REGi(NF_BASE + 0x3c)

修改下面的宏:

#define S3C2410_NFCONF_EN (1<<15)

#define S3C2410_NFCONF_512BYTE (1<<14)

#define S3C2410_NFCONF_4STEP (1<<13)

#define S3C2410_NFCONF_INITECC (1<<12)

#define S3C2410_NFCONF_nFCE (1<<11)

#define S3C2410_NFCONF_TACLS(x) ((x)<<8)

#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4)

#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0)

#define S3C2410_ADDR_NALE 4

#define S3C2410_ADDR_NCLE 8

uboot代码中的NAND Flash的读写驱动中存在一些错误,需要进行修改后才能完成,主要修改drivers/mtd/nand/s3c2410_nand.c文件,首先修改27行如下:

修改s3c2410_hwcontrol函数 ,这个函数用来控制发送命令还是地址。board_nand_init函数。

首先声明一个全局变量 ulong IO_ADDR_W = NF_BASE;

#ifdef CONFIG_S3C2410_NAND_HWECC //这个宏没有定义,所以我们不用关心ECC之类的。

ulong
IO_ADDR_W = NF_BASE;

static void s3c2410_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)

{

struct nand_chip *chip = mtd->priv;

DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

if (ctrl & NAND_CTRL_CHANGE) {

ulong IO_ADDR_W = NF_BASE;

IO_ADDR_W = NF_BASE;

if (!(ctrl & NAND_CLE))

IO_ADDR_W |= S3C2410_ADDR_NCLE;

if (!(ctrl & NAND_ALE))

IO_ADDR_W |= S3C2410_ADDR_NALE;

//chip->IO_ADDR_W = (void *)IO_ADDR_W;





#if defined(CONFIG_S3C2440)

if (ctrl & NAND_NCE)

NFCONT&= ~S3C2410_NFCONT_nFCE; //源码中是NFCONF,S3C2410_NFCONF_nFCE



else

NFCONT|=
S3C2410_NFCONT_nFCE; //源码中是NFCONF,S3C2410_NFCONF_nFCE

#endif

}

if (cmd != NAND_CMD_NONE)

// writeb(cmd, chip->IO_ADDR_W);

writeb(cmd, (void *)IO_ADDR_W);

}

int board_nand_init(struct nand_chip *nand)

{

u_int32_t cfg;

u_int8_t tacls, twrph0, twrph1;

S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();

DEBUGN("board_nand_init()\n");

clk_power->CLKCON |= (1 << 4);
/* initialize hardware */

twrph0 = 0; twrph1 = 4; tacls = 2;

cfg = 0;

cfg |= S3C2410_NFCONF_TACLS(tacls - 1);

cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);

cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);

NFCONF = cfg;

cfg = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(0<<1)|(1<<0);

NFCONT = cfg;
* initialize nand_chip data structure */

nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010; //NFSTAT 的地址是0x4e000010

/* read_buf and write_buf are default */

/* read_byte and write_byte are default */

/* hwcontrol always must be implemented */

nand->cmd_ctrl = s3c2410_hwcontrol;

nand->dev_ready = s3c2410_dev_ready;
/*以下是校验码的设置,可以不用设置*/

#ifdef CONFIG_S3C2410_NAND_HWECC

nand->ecc.hwctl = s3c2410_nand_enable_hwecc;

nand->ecc.calculate = s3c2410_nand_calculate_ecc;

nand->ecc.correct = s3c2410_nand_correct_data;

nand->ecc.mode = NAND_ECC_HW3_512;

#else

nand->ecc.mode = NAND_ECC_SOFT;

#endif

ifdef CONFIG_S3C2410_NAND_BBT

nand->options = NAND_USE_FLASH_BBT;

#else

nand->options = 0;

#endif

DEBUGN("end of nand_init\n");

return 0;

}

突然发现我自己都爱上了自己的执着精神,哈哈,回去吃完饭了。
参考地址:http://blog.csdn.net/yanghao23/article/details/7700699
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: