1、在u-boot-2016.05\drivers\mtd\nand文件夹中拷贝一份s3c2410_nand.c并重命名s3c2440_nand.c。那么如何决定将s3c2440_nand.c和s3c2410_nand.c哪个编译进程序?
首先在u-boot-2016.05\include\configs\smdk2440.h中将
/*
* NAND configuration
*/
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE 0x4E000000
#endif
中的
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
改为
#ifdef CONFIG_S3C2410
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif
然后,在u-boot-2016.05\drivers\mtd\nand\Makefile文件中的
obj-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
之后添加一项
obj-$(CONFIG_NAND_S3C2440) += s3c2440_nand.o
因为宏定义了CONFIG_NAND_S3C2440而没宏定义CONFIG_NAND_S3C2410,所以,这样编译进u-boot就是s3c2440_nand.c文件。
2、在u-boot-2016.05\drivers\mtd\nand\s3c2440_nand.c:board_nand_init函数中用
/* 设置时序 */
cfg = ((tacls-1)<<12)|((twrph0-1)<<8)|((twrph1-1)<<4);
替换
cfg = S3C2410_NFCONF_EN;
cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
紧接着后面添加
/* 使能NAND Flash控制器, 初始化ECC, 禁止片选 */
writel((1<<4)|(1<<1)|(1<<0), &nand_reg->nfcont);
再用
nand->select_chip = s3c2440_nand_select;
替换
nand->select_chip = NULL;
然后在board_nand_init函数前边添加片选函数s3c2440_nand_select:
static void s3c2440_nand_select(struct mtd_info *mtd, int chipnr)
{
struct s3c24x0_nand *nand = s3c24x0_get_base_nand();
switch (chipnr) {
case -1: /*取消选中*/
nand->nfcont |= (1<<1);
break;
case 0: /*选中*/
nand->nfcont &= ~(1<<1);
break;
default:
BUG();
}
}
3、在u-boot-2016.05\drivers\mtd\nand\s3c2440_nand.c:s3c24x0_hwcontrol函数中删掉
struct nand_chip *chip = mtd->priv;
debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
if (ctrl & NAND_CTRL_CHANGE) {
ulong IO_ADDR_W = (ulong)nand;
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 (ctrl & NAND_NCE)
writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
&nand->nfconf);
else
writel(readl(&nand->nfconf) | S3C2410_NFCONF_nFCE,
&nand->nfconf);
}
if (cmd != NAND_CMD_NONE)
writeb(cmd, chip->IO_ADDR_W);
添加
if (ctrl & NAND_CLE)
{
writeb(cmd, &nand->nfcmd);
}
else if (ctrl & NAND_ALE)
{
writeb(cmd, &nand->nfaddr);
}
编译烧写到NAND FLASH就可以识别NAND大小。
4、分析过程:
u-boot-2016.05\common\board_r:board_init_r函数中的初始化序列init_sequence_r中的:
initr_nand
nand_init
nand_init_chip
board_nand_init
设置nand_chip结构体, 提供底层的操作函数
nand_scan
nand_scan_ident
nand_set_defaults
chip->select_chip = nand_select_chip;
chip->cmdfunc = nand_command;
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
nand_get_flash_type
chip->select_chip
chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
nand_command() // 即可以用来发命令,也可以用来发列地址(页内地址)、行地址(哪一页)
chip->cmd_ctrl
s3c24x0_hwcontrol
chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
*maf_id = chip->read_byte(mtd);
*dev_id = chip->read_byte(mtd);