Linux下的nandflash驱动分析(2)

Linux下的nandflash驱动分析(1)——基于S3C6410平台

Linux下的nandflash驱动分析(2)——基于S3C6410平台

Linux下的nandflash驱动分析(3)——基于S3C6410平台

其实这些都是在NAND芯片中定义的,我们只需按对应的时序读出这些信息,就可以进行判断,看下面这个图(摘于一个NAND芯片手册):

Linux下的nandflash驱动分析(2)


Linux下的nandflash驱动分析(2)


2、上一篇中,nand_scan(s3c_mtd, 1)函数没有细说,这一篇说下这个函数,源码如下:


/**
 * nand_scan - [NAND Interface] Scan for the NAND device
 * @mtd:MTD device structure
 * @maxchips:Number of chips to scan for
 *
 * This fills out all the uninitialized function pointers
 * with the defaults.
 * The flash ID is read and the mtd/chip structures are
 * filled with the appropriate values.
 * The mtd->owner field must be set to the module of the caller
 *
 */
int nand_scan(struct mtd_info *mtd, int maxchips)
{
int ret;


/* Many callers got this wrong, so check for it for a while... */
if (!mtd->owner && caller_is_module()) {
printk(KERN_CRIT "nand_scan() called with NULL mtd->owner!\n");
BUG();
}


ret = nand_scan_ident(mtd, maxchips);
if (!ret)   如果上面的函数成功,这执行nand_scan_tail函数。这个函数的分析,看下面:
ret = nand_scan_tail(mtd);
return ret;
}

主要就是上面那个函数:nand_scan_ident,源码如下:

/**
 * nand_scan_ident - [NAND Interface] Scan for the NAND device
 * @mtd:    MTD device structure
 * @maxchips:    Number of chips to scan for
 *
 * This is the first phase of the normal nand_scan() function. It
 * reads the flash ID and sets up MTD fields accordingly.

 *
 * The mtd->owner field must be set to the module of the caller.
 */
int nand_scan_ident(struct mtd_info *mtd, int maxchips)
{
int i, busw, nand_maf_id;
struct nand_chip *chip = mtd->priv;   得到struct nand_chip结构体
struct nand_flash_dev *type;


/* Get buswidth to select the correct functions */
busw = chip->options & NAND_BUSWIDTH_16;   和数据宽度有关,看下面这个图:

Linux下的nandflash驱动分析(2)


/* Set the default functions */ 根据数据宽度设置默认函数:
nand_set_defaults(chip, busw);此函数源码如下:

/*
 * Set default functions
 */
static void nand_set_defaults(struct nand_chip *chip, int busw)
{
/* check for proper chip_delay setup, set 20us if not */
if (!chip->chip_delay)
chip->chip_delay = 20;


/* check, if a user supplied command function given */
if (chip->cmdfunc == NULL)
chip->cmdfunc = nand_command;


/* check, if a user supplied wait function given */
if (chip->waitfunc == NULL)
chip->waitfunc = nand_wait;


if (!chip->select_chip)
chip->select_chip = nand_select_chip;
if (!chip->read_byte)
chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
if (!chip->read_word)
chip->read_word = nand_read_word;
if (!chip->block_bad)
chip->block_bad = nand_block_bad;
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
if (!chip->write_buf)
chip->write_buf = busw ? nand_write_buf16 : nand_write_buf;
if (!chip->read_buf)
chip->read_buf = busw ? nand_read_buf16 : nand_read_buf;
if (!chip->verify_buf)
chip->verify_buf = busw ? nand_verify_buf16 : nand_verify_buf;
if (!chip->scan_bbt)
chip->scan_bbt = nand_default_bbt;


if (!chip->controller) {
chip->controller = &chip->hwcontrol;
spin_lock_init(&chip->controller->lock);
init_waitqueue_head(&chip->controller->wq);
}


}


/* Read the flash type */     读取NAND芯片的信息,并进行一些结构体成员的赋值
type = nand_get_flash_type(mtd, chip, busw, &nand_maf_id);


if (IS_ERR(type)) {
printk(KERN_WARNING "No NAND device found!!!\n");
chip->select_chip(mtd, -1);
return PTR_ERR(type);
}


/* Check for a chip array */    和多芯片有关
for (i = 1; i < maxchips; i++) {
chip->select_chip(mtd, i);
/* See comment in nand_get_flash_type for reset */
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 */
if (nand_maf_id != chip->read_byte(mtd) ||
   type->id != chip->read_byte(mtd))
break;
}
if (i > 1)
printk(KERN_INFO "%d NAND chips detected\n", i);


/* Store the number of chips and calc total size for mtd */
chip->numchips = i;
mtd->size = i * chip->chipsize;


return 0;
}

3、nand_scan_tail函数:源码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/ppgfj.html