Linux pinctrl子系统分析之二 从数据结构关联理解pinctrl子系统

 

     上一章我们对pinctrl子系统进行概述,说明了pinctrl子系统相关的概念、软件框架等内容,本章我们主要从pinctrl子系统数据结构间的关联,从而理解pinctrl子系统的设计。

 

 

 

pinctrl数据结构说明

      在上一章我们画出了pinctrl子系统的软件架构(如下图所示),而在linux内核的各子系统设计过程中,软件框架基本上就是由数据结构间关联以及对外接口实现子系统的设计,因此理解了一个子系统数据结构间的关联,基本上就掌握了一个子系统大致实现流程。在linux 内核中,当学习一个新的子系统中,先熟悉其数据结构,基本上可以做到事半功倍。

 

      我们首先理清数据结构间的关联。如下图,通过pinctrl子系统的数据结构、处理接口构建的pinctrl子系统框架。下面我们分类说明。

 

Soc pin 描述

       针对一款soc芯片,我们通过其数据手册,可以知道其提供的引脚个数、每一个引脚复用情况、每一个引脚的配置信息、每一个function包含的引脚使用组合(如iic0可以支持{pin8、pin9}、{pin20、pin21}两种group类型供选择,而基于该款soc设计的开发板,则需要针对iic0选择一组作为iic0的引脚。如开发板1基于该soc选择{pin8、pin9}作为iic0的引脚,而开发板2基于该soc选择{pin20、pin21}作为iic0的引脚)等信息。而针对soc芯片而言,其无需关注具体基于该soc的开发板的引脚复用,其只需要列出该soc芯片针对引脚配置的所有信息即可。

   在pinctrl子系统中,soc pin controller的描述通过数据结构struct pinctrl_dev描述,其包含如下信息:

  1. 存储该soc支持的所有引脚的描述,此处使用基数树pin_desc_tree存储所有struct pin_desc类型的变量,而struct pin_desc主要描述一个pin引脚,包括该引脚当前配置的引脚复用情况、引脚名称、引脚复用设置的次数,以及该引脚所属的pinctrl device;
  2. 存储该soc支持的所有group的描述(该项内容在4.4以后的内核版本中添加的,在之前的版本中,group与function的描述由各soc pin controller自行描述,struct pinctrl_dev中没有描述,pinctrl子系统只要求各soc pin controller driver提供group、function的访问方法即可,其不进行function与group的存储情况,而在4.4内核以后,pinctrl子系统提供了function与gropu的存储,均是通过基数树进行存储,并定义struct group_desc 、struct function_desc描述group、function ),新的内核版本将group、function也纳入pinctrl子系统的管理确实是一个大的提升,因为pinctrl子系统没有提供group、function存储时,各soc pin controller driver定义的group、function数据结构基本上是类似的,因此这些数据结构由pinctrl子系统接管是最好的。
  3. 存储该soc支持的所有function的描述;
  4. 提供引脚复用相关的操作接口(struct pinmux_ops定义的操作接口);
  5. 提供引脚配置相关的操作接口(struct pinconf_ops定义的操作接口)

 

       以上几点就完整的描述了soc pin controller相关的信息,包含哪些引脚、包含哪些可能的组合、包含哪些可能功能、引脚配置相关的操作接口、引脚复用相关的操作接口等信息。关于pinctrl dev及引脚配置、引脚复用相关的驱动均是由soc 厂家提供。soc厂家提供了进行引脚分配及复用的接口,而具体怎么用,则由使用该soc的厂商决定。

 

board pin 描述

      上面讲的pinctrl_dev对应的是soc pin controller,而此处介绍的board pin描述,则是针对使用soc芯片的board,其所对应的具体的引脚使用,这部分引脚使用由具体的开发板厂家分配,也就是我们大部分驱动工程师的工作。下面即介绍board pin描述相关的信息。

    在pinctrl 子系统中,使用数据结构struct pinctrl_maps描述一个board的引脚使用情况,包含引脚的复用以及引脚配置信息等。具体包含如下信息:

  1. 每一个struct pinctrl_map表示一个function在某一个状态下对应的引脚复用及引脚配置信息,包含:
    1. function名称、状态名称(default、sleep、idle等);
    2. 所属pinctrl dev的名称、dev名称(即该pinctrl_map所依附的设备名称,如iic1等)
    3. map类型(引脚复用、引脚配置、group配置等)。
    4. 针对引脚复用,则包含function名称、group名称,通过pinctrl dev名称、function名称、group名称即可查找具体的pins信息。
    5. 针对pin/group配置,则包含group或pin名称,引脚配置信息等内容。

 

       针对板级引脚描述而言,主要描述该board所需要设置的所有function对应的引脚复用、引脚配置信息。针对board pin描述而言,基本上就是我们大部分驱动工程师的工作。但针对现有的pinctrl子系统而言,我们也就只需要在dts中配置一下引脚复用及配置情况即可。若内核不支持设备树,则需要在板级文件中定义引脚复用情况,并调用pinctrl_register_maps将其注册到pinctrl子系统即可。

 

       以上soc pin以及board pin以及完成了soc pin controller、board pin config and pin mux的描述,那board pin config and pin mux是如何完成针对具体device的配置的呢?这就涉及dev与pinctrl之间的关联了。pinctrl子系统在设计时,为了让具体外设设备驱动开发者对pin ctrl子系统无感知,在struct device中实现了该device与具体引脚配置function的关联,并在设备驱动模型子系统的device_driver probe之前,完成引脚的配置(主要通过pinctrl_bind_pins函数实现)。下一个小节则介绍dev与pinctrl的关联。

 

Dev与pinctrl关联描述

      如下图所示,struct device总增加了struct dev_pin_info类型的数据结构,实现了dev与pinctrl子系统进行的关联。

struct dev_pin_info包含如下信息:

  1. 该device pin支持的状态,包括idle_state状态下的引脚配置参数、init state下的引脚配置参数、default_state状态下的引脚配置参数(大多数设备一般只需要定义一个default state即可。只有少数的设备,其正常工作状态下与sleep状态下,引脚复用不同,如在sleep状态下可以释放该引脚,由别的设备使用,一般的话只需要设置default_state即可);
  2. struct pinctrl表示一个设备针对引脚控制的holder,其包括
    1. 该device所支持的引脚控制状态(如支持default、sleep状态的引脚控制策略);
    2. 每一个状态通过struct pinctrl_state描述,一个pinctrl state中包含该state下需要进行的设置策略(可有多个设置策略,每一个设置策略对应一个struct pinctrl_setting类型的变量,设置策略包含引脚复用的设置策略、引脚的配置策略、group的配置策略,针对一个device的一个state,可以包含多个引脚复用、引脚配置的策略),而struct pinctrl_setting类型主要根据function、group名称

 

 

 

 

 

         通过上面的soc pin controller 描述、board pin 描述、dev与pinctrl关联描述,即可完成引脚复用的配置以及引脚的配置。通过soc pin controller描述,说明一个soc pin controller支持的所有引脚、group、function等描述;通过board pin描述,说明一个board对引脚功能、引脚配置、引脚复用的使用情况;最后借助dev与pinctrl子系统的关联,将board pin描述与soc pin controller描述关联,并完成引脚的具体配置操作。以上就是本篇文章的主要内容。我们通过数据结构之间的关联,说明pinctrl子系统的设计框架。下一章介绍具体的数据结构定义。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章