这个API用来根据传入的参数匹配一个map_info对象的驱动,比如CFI接口或JEDEC接口的NOR Flash。这个函数的接口如下:
struct mtd_info *do_map_probe(const char *name, struct map_info *map)对于常用的NorFlash标准,这个函数的调用方式如下:
do_map_probe("cfi_probe", &xxx_map_info); do_map_probe("jedec_probe",&xxx_map_info); do_map_probe("map_rom",&xxx_map_info);匹配了设备驱动,可以发现一个map_info对象中没有mtd_partitions相关的信息,对于一个NOR Flash的分区信息,需要通过do_map_probe返回的mtd_info对象来注册到内核。这里我们可以先调用parse_mtd_partitions()查看Flash上已有的分区信息,获取了分区信息之后再调用add_mtd_partitions()将分区信息写入内核
NOR Flash驱动模板 #define WINDOW_SIZE ... #define WINDOW_ADDR ... static struct map_info xxx_map = { .name = "xxx flash", .size = WINDOW_SIZE, .bankwidth = 1, .phys = WINDOW_ADDR, }; static struct mtd_partition xxx_partitions[] = { .name = "Drive A", .offset = 0, .size = 0x0e000, }; #define NUM_PARTITIONS ARRAY_SIZE(xxx_partitions) static struct mtd_info *mymtd; static int __init init_xxx_map(void) { int rc = 0; xxx_map.virt = ioremap_nocache(xxx_map.phys, xxx_map.size); if(!xxx_map.virt){ printk(KERN_ERR"Failed to ioremap_nocache\n"); rc = -EIO; goto err2; } simple_map_init(&xxx_map); mymtd = do_map_probe("jedec_probe", &xxx_map); if(!mymtd){ rc = -ENXIO; goto err1; } mymtd->owner = THIS_MODULE; add_mtd_partitions(mymtd, xxx_partitions, NUM_PARTITIONS); return 0; err1: map_destroy(mymtd); iounmap(xxx_map.virt); err2: return rc; } static void __exit cleanup_xxx_map(void) { if(mymtd){ del_mtd_partitions(mymtd); map_destroy(mymtd); } if(xxx_map.virt){ iounmap(xxx_map.virt); xxx_map.virt = NULL; } } Nand Flash驱动下图就是基于MTD框架的NandFlash驱动的位置。
Nand Flash和NOR Flash类似,内核中已经在"drivers/mtd/nand/nand_base.c"中实现了通用的驱动程序,驱动开发中不需要再实现mtd_info中的read, write, read_oob, write_oob等接口,只需要构造并注册一个nand_chip对象, 这个对象主要描述了一片flash芯片的相关信息,包括地址信息,读写方法,ECC模式,硬件控制等一系列底层机制。当下,编写一个NandFlash驱动的工作流程如下:
nand_chip这个结构描述一个NAND Flash设备,通常藏在mtd_info->priv中,以便在回调其中的接口的时候可以找到nand_chip对象。
547 struct nand_chip { 548 void __iomem *IO_ADDR_R; 549 void __iomem *IO_ADDR_W; 550 551 uint8_t (*read_byte)(struct mtd_info *mtd); 578 579 int chip_delay; 580 unsigned int options; 581 unsigned int bbt_options; 582 583 int page_shift; 584 int phys_erase_shift; 585 int bbt_erase_shift; 586 int chip_shift; 587 int numchips; 588 uint64_t chipsize; 589 int pagemask; 590 int pagebuf; 591 unsigned int pagebuf_bitflips; 592 int subpagesize; 593 uint8_t bits_per_cell; 594 uint16_t ecc_strength_ds; 595 uint16_t ecc_step_ds; 596 int badblockpos; 597 int badblockbits; 598 599 int onfi_version; 600 struct nand_onfi_params onfi_params; 601 602 int read_retries; 603 604 flstate_t state; 605 606 uint8_t *oob_poi; 607 struct nand_hw_control *controller; 608 609 struct nand_ecc_ctrl ecc; 610 struct nand_buffers *buffers; 611 struct nand_hw_control hwcontrol; 612 613 uint8_t *bbt; 614 struct nand_bbt_descr *bbt_td; 615 struct nand_bbt_descr *bbt_md; 616 617 struct nand_bbt_descr *badblock_pattern; 618 619 void *priv; 620 };