U-boot-2008-10之支持nand flash驱动
?U-Boot版本:U-boot 2008.10?? 目标板:Mini2440 ??Nandflash型号:?K9F1G08U0B??256M? ? ? ?
?
修改include/configs/mini2440.h。
1)添加命令支持:
#define CONFIG_CMD_ELF
#define ?CONFIG_CMD_NAND
2)添加nand flash 参数设置:
/*nand flashsettings******************************************************************************************/
#define CFG_NAND_BASE ????????????????????? 0? ?/*Nand?Flash控制器在SFR区起始寄存器地址*/
#define CFG_MAX_NAND_DEVICE????????????????? 1 ? ? /*NAND?Flash设备最大数*/
#define NAND_MAX_CHIPS ??????????????????? 1? ???????????? /*NAND?Flash芯片数*/
#define SECTORSIZE ???????????????????????????????? ?2048?? ?/*扇区容量2K Bytes*/
#define ADDR_COLUMN ????????????????????????? 2/*2Byte Column address*/
#define ADDR_PAGE ?????????????????????????????? 3??? //3字节的页块地址
#define ADDR_COLUMN_PAGE???????? 4?????? //总共4字节的页块地址
#define NAND_ChipID_UNKNOWN ?????0x00??? //未知芯片的ID号
#define NAND_MAX_FLOORS ???????????????? 4??????
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
?
说明:此版的u-boot已自带board_nand_init(),在cpu/arm920t/s3c24x0/nand.c中定义。
因为s3c2410和s3c2440在flash控制器上,有所差别,驱动代码需要改进,主要修改在cpu/arm920t/s3c24x0/nand.c中进行。
cpu/arm920t/s3c24x0/nand.c中修改过程:
先加入 S3C2440 NANDflash 控制器的地址定义,修改后如下:
``````
#if ndef(CONFIG_S3C2440)???????????????? //针对S3C2410这款SOC
#define NF_BASE??? 0x4e000000
#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)
#else?????????????????????????????????????????????????????????????????????????????????? //S3C2440与S3C2410不太一样
#define NF_BASE??? 0x4e000000
#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 S3C2440_NFCONT_nCE? (1<<1)?????????

