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();
}