基于MTD的2440-大页nand驱动

基于MTD2440-大页nand驱动

作者:guolele                                                                                    blog: http://blog.csdn.net/guolele2010

首先,这里就不分析MTD层了,这里只是说明在内核中应该如何写nand驱动程序,这里我用的是2Kpagenand。因为MTD层给我们做了大部分工作,我们在驱动里只要做几件事,注册MTD原始设备或者分区MTD,还要填充几个结构体,实现部分函数的操作。

先介绍几个重要的函数体。

Struct nand_chipstruct mtd_infostruct mtd_partitionstruct nand_ecclayout

其中,nand_chip是描述芯片的操作的一个结构体,mtd_info是描述MTD原始设备的结构体,mtd_partition是描述分区的结构体,而每一个分区注册进内核又是以一个个的MTD原始设备注册进内核的mtd_table里的,而nand_ecclayout的作用是描述ecc校验的相关信息。

 

  

这些函数都会在MTD层调用完MTD原始设备,从MTD原始设备再回调到nand_chip结构里调用真正操作硬件的函数指针,这个结构体是直接跟硬件相结合的。其中比较重要的除去函数指针(这里的这些指针我们并不需要全部写,因为内核实现了很大一部分的默认函数),其中的bbt_td bbt_md就是描述坏块的信息。

 

下面看看MTD原始设备

具体代码你们就自己去看内核的,这里我只说明其中的priv私有指针是非常非常重要的,因为它是要指向nand_chip的,然后才能在各MTD层里回调。

 

还有一个是struct nand_ecclayout,这个是描述ECC检验信息的,详情去看我转的一个文章。

 

下面具体分析代码,其中拿driver/mtd/nand/s3c2410.c为例,不过它的容器太多了,搞到层次太多,可能很里面才能看到上面讲的结构体,现在先讲讲它定义的几个结构体的关系。

 

 

 

 

这个是描述nand信息的,里面有两个结构体比较重要,这里说一下,内核采用的抽象结构比较多层,这样也适合于多种芯片一起工作,同类型的芯片分一个集合,所有集合整合到同一个大容器中,下面慢慢了解,我最后会画张图尝试讲讲,很多地方都用这样的方法。

 

struct s3c2410_nand_mtd                *mtds;

struct s3c2410_platform_nand       *platform;

 

一看这结构体,就是描述一块MTD设备以及它的芯片信息(即如何操作函数的),这里有一个新结构体struct s3c2410_nand_set           *set;这个结构体是描述一块或者多块nand芯片的分区的集合,下面有它的结构体。

 

 

 

这里就是有多少块,每块的分区情况,每块的ecc校验情况,集合成一个集合。

其中struct mtd_partition是描述一块芯片的分区信息的

  

而集合的集合,即集合的容器。

这里是有多少个集合,也就是这是集合上一层的容器。

看来已经迷糊了,所以发个图吧。

这个图画得真难啊,如果有谁有比word好画的软件,介绍一下啊。

 

 

那两个花括号是表示芯片一与芯片二,不知道为什么显不出来。背影也黑了。

 

这里再唠叨一下,struct s3c2410_nand_info里的struct s3c2410_platform_nand是在

arch/plat-s3c24xx/devs.c里定义的平台设备的私有数据。保存在xxx_nand_info里的作用是想知道有多少集合,每个集合的分区信息对应一个xxx_nand_mtd的结构体。

 

一个集合里有很多个分区组成,分区里也分了有几块芯片,而每一个集合注册进内核里又是以MTD设备注册,所以Struct s3c2410_nand_mtd里是保存了每个集合里的多少个芯片就多少个Struct s3c2410_nand_mtd->struct mtd_info结构体,注册是所有分区或者设备一起注册的。

 


 


分析完这几个结构体后,就知道,真正注册MTD设备(内核只处理MTD设备,而MTD设备操作就调用nand_chip结构)的结构体是保存在struct s3c2410_nand_mtd里。

注册一个MTD设备有两组对应函数:

Add_mtd_device 注册del_mtd_device卸载

 

Add_mtd_partition注册dev_mtd_partition卸载

这两组函数的主要区别是,分区在内核也是一个个MTD,前面一组是直接只有一个整体,而后面的把一个整体看作很多个。

在初始化这些结构体里的函数指针时,就有必要介绍两个函数:

int nand_scan_ident(struct mtd_info *mtd, int maxchips)

int nand_scan_tail(struct mtd_info *mtd)

 

先感性认识一下,nand_scan_ident这个函数的主要作用是为一些nand_chip里没定义的函数指针赋默认值,然后在读ID,再在nand_flash_ids这个全局数组中匹配,然后更新信息,这里的匹配相当重要,一些页大小,OOB大小,擦除一页大小,等等操作必要的信息都在里面。

 

nand_scan_tail这个函数是对更新后的mtd_info赋一些默认值。

 

看回s3c2410.c这个函数,它主要的作用是注册一个平台驱动,然后匹配时调用s3c24xx_nand_probe

 

这个函数一开始就初始化一些结构,然后先调用nand_scan_ident初始化每个集合中的每块MTD里的nand_chip再调用nand_scan_tail初始化每个MTD块设备,就完成了。

其中最主要就是下面这段函数:

for (setno = 0; setno < nr_sets; setno++, nmtd++) {

                   pr_debug("initialising set %d (%p, info %p)/n", setno, nmtd, info);

 

                   s3c2410_nand_init_chip(info, nmtd, sets);

 

                   nmtd->scan_res = nand_scan_ident(&nmtd->mtd,

                                                         (sets) ? sets->nr_chips : 1);

 

                   if (nmtd->scan_res == 0) {

                            s3c2410_nand_update_chip(info, nmtd);

                            nand_scan_tail(&nmtd->mtd);

                            s3c2410_nand_add_partition(info, nmtd, sets);

                   }

 

                   if (sets != NULL)

                            sets++;

         }

s3c2410_nand_init_chip(info, nmtd, sets);为每一个集合初始化它的nand_chip,然后赋给mtd_info->priv.

nmtd->scan_res = nand_scan_ident(&nmtd->mtd,

                                                         (sets) ? sets->nr_chips : 1);

因为是每个芯片一个MTD,所以对每个芯片要单独初始化,这个初始化函数会找到芯片ID,并根据信息初始化它的处理函数以及配置信息。

nand_scan_tail(&nmtd->mtd);

是接着上面的,找到了芯片,再初始化这块芯片的结构体。

 

总结一下,struct s3c2410_nand_set 就是保存多块芯片的多块分区信息,这些芯片必然有个联系,就是ECC校验相同或者是都差不多页大小之类的。

struct s3c2410_nand_platform就是所有集合的容器。

struct s3c2410_nand_mtd就是每个集合对应的MTD的容器,而这个容器里面就是包含了每个集合所有芯片以及分区。而注册里是一个集合的所有设备或者分区一起注册的。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值