????
#define S3C2440_ADDR_NALE????? 0x0c
#define S3C2440_ADDR_NCLE????? 0x08
#endif
?
``````
U-Boot.2008.10自带的s3c2410的s3c2410的s3c2410_hwcontrol函数有错。在此函数中,把chip->IO_ADDR_W的值改写了,导致在写数据时出现错误,解决办法是使用一全局变量代替chip->IO_ADDR_W。在s3c2410_hwcontrol函数的上一行定义这个全局变量,然后修改s3c2410_hwcontrol函数,让它支持S3C2440,修改该后如下:
````
ulong IO_ADDR_W =NF_BASE;
static void s3c2410_hwcontrol(structmtd_info *mtd,int cmd,unsigned int ctrl)
{
struct nand_chip *chip = mtd->priv;
DEBUGN("hwcontrol(): 0x%02x 0x%02xn",cmd,ctrl);
/*modified by xxx,for 2440*********************************************************/
#if !defined(CONFIG_S3C2440)
if (ctrl & NAND_CTRL_CHANGE) {
/*modified by xxx,for2440*********************************************************/
/*ulong IO_ADDR_W = NF_BASE;*/ /*delete ulong,by xxx ********/
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;*/ ?/*BUG,delete byxxx******/
if (ctrl & NAND_NCE)
NFCONF &= ~S3C2410_NFCONF_nFCE;
else
NFCONF |= S3C2410_NFCONF_nFCE;
}
if (cmd != NAND_CMD_NONE)
/*writeb(cmd,chip->IO_ADDR_W);*/ ? /*modified by xxx************/
writeb(cmd,(void *)chip->IO_ADDR_W);
#else
if (ctrl & NAND_CTRL_CHANGE) {
? ?IO_ADDR_W = NF_BASE;
if (!(ctrl & NAND_CLE))
IO_ADDR_W |= S3C2440_ADDR_NALE;
if (!(ctrl & NAND_ALE))
IO_ADDR_W |= S3C2440_ADDR_NCLE;
/*chip->IO_ADDR_W = (void *)IO_ADDR_W;*/ ?/*BUG,delete by xxx******/
if (ctrl & NAND_NCE)
NFCONT &= ~S3C2440_NFCONT_nCE;/*Becareful there is NFCONT**********/
else
NFCONT |= S3C2440_NFCONT_nCE;
}
if (cmd != NAND_CMD_NONE)
/*writeb(cmd,(void *)IO_ADDR_W);
#endif
}
board_nand_init修改后如下:
····
clk_power->CLKCON |= (1 << 4);
/*add by xxx,for 2440******************************************************/
#if !defined(CONFIG_S3C2440)
DEBUGN("CONFIG_S3C2410n");
/* initialize hardware */
twrph0 = 3; twrph1 = 0; tacls = 0;
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls- 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0- 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1- 1);
NFCONF = cfg;
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e00000c;
/* 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;
#else
DEBUGN("CONFIG_S3C2440n");
/* initialize hardware */
twrph0 = 4; twrph1 = 2; tacls = 0; ?/*modified by dazhi,for 2440*****/
/*modified by xxx,for 2440*************************************************/
cfg =(tacls <<12)|(twrph0<<8)|(twrph1<<4);
NFCONF=cfg;
cfg =(1 <<6)|(1<<4)|(0<<1)|(1<<0);
NFCONT=cfg;
/* initialize nand_chip data structure */
nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)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;
#endif
为了显示芯片型号,将 ?drivers/mtd/nand/nand_base.c中的nand_get_flash_type函数结尾,修改MTDDEBUG为printf。
在NAND FLASH中保存u-boot 参数,(saveenv功能)
/include/configs/mini2440.h添加:
`````
#define CONFIG_CMD_NAND
#define CONFIG_CMD_ENV
`````
/*#define CONFIG_ENV_IS_IN_FLASH ? ? ?? 1?*/
#define CONFIG_ENV_IS_IN_NAND ?????????????? 1
#define? CONFIG_ENV_OFFSET?????????????????????? 0x40000/*参数在nand flash中的起始位置位256K*/
#define ?CONFIG_ENV_SIZE????????????????????????????? 0x20000 /*环境变量总大小,128K*/
保存,在Uboot根目录下先清除make? clean下,然后make,下载测试。
注:中间可能会出现宏未定义的错误,或者redifined 宏。对于这些错误,没办法,得挨个修改,这是调试技术。
出错的宏最好在 u-boot-2008-10/include/configs/mini2440.h里修改,针对本开发板的软硬件配置modify,避免修改参数范围太大,难于控制。比如CONFIG_NAND_BASE为CFG_NAND_BASE。
?
下载NAND FLASH移植测试:
????将编译好的u-boot.bin通过JTAG烧入Mini2440开发板,重启开发板可以看到:

显示的信息中存在一个 bad CRC的警告信息,这是由于在启动时,uboot会从flash中读取环境变量的信息,通常执行save或saveenv后,下次启动就不会出现此警告了。
????在u-boot界面,输入“?nand”命令,查看nand相关的用法:
Jz2440 # ? nand

????可以看到一系列nand read、nand write命令,以及命令的使用方法。
?
1.擦除NAND FLASH测试
????在u-boot界面输入nand erase 0 1000:

????命令解释:擦除NAND FLASH偏移0个地址后的4K内容(0x1000)
?
2.读NAND FLASH测试
????在u-boot界面输入nand read 30000000 0 1000:

????命令解释:读NAND FLASH偏移0个地址大小为4K的内容(0x1000),放到内存的0x30000000处
????在u-boot界面使用md命令查看内存内容:

????可以看到,内存0x30000000处全是f,说明nand read读到的是上一步擦除后NAND FLASH上的内容,说明上一步擦除NAND FLASH成功,本次读操作也OK。
?
3.写NAND FLASH测试