u-boot-2016.05移植:(4)、支持NADN FLASH

时间:2023-01-04 17:18:05

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);