从模型分析到Flash驱动模板(7)

struct nand_chip
--609-->NAND芯片的OOB分布和模式,如果不赋值,则会使用内核默认的OOB
--580-->与具体的NAND 芯片相关的一些选项,如NAND_BUSWIDTH_16 等,可以参考<Linux/mtd/nand.h>
--583-->用位表示的NAND 芯片的page 大小,如某片NAND 芯片的一个page 有512 个字节,那么page_shift 就是9 ;
--584-->用位表示的NAND 芯片的每次可擦除的大小,如某片NAND 芯片每次可擦除16K 字节( 通常就是一个block 的大小) ,那么phys_erase_shift 就是14 ;
--585-->用位表示的bad block table 的大小,通常一个bbt 占用一个block ,所以bbt_erase_shift 通常与phys_erase_shift 相等;
--587-->表示系统中有多少片NAND 芯片;
--588-->NAND 芯片的大小;
--589-->计算page number 时的掩码,总是等于chipsize/page 大小 - 1 ;
--590-->用来保存当前读取的NAND 芯片的page number ,这样一来,下次读取的数据若还是属于同一个page ,就不必再从NAND 芯片读取了,而是从data_buf 中直接得到;
--596-->表示坏块信息保存在oob 中的第几个字节。对于绝大多数的NAND 芯片,若page size> 512,那么坏块信息从Byte 0 开始存储,否则就存储在Byte 5 ,即第六个字节。
--619-->私有数据

nand_scan()

准备好了一个nand_chip,接下来的工作就是匹配驱动+注册分区表
NAND flash使用nand_scan()来匹配驱动,这个函数会读取NAND芯片的ID,并根据mtd->priv即nand_chip中的成员初始化mtd_info。如果要分区,则以mtd_info和mtd_partition为参数调用add_mtd_partitions来添加分区信息。

int nand_scan(struct mtd_info *mtd, int maxchips) NAND Flash驱动模板 #define CHIP_PHYSICAL_ADDRESS ... #define NUM_PARTITIONS 2 static struct mtd_partition partition_info[] = { { .name = "Flash partition 1", .info = 0, .size = 8 * 1024 * 1024, }, { .name = "Flash partition 2", offset = MTDPART_OFS_NEXT, size = MTDPART_SIZ_FULL, }, }; int __init board_init(void) { struct nand_chip *this; int err = 0; /* 为MTD设备对象和nand_chip分配内存 */ board_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip),GFP_KERNEL); if(!board_mtd){ printk("Unable to allocate NAND MTD device structure\n"); err = -ENOMEM; goto out; } /* 初始化结构体 */ memset((char *)board_mtd, 0 ,sizeof(struct mtd_info) + sizeof(struct nand_chip)); /* 映射物理地址 */ baseaddr = (unsigned long) ioremap(CHIP_PHYSICAL_ADDRESS,1024); if(!baseaddr){ printk("Ioremap to access NAND Chip failed\n"); err = -EIO; goto out_mtd; } /* 获取私有数据(nand_chip)指针 */ this = (struct nand_chip *)(&board_mtd[1]); /* 将nand_chip赋予mtd_info私有指针 */ board_mtd->priv = this; /* 设置NAND Flash的IO基地址 */ this->IO_ADDR_R = baseaddr; this->IO_ADDR_W = baseaddr; /* 硬件控制函数 */ this->cmd_ctrl = board_hwcontrol; /* 初始化设备ready函数 */ this->dev_ready = board_dev_ready; /* 扫描以确定设备的存在 */ if(nand_scan(board_mtd, 1)){ err = -ENXIO; goto = out_ior; } /* 添加分区 */ add_mtd_partitions(board_mtd,partition_info,NUM_PARTITIONS); goto out; out_ior: iounmap((void *)baseaddr); out_mtd: kfree(board_mtd); out: return err; } static void __exit board_cleanup(void) { /* 释放资源,注销设备 */ nand_release(board_mtd); /* unmap物理地址 */ iounmap((void *)baseaddr); /* 释放MTD设备结构体 */ kfree(board_mtd); } /* 硬件控制 */ static void board_hwcontrol(struct mtd_info *mtd, int dat,unsigned int ctrl) { ... if(ctrl & NAND_CTRL_CHANGE){ if(ctrl & NAND_NCE){ } } ... } /*返回ready状态*/ static int board_dev_ready(struct mtd_info *mtd) { return xxx_read_ready_bit(); }

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

转载注明出处:https://www.heiqu.com/8840177b6c5801da96185883ebeb051f.html