Linux pinctrl子系统分析之六 设备与pinctrl子系统的bind

     本章我们分析设备与pinctrl子系统的bind,在前面几章我们介绍了soc pin 描述相关的数据结构与注册接口、board pin 描述相关的数据结构与注册接口,但是我们却没有看到是在何时由谁实现对设备相关的引脚进行引脚复用与引脚配置的,而这些就是本章的内容。

 

 

设备与pinctrl 子系统的bind

     在前面我们说了,device是pinctrl的持有者,因此设备相关的引脚复用设置以及引脚配置均应由设备来进行控制,若由设备进行控制的话,难道由每个设备的驱动程序实现引脚复用相关的调用,那岂不是很大的改动量???在进行开发设计时,这种方式显然是不可取的,在pinctrl子系统的实现中,借助设备驱动模型中的driver_probe_device接口,当device与drivermatch后,在driver_probe_device->really_probe的接口中,在调用driver/bus的probe接口进行probe之前,通过调用pinctrl_bind_pins接口实现dev与pinctrl子系统的绑定,并完成pin相关的复用与配置操作。那为什么是在调用driver/bus的probe接口进行probe之前??因为driver的probe接口中会访问设备,因此需要在访问设备操作之前,完成引脚的配置。

 

pinctrl_bind_pins接口

      那pinctrl_bind_pins接口实现什么功能呢?我们通过之前分析数据结构、pinctrl device、pinctrl map,大概也可知道一二,主要包含如下内容:

  1. 完成如下的数据结构关联图,为该设备申请struct dev_pin_info类型的内存空间;
  2. 根据设备名称,在pinctrl_list链表查找该设备对应struct pinctrl 类型的变量:
    1. 若pinctrl_list链表上存在对应的pinctrl,则将其与struct dev_pin_info进行绑定;
    2. 若pinctrl_list链表上不存在对应的pinctrl,则首先调用pinctrl_dt_to_map接口,对于支持设备树的内核,则解析该设备的节点内容,解析出该设备所对应的map信息,并pinctrl map注册至pinctrl_maps链表上;然后则申请struct pinctrl类型的内存空间,并查找pinctrl_maps链表上所有dev_name与该设备名称相同的pinctrl_map,并依据pinctrl_map信息为该pinctrl创建对应的state,并为该state创建对应的pinctrl_setting信息,至此即完成下图中数据结构间的关联图(其中pinctrl_setting中存储了该device对应的mux group、pin/group config相关的group/pin id、function id等信息)。
  3. 获取该dev default state或者init state对应的struct pinctrl_state类型的变量,然后调用接口pinctrl_select_state进行group mux、group/pin config的操作,即完成设备相关引脚的配置。

 

Linux pinctrl子系统分析之六 设备与pinctrl子系统的bind

 

而pinctrl_bind_pins接口也基本上就是实现上述内容,下面是该函数的实现代码,其中

  1. devm_pinctrl_get则实现上述1-2中描述的内容;
  2. 而通过pinctrl_lookup_state完成该设备init_state、default_state、sleep_state、idle_state的查找,最后调用pinctrl_select_state接口,实现引脚复用以及引脚配置操作(针对group mux,则最终调用pinctrl_dev提供的pin_request、set_mux实现相应的引脚复用设置操作;针对pin/group config,则最终调用pinctrl_dev提供的pin_config_group_set实现pin/group的配置,有兴趣的童鞋可以跟踪一下,这部分的代码不复杂)。

 

Linux pinctrl子系统分析之六 设备与pinctrl子系统的bind

 

 

 

devm_pinctrl_get接口

    刚才上面说了,该接口实现pinctrl的查找或创建工作,下面我们说明一下,其内部主要调用pinctrl_get实现pinctrl的查找或创建工作。

     pinctrl_get的实现简单明了:

  1. 调用find_pinctrl接口,根据设备名称从pinctrl_list中查找是否存在该pinctrl,若存在函数返回;
  2. 若未找到,则调用create_pinctrl创建一个pinctrl。

 

Linux pinctrl子系统分析之六 设备与pinctrl子系统的bind

 

create_pinctrl

如下即是create_pinctrl接口的实现,其主要内容:

  1. 调用pinctrl_dt_to_map接口,针对支持设备树的情况,则对该设备的节点内容进行解析,解析出该设备对应的pinctrl map信息,并注册至pinctrl_maps链表中,一个设备对应的pinctrl map包括mux group、pin/group config等(可参考上一篇文章内容)。pinctrl_dt_to_map主要调用pinctrl dev的dt_node_to_map接口对设备节点中的map信息进行解析;
  2. 在pinctrl_maps链表上,查找该设备所对应的所有pinctrl_map(根据设备名称查找),然后根据pinctrl_map提供的信息,调用add_setting,为该pinctrl创建pinctrl_state、并设置pinctrl_state对应的pinctrl_setting信息,就是实现最上面的数据结构间的关联,大家对照着上面的数据结构再去看add_setting接口的实现就相对容易很多。

Linux pinctrl子系统分析之六 设备与pinctrl子系统的bind

 

 

 

以上即是设备与pinctrl绑定的大致分析,希望对大家有所帮助。