Linux mtd子系统专栏分析之三 MTD层相关接口说明(注册与注销等)

       原文再续,书接上回。在上篇文章中,我们介绍了mtd层相关数据结构以及接口的关联,并简要说明了mtd层与vfs、文件系统层、闪存芯片驱动层的关联,本篇文章主要介绍mtd层相关的接口,这些接口用于实现这些数据结构的关联与解绑。

 

本篇文章的主要内容如下:

 

  1. mtd设备相关的注册与注销接口说明
  2. Mtd info master与slave的区别
  3. 如何进行分区设置操作
  4. 如何实现将一个闪存芯片注册至mtd子系统中。

 

 

一、mtd设备相关的注册与注销接口

按照上一篇文章的分析,针对mtd设备相关的注册,主要包括如下几个方面:

  1. 提供mtd设备注册的接口,完成mtd info设备注册至设备驱动模型子系统中,并完成mtd字符设备与mtd块设备的创建(从而完成mtd info与设备驱动子系统、vfs子系统的关联);
  2. 若闪存设备支持分区,则提供分区注册接口,主要完成每一个分区对应的mtd_info设备注册至设备驱动模型子系统中;并将每一个分区对应的mtd_part类型的变量注册至链表mtd_partitions中;

 

基本上也就以上两个功能,而在mtd子系统中,针对注册的接口即为mtd_device_parse_register,而在

该接口中,则根据是否进行分区,分别调用add_mtd_partitions、add_mtd_device的注册。

 

mtd_device_parse_register接口分析

      该接口主要实现将mtd_info设备注册到mtd子系统中。由于闪存设备可以选择分区,也可以选择不分区,因此该接口包括这两个功能。该接口的实现如下,还包括parse_mtd_partitions接口,该接口主要是解析分区信息的配置。该接口实现较简单,不再细说。

 

 

     若一个闪存芯片,在注册至mtd子系统中时,不需要进行分区,则只需要使用接口add_mtd_device即可,下面我们对该接口进行分析。

 

add_mtd_device接口

该接口的处理流程如下图所示(省略了异常处理),其主要实现如下功能:

  1. 设置mtd_info相关的信息,包括writesize_shift等;另外针对设置了可写信息且上电时锁定芯片的mtd设备,需要执行unlock操作(在某些场景下,我们做flash的设计时,可以让硬件设计人员将wp引脚默认为有效,用于保证系统上电时可能导致的写异常。然后在驱动中再将wp引脚关闭即可,而mtd子系统支持该功能,只需要实现mtd_info中_unlock成员函数指针即可);
  2. 设置该mtd_info所包含的device类型成员的信息,主要设置其所属的class以及其device_type信息

关于device、class相关的关联我们在之前的设备驱动模型系列文章中已经说明;而在mtd_devtype中则主要定义了mtd_info设备的注销信息。如下为device_ktype中的release和device_type的release接口的关系,当mtd_info的引用计数为0时,则会调用device_ktype的release接口,最终则调用mtd_release进行释放操作。

 

 

 

  1. 调用device_register,进行mtd_info对应device类型变量的设备注册,而在注册中会向应用层发送uevent信息(借助netlink),然后应用层的mdev/udev程序接收到uevent信息,根据设备号会进行字符设备与块设备对应inode节点的创建(调用mknod),至此即完成该mtd_info对应的字符设备与块设备文件的创建;

 

 

add_mtd_partitions

该接口主要针对需要对注册设备进行分区的情况,该接口主要实现两个功能:

  1. 针对每一个分区,均创建一个mtd_part类型的变量,该变量包括master mtd_info以及该分区对应的mtd_info,并初始化该分区对应slave mtd_info,而针对slave mtd_info,其上层接口主要为分区相关的接口,该接口主要会调用master mtd_info对应的接口。针对master mtd_info、slave mtd_info的关联,在下面分析。
  2. 针对每一个分区,将其mtd_part中的slave mtd_info调用add_mtd_device,将其注册至mtd子系统中。

该接口的代码实现如下,逻辑流程简单,不再赘述。

 

 

       Mtd_info的注销接口为mtd_device_unregister,该接口主要是实现mtd_info的注销操作,其实主要就是调用device_unregister进行mtd_info对应device类型设备的注销,同时若为分区设备,则将其从mtd_partitions链表上删除等。

 

 

Mtd info master与slaver的区别

在上一篇文件介绍mtd_info与上下层子系统的关联时,没有详细说明master 与slaver mtd_info的关联,下面具体说明下。主要包括如下几点:

  1. 一个master mtd_info对应一个闪存设备;
  2. 一个slaver mtd_info对应一个闪存设备的逻辑分区(若没有逻辑分区,则不存在该变量)
  3. 若一个闪存设备没有进行逻辑分区,则会将该master mtd_info注册至mtd子系统中,并创建一个master mtd_info对应的字符设备、块设备;
  4. 若一个闪存设备进行逻辑分区,则每一个逻辑分区对应的slaver mtd_info均注册至mtd子系统中,并创建该slaver mtd_info对应的字符设备与块设备,而master mtd_info不注册至mtd子系统中;此时slaver mtd_info并没有实现对芯片驱动的访问接口,而对下层闪存芯片驱动的访问接口还是由master mtd_info中的接口实现访问操作;而slaver mtd_info中的接口主要即是对master mtd_info的简单封装而已。还需要将每一个逻辑分区对应的mtd_part变量注册至mtd_partitions链表中。

如下图是逻辑关联图,当没有逻辑分区时,则mtd接口层通过黄色箭头调用master mtd_info中的接口完成对下层闪存芯片的访问;当存在逻辑分区时,则mtd接口层通过蓝色接口借助slaver mtd_info,间接调用master mtd_info的接口完成对下层闪存芯片的访问。

 

 

 

如何进行分区设置操作

针对闪存芯片逻辑分区的设置,主要包括两种:

  1. 若linux内核不支持设备树,则定义struct mtd_partition类型的变量即可(可以在板级文件中定义,并将其作为platform 的device的参数传递,然后在闪存芯片或闪存芯片控制器的驱动接口中解析该参数即可);
  2. 若linux内核支持设备树,则只需要在设备树文件中,增加分区信息即可;

当我们进行逻辑分区时,可设置分区属性为只读,这样在linux内核下则不会修改该分区(这只是逻辑实现只读属性,若想决定只读则可使用wp引脚设置写保护)

 

如何实现将一个闪存芯片注册至mtd子系统中

  1. 在闪存对应驱动的probe接口中,完成针对master mtd_info变量的初始化,包括参数以及接口的设置,并完成设置master mtd_info的priv成员指针指向该芯片驱动对应的结构体变量(包含了针对该闪存芯片参数及访问接口等信息);
  2. 调用mtd_device_parse_register接口,完成对该芯片逻辑分区注册至mtd子系统中。

针对系统中nor flash驱动、nandflash驱动、spi flash驱动(如m25p80驱动)等驱动模型,均是通过这两步完成注册的。

 

 

本篇文章主要说明mtd子系统的注册与注销以及一些概念的说明,下一篇文章说明nandflash框架。

 

 

发布了151 篇原创文章 · 获赞 34 · 访问量 46万+

猜你喜欢

转载自blog.csdn.net/lickylin/article/details/104760367