Linux pinctrl子系统分析之四 pinctrl device的注册与注销

  前面我们分析了pinctrl子系统相关的数据结构等内容,本章我们分析pinctrl device的注册与注销接口。

 

  针对pinctrl device的注册与注销主要涉及pinctrl_register、pinctrl_unregister、devm_pinctrl_register、devm_pinctrl_unregister这几个接口。而devm_pinctrl_register、devm_pinctrl_unregister这两个接口则主要由设备驱动模型实现资源申请与释放,即使用者两个接口,则pinctrl device无须在driver remove时进行资源的释放(设备资源管理也是设备驱动子系统的一个模块,该模块实现资源的管理,也就是针对device申请的资源均存放到device的链表上,当对该device 进行destroy时,一并对这些资源进行释放)。

 

Pinctrl device 注册与注销实现的功能

其实pinctrl device的注册就是实现如下图的数据结构间的关联,这个我们之前也说了,理清了数据

结构间的关系,也就知道相应函数的实现流程了,尤其是linux内核的代码,只要理解数据结构间的关系,那理解一个驱动模块就事半功倍了。

 

pinctrl_register接口

针对pinctrl_register接口就是建立下图的数据结构间的关联图,下面我们具体说明:

Linux pinctrl子系统分析之四 pinctrl device的注册与注销_第1张图片

 

  1. 调用pinctrl_register进行pinctrl device的注册时,需要传递struct pinctrl_desc类型的变量,该变量用于描述一个soc pin controller的信息,包含所支持的pin引脚的描述(每一个引脚的名称与index)、pin复用操作的接口(主要是struct pinmux_ops类型的变量,包含引脚的申请与释放接口、引脚复用设置接口、gpio引脚复用配置以及方向设置接口等)、pin引脚或group相关的引脚配置接口(包含引脚配置接口、引脚当前配置参数获取接口、group相关引脚的配置接口、debug接口等)、group相关的操作接口(获取group的个数、获取group的名称、获取group对应的引脚内容、从设备树设备节点中解析board pin描述信息并进行pinctrl map注册的接口dt_node_to_map)
  2. 根据struct pinctrl_desc类型变量中的引脚描述成员pins、npins,对pin引脚进行解析,并针对每一个pin均创建一个对应的struct pin_desc类型的变量,并将其加入到基数树pinctrl_dev->pin_desc_tree中,而struct pin_desc则主要描述该pin当前的配置信息(所属function、group、pin引脚配置计数等,该数据结构在上一章已经介绍,当我们进行引脚复用配置调用pin_request时,则根据struct pin_desc类型变量记录的值确定该引脚是否已经被别的模块配置);
  3. 需要检查pinctrl_desc定义的pinmux_ops、pinctrl_ops、pinconf_ops变量中各接口是否定义,做合法性检测;
  4. 当完成以上操作后,即将该struct pinctrl_dev类型的变量添加到pinctrldev_list链表上,至此完成pinctrl device的注册。

 

     pinctrl_register、devm_pinctrl_register主要实现soc pin controller描述相关信息的定义与注册。该接口实现的功能也就是以上四点。

 

     pinctrl_register函数主要分为pinctrl_init_controller、pinctrl_enable两个函数,pinctrl_init_controller函数主要实现上述的1-3的内容,而pinctrl_enable则实现上述4的内容,主要将该pinctrl device添加到pinctrldev_list上。

       pinctrl_init_controller的实现如下所示,基本上也就实现上面的1-3点的内容,根据传递的struct pinctrl_desc类型的变量pctldesc,申请struct pinctrl_dev类型的内存,然后初始化pin_desc_tree、pin_group_tree、pin_function_tree(这三个基数树变量主要存储引脚配置的变量、group相关的变量、function相关的变量等信息,其中pin引脚加入到pin_desc_tree中的操作由pinctrl_register_pisn实现。而group、function加入到pin_group_tree、pin_function_tree这个操作是新内核加入的,因此这个加入操作没有再pinctrl_register中,而是由具体的pinctrl device driver自行调用pinctrl_generic_add_group、pinmux_generic_add_function实现,在以后的内核升级中可能也会由pinctrl_register实现)

Linux pinctrl子系统分析之四 pinctrl device的注册与注销_第2张图片

      而接口pinctrl_register_pins则根据该pinctrl device的引脚描述,将所有的引脚注册进pinctrl device的pin_desc_tree中。该接口的实现如下,代码逻辑也比较清晰,就不再细述。

Linux pinctrl子系统分析之四 pinctrl device的注册与注销_第3张图片

 

pinctrl_unregister接口

该接口实现的功能刚好和pinctrl_register相反,此处就不细述。

 

Pinctrl device driver的实现流程

下面我们描述下如何实现pinctrl device driver,主要包含如下几个步骤:

  1. 为该soc pin controller 实现platform device driver驱动,然后在该驱动的probe接口中实现如下功能:
    1. 定义struct pinctrl_desc类型的变量,并实现相应的成员变量的配置,包含支持的引脚描述、支持的引脚复用接口的赋值、支持的引脚配置接口的赋值、支持的group操作接口以及dt2map接口的赋值等;
    2. 调用pinctrl_register/devm_pinctrl_register完成pinctrl device的注册
    3. 定义该soc  pin controller的group相关变量的添加(若使用自行定义的结构存储就自行实现,也可调用pinctrl_generic_add_group接口实现);
    4. 定义该soc  pin controller的function相关变量的添加(若使用自行定义的结构存储就自行实现,也可调用pinctrl_generic_add_function接口实现);

 

        完成以上几步,基本上就完成了pinctrl device driver的注册。在本专栏的最后,我将实现一个虚拟的pinctrl device driver,并借助sysfs进行调试,从而完成pinctrl 子系统的驱动开发实践。

你可能感兴趣的:(Linux,内核)