您的位置:首页 > 其它

移植uboot到TQ2440出现No NAND device found!!!的解决办法

2012-03-03 16:50 483 查看
在增加Nand读写支持的时候,曾经一度出现下面的错误信息:
NAND:No NAND device found!!! 0MiB
这个信息曾经困扰了我很久,终于在某一天成功的解决了。在此写下以记录教训!
首先,用Source Insight搜索这个信息的打印出处,在drivers/mtd/nand/nand_base.c文件:
intnand_scan_ident(struct mtd_info *mtd, int maxchips)
{
int i, busw, nand_maf_id;
struct nand_chip *chip = mtd->priv;
struct nand_flash_dev *type;
……
type = nand_get_flash_type(mtd, chip,busw, &nand_maf_id);

if (IS_ERR(type)) {
#ifndefCONFIG_SYS_NAND_QUIET_TEST
printk(KERN_WARNING "No NAND device found!!!\n");
#endif
……
}
根据打印条件,判断是type返回值出错,于是分析nand_get_flash_type函数,可以发现在函数中有这么两行:
if (!type)
return ERR_PTR(-ENODEV);
因此猜测是type出错了,于是向上查找type的赋值情况,在紧挨着上述两行代码前面有这么几行:
/* Lookup the flash id */
for (i = 0; nand_flash_ids[i].name !=NULL; i++) {
if (dev_id ==nand_flash_ids[i].id) {
type = &nand_flash_ids[i];
break;
}
}
这段代码是Nand ID的匹配查找工作,在源代码的文件drivers/mtd/nand/nand_ids.c文件中定义了常见的Nand Flash厂商号和设备号,上述代码就是把从硬件Flash中读取到的设备号与源码中的Nand Flash ID列表进行比对,如果有一个ID与从硬件NAND上读取的ID匹配,说明找到了外设Nand,否则就没找到。根据这个信息,我们在这个函数的前面找到了读取硬件ID的代码:
chip->cmdfunc(mtd, NAND_CMD_RESET, -1,-1);
/* Send the command for reading device ID*/
chip->cmdfunc(mtd, NAND_CMD_READID,0x00, -1);
/* Read manufacturer and device IDs */
*maf_id = chip->read_byte(mtd);
dev_id = chip->read_byte(mtd);
/*下面这行是我后来加上的,目的就是看看读取的ID号到底是多少。*/
printf("In %s,*maf_id is 0x%x,dev_idis 0x%x.\n",__func__,*maf_id,dev_id);
重新编译并下载之后看到如下打印信息:
NAND:In nand_get_flash_type,*maf_id is 0x95,dev_id is 0x95.
No NAND device found!!!
0 MiB
依然是找不到Nand。不过从这句话我们可以看出,读取Nand的厂商号和设备号出了问题。实际上的厂商号是0xEC,设备号是0xDA。
于是定位到读取ID代码上,搜索chip->read_byte函数的赋值语句发现是在本文件中的nand_read_byte函数,再起里面加上打印语句:
static uint8_t nand_read_byte(structmtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
printf("Innand_read_byte,chip->IO_ADDR_R is %p\n",chip->IO_ADDR_R);
return readb(chip->IO_ADDR_R);
}
接着搜索发送命令/地址的函数,chip->cmdfunc,发现该函数调用了chip->cmd_ctrl函数,而这个函数正好是自己在nand_flash函数中实现的函数,也加上打印语句:
25static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
26 {
……
56 printf("Ins3c2440_hwcontrol.ctrl is 0x%x,cmd is 0x%x\n",ctrl,cmd);
57 if (cmd != NAND_CMD_NONE)
58 writeb(cmd,chip->IO_ADDR_W);
59 }
上述函数是在board_nand_init函数中赋值的,在这个函数也加上打印信息。另外,在函数s3c2440_dev_ready中也增加打印信息,判断一下读取硬件是否出现问题,为此修改如下:
61static int s3c2440_dev_ready(struct mtd_info *mtd)
62 {
63 struct s3c2440_nand *nand =s3c2440_get_base_nand();
64 unsigned int ready=0;
65 ready = readl(&nand->NFSTAT)& 0x01;
66 printf("Ins3c2440_dev_ready,dev is %s ready.\n",ready?"":"not");
67 return ready;
68 }
重新编译并下载之后看到的信息如下图所示:



可以看到,虽然基本断定函数调用没有问题,但是厂商号和设备号依然是0x95,依旧找不到NAND!!!因此,肯定的说,是Nand的发送命令和地址的地方出现了错误。该功能的实现在nand->cmd_ctrl函数中,回去仔细研究,发现问题就是出在这里:
49 if (ctrl & NAND_NCE)
50 writel(readl(&nand->NFCONF)& ~S3C2440_NFCONT_nCE,
51 &nand->NFCONF);
52 else
53 writel(readl(&nand->NFCONF)| S3C2440_NFCONT_nCE,
54 &nand->NFCONF);
S3C2410和S3C2440的寄存器是不相同的,原先的S3C2410使用的是NFCONF寄存器,而S3C2440使用的是NFCONT寄存器,修改成NFCONT,重新编译下载,成功!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