MTD层调用驱动代码流程
read
mtd_read
mtd->_read
nand_read
nand_do_read_ops
nand->cmdfunc
chip->ecc.read_page
chip->read_buf
write
mtd_write
mtd->_write
nand_write
nand_do_write_ops
chip->write_page
chip->cmdfunc
chip->ecc.write_page
chip->write_buf
driver层代码初始化
maps/bcm963xx_mtd.c
mtd->priv = nand; 这个比较重要,实现nand与mtd的连接;
module_init(mtd_init);
struct mtd_info * mtd;
struct nand_chip * nand;
mtd = kmalloc(sizeof(struct mtd_info), GFP_KERNEL)
nand = kmalloc(sizeof(struct nand_chip), GFP_KERNEL)
mtd->priv = nand;
bcmspinand_probe(mtd);
nand_scan(mtd, 1)
nand->init_size(mtd, nand, NULL)
setup_mtd_parts(mtd);
nand层函数实现和函数指针实现赋值
nand/bcm63xx_spinand.c
bcmspinand_probe(mtd);
struct nand_chip * nand = mtd->priv;
pSpiDevice = spi_new_device(pSpiMaster, &bcmSpiDevInfo);
spi_register_driver(&bcmSpiDevDrv);
// reset and set configuration information
spi_nand_device_reset();
nand->ecc.size = pchip->chip_page_size;
nand->ecc.bytes = 0;
nand->ecc.strength = 0;
nand->ecc.layout = pchip->ecclayout;
nand->page_shift = pchip->chip_page_shift;
nand->phys_erase_shift = pchip->chip_block_shift;
nand->chipsize = pchip->chip_total_size;
rpageBuf = kmalloc(pchip->chip_page_size + pchip->chip_spare_size, GFP_KERNEL);
wpageBuf = kmalloc(pchip->chip_page_size + pchip->chip_spare_size, GFP_KERNEL);
nand->options = NAND_NO_SUBPAGE_WRITE;
nand->chip_delay = 0;
nand->read_byte = bcm63xx_read_byte;
nand->read_buf = bcm63xx_read_buf;
nand->ecc.mode = NAND_ECC_NONE;
nand->select_chip = bcm63xx_select;
nand->write_buf = bcm63xx_write;
nand->scan_bbt = bcm63xx_scan_bbt;
nand->block_bad = bcm63xx_block_isbad;
nand->block_markbad = bcm63xx_block_markbad;
nand->cmdfunc = bcm63xx_cmd;
nand->waitfunc = bcm63xx_status;
nand->init_size = bcm63xx_init_size;
MTD层函数实现和函数指针实现赋值
nand/nand_base.c
nand_scan(mtd, 1)
nand_scan_ident(mtd, maxchips, NULL)
nand_set_defaults
chip->scan_bbt = nand_default_bbt;
nand_scan_bbt(mtd, this->badblock_pattern);
nand_scan_tail(mtd);
struct nand_chip *chip = mtd->priv;
struct nand_ecc_ctrl *ecc = &chip->ecc;
ecc->layout = &nand_oob_64;
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
ecc->read_page = nand_read_page_raw;
ecc->write_page = nand_write_page_raw;
ecc->read_oob = nand_read_oob_std;
ecc->read_page_raw = nand_read_page_raw;
ecc->write_page_raw = nand_write_page_raw;
ecc->write_oob = nand_write_oob_std;
ecc->size = mtd->writesize;
ecc->bytes = 0;
ecc->strength = 0;
mtd->_erase = nand_erase;
mtd->_point = NULL;
mtd->_unpoint = NULL;
mtd->_read = nand_read;
mtd->_write = nand_write;
mtd->_panic_write = panic_nand_write;
mtd->_read_oob = nand_read_oob;
mtd->_write_oob = nand_write_oob;
mtd->_sync = nand_sync;
mtd->_lock = NULL;
mtd->_unlock = NULL;
mtd->_suspend = nand_suspend;
mtd->_resume = nand_resume;
mtd->_reboot = nand_shutdown;
mtd->_block_isreserved = nand_block_isreserved;
mtd->_block_isbad = nand_block_isbad;
mtd->_block_markbad = nand_block_markbad;
mtd->writebufsize = mtd->writesize;
/* propagate ecc info to mtd_info */
mtd->ecclayout = ecc->layout;
mtd->ecc_strength = ecc->strength;
mtd->ecc_step_size = ecc->size;
chip->write_page = nand_write_page;
return chip->scan_bbt(mtd);