在u-boot_1.1.6中支持大量的NandFlash芯片,但是由于各种NandFlash在各个不同系统中可以有不同的实现方式,因此在u-boot_1.1.6中必须自已实现对NandFlash的一些低级操作,需要修改的代码较多。
下面以目标板上使用的Samsung K9WAG08U1A为例进行移植说明。K9WAG08U1A是一片2G的Nand Flash,其内部由2片1G的nand chip堆叠而成。在外部连接上,它的CE1和CE2连接到BF561的PF0和PF1,CLE连接到PF2,ALE连接到PF3,RB1连接到PF4,RB2连接到PF5,其读写地址为0x2900 0000。
(1)在<include/configs/bf561-ezkit.h>中定义nand的基本信息。
#define CFG_MAX_NAND_DEVICE
1 /*Nand器件的数量*/
#define CFG_NAND_BASE
0x29000000 /* Nand读写的地址 */
#define NAND_MAX_CHIPS
2 /* 由2片堆叠而成 */
(2)在<include/configs/bf561-ezkit.h>中打开对Nand的支持。
#define CONFIG_COMMANDS (CONFIG_COMMANDS1 | CONFIG_COMMANDS2 | CFG_CMD_NAND)
(3)在<lib_blackfin/board.c>中添加对nand的控制函数。
static void bfin_hwcontrol(struct mtd_info *mtd, int cmd)
{
register struct nand_chip *this = mtd->priv;
switch(cmd){
/*将CLE设置为高电平*/
case NAND_CTL_SETCLE: *pFIO0_FLAG_S = 0x04; break;
/*将CLE设置为低电平*/
case NAND_CTL_CLRCLE: *pFIO0_FLAG_C = 0x04; break;
/*将ALE设置为高电平*/
case NAND_CTL_SETALE: *pFIO0_FLAG_S = 0x08; break;
/*将ALE设置为低电平*/
case NAND_CTL_CLRALE: *pFIO0_FLAG_C = 0x08; break;
}
__builtin_bfin_ssync();
}
int bfin_device_ready(struct mtd_info *mtd)
{
/*判断nand flash是否空闲*/
return ((*pFIO0_FLAG_D & 0x30) == 0x30) ? 1 : 0;
}
(4)在<lib_blackfin/board.c>中添加选择nand内部芯片的函数,实际上就是控制CE1和CE2,根据参数将之设置为低或高。
static int current_chip = -1;
static void nand_select_chip(struct mtd_info *mtd, int chip)
{
struct nand_chip *this = mtd->priv;
current_chip = chip;
switch(chip) {
/*两块芯片均不选中,即CE1和CE2都为高电平*/
case -1: *pFIO0_FLAG_S = 0x03; break;
/*选择第1块芯片,即CE1为低电平,CE2为高电平*/
case 0:
*pFIO0_FLAG_C = 0x01;
ssync();
*pFIO0_FLAG_S = 0x02;
break;
/*选择第2块芯片,即CE1为高电平,CE2为低电平*/
case 1:
*pFIO0_FLAG_C = 0x02; ssync();
*pFIO0_FLAG_S = 0x01;
break;
default:
BUG();
}
ssync();
}
(5)在<lib_blackfin/board.c>中添加初始化nand芯片的函数。
void board_nand_init(struct nand_chip *nand)
{
*pFIO0_DIR |= 0x000F; // 将 PF0~PF3 设置为输出
ssync();
*pFIO0_INEN |= 0x0030; // 将PF4和PF5设置为输入
ssync();
/*设置自己的控制函数*/
nand->hwcontrol = bfin_hwcontrol;
nand->eccmode = NAND_ECC_SOFT;
nand->dev_ready = bfin_device_ready;
nand->chip_delay = 30;
nand->select_chip = nand_select_chip;
}
(6)在<drivers/nand/nand.c>的nand_init_chip函数中有一行对nand_scan函数的调用,将之由
if (nand_scan(mtd, 1) == 0) {
修改为
if (nand_scan(mtd, NAND_MAX_CHIPS) == 0) {
经过修改后u-boot在启动时将可检测到两个内部芯片,并以正确计算出nand flash的大小,遗憾的是在使用nand info查看nand信息时仍然显示的是NAND 1GiB 3,3V 8-bit字样。