歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下的nandflash驅動分析(2)——基於S2C6410平台

Linux下的nandflash驅動分析(2)——基於S2C6410平台

日期:2017/3/1 10:21:08   编辑:Linux編程

1、在上一篇的probe函數中,在那個很大的for循環中出現了,對NAND的廠商,設備號,是MLC或SLC進行判斷,這些是怎樣進行的呢?

相關閱讀:

Linux下的nandflash驅動分析(1)——基於S3C6410平台 http://www.linuxidc.com/Linux/2012-05/61439.htm

Linux下的nandflash驅動分析(2)——基於S3C6410平台 http://www.linuxidc.com/Linux/2012-05/61544.htm

Linux下的nandflash驅動分析(3)——基於S3C6410平台 http://www.linuxidc.com/Linux/2012-05/61545.htm

其實這些都是在NAND芯片中定義的,我們只需按對應的時序讀出這些信息,就可以進行判斷,看下面這個圖(摘於一個NAND芯片手冊):



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; 和數據寬度有關,看下面這個圖:


/* 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函數:源碼如下:

/**
* nand_scan_tail - [NAND Interface] Scan for the NAND device
*/

Copyright © Linux教程網 All Rights Reserved