首页 服务器系统 Linux

Linux pinctrl子系统分析之一 系统概述

前面我们已经分析了gpio的系统,从现在开始我们还是把pinctrl子系统学习一下吧,pinctrl子系统主要涉及引脚复用设置、引脚设置等操作。本专栏大概划分如下几个篇章:
一、 pinctrl 子系统概述

二、pinctrl 子系统相关的数据结构及关联

三、pinctrl device的注册与注销

四、pinctrl map的注册与注销

五、pinctrl 引脚配置及复用

六、pinctrl驱动实践(虚拟pinctrl device驱动实现)

本篇是pinctrl子系统的第一篇文章,主要对pinctrl 子系统进行整体说明,了解pinctrl实现相关的大

致轮廓。本篇文章涉及的内容如下:

pinctrl子系统涉及的概念

pinctrl子系统实现的目标

pinctrl的系统软件框架


pinctrl子系统涉及的概念

作为驱动开发人员,当我们对一块新的开发板进行适配时,免不了要进行引脚的复用设置以及引脚自身的配置。我们知道一款soc所提供的引脚是有限的,且具体厂家依据soc设计的开发板,也并不需要使用soc所有的控制器,因此soc所提供的引脚,一般都会进行复用配置,如iic0可以使用pin8、pin9作为scl、sda,同时pin8、pin9也可以作为gpio或者作为can0引脚。基于此,当我们进行开发板的适配时,则需要根据开发板引脚的使用情况,进行引脚复用的配置等操作。针对pinctrl子系统包括如下几个概念:

  • pin复用: 包括复用模式、复用相关寄存器等;
  • pin配置: 针对有些引脚需要进行相关的配置,如pullup、pulldown、slew-rate、drive-open-drain等;
  • Pin group:几个pin组合在一起,可以对该组合中的引脚进行配置。如上面所说的{pin8、pin9},即可作为一个group(该group即可以作为iic0的引脚使用,也可以配置成can0的引脚使用)。
  • Pin function:表示实现的功能,如上述的iic0,则作为引脚使用的一种功能(iic引脚),而一个function是需要和一个或者多个group绑定的,假如我们规定pin12、pin13也可以作为ii0的引脚,那么function iic0,则可以与group{pin8、pin9}、group{pin12、pin13}关联,而具体使用哪种group作为iic0,则由具体的开发板设计相关。


pinctrl子系统实现的目标

  1. 我们先说下没有pinctrl或者不使用pinctrl时,引脚配置的方式。我们可以在bootloader下进行引脚复用的设置(如nxp ls系列的soc,通过设置rcw进行引脚复用配置,并没有使用pinctrl子系统),或者在linux kernel的板级文件中进行引脚复用的配置。
  2. 在进行复用配置时,出现了一个引脚同时配置两个功能的错误情况,这就给调试带来了困难,查了半天发现引脚复用错了。。。
  3. 每一个芯片厂家实现了各自的引脚复用设计(如ti omap2在板级文件中就实现了引脚复用相关的设置)

pinctrl子系统实现的目标

针对上面的一些问题,linux引入了pinctrl子系统,用于解决上述问题,并提供引脚复用相关的操作,下面我们简要说明下pinctrl子系统的设计要点

  1. 针对一款soc芯片,实现引脚定义、所有group的定义、所有可能的function定义,并提供引脚复用设置相关的接口、引脚配置相关的接口,这就对应到pinctrl子系统的pinctrl device;
  2. 针对每一款基于soc设计的开发板,均提供本开发板对应的引脚复用情况,包括使用哪些function(如使用iic0、iic1、can1、spi0);针对每一个使用的function,选用哪一个group(如上面ii0可选2个group,而在此处需要确定具体使用哪一个group),这就对应的pinctrl子系统的pinctrl maps。
  3. 在设备控制器驱动中,实现引脚复用及引脚配置的操作(如在iic控制器驱动或者spi控制器驱动中,完成spi对应引脚的配置操作)。

基本上完成以上功能,即完成了pinctrl子系统的设计目录,其中pinctrl device由芯片厂家实现;而pinctrl maps则由具体的开发板设计厂家实现。

但是我们考虑一个问题,基于pinctrl子系统之后,具体设备相关引脚复用是由具体的设备驱动实现了,那岂不是每一个设备控制器驱动开发时均需要在设备驱动中进行引脚复用设置,这相比以前的在板级文件中进行引脚复用相比,是不是不够完美呢?

针对这个问题,就需要借助设备驱动模型中来解决了。该设备驱动模型在完成device与driver的match之后,且在调用bus/driver->probe之前进行引脚复用的设置(调用pinctrl_bind_pins实现引脚复用的设置以及引脚配置操作),这样的话每一个设备驱动亦不需要关注引脚配置相关信息(前面已经介绍了linux设备驱动模型,此处不再细述)。


那pinctrl子系统又是如何解决“在进行引脚复用配置时,一个引脚同时配置两个功能的错误情况”呢?

这个问题也很好解决,之前我们在分析gpio子系统中,知道gpio引脚的使用与释放时,需要进行申请与释放,当调用gpio_requset申请一个gpio后,再对该gpio进行申请即出错。而pinctrl子系统针对pin引脚的设置,也定义了类型的函数pin_request、pin_free,在pin_request中若已有device对该pin进行了配置,则返回失败,从而可解决该问题。


pinctrl的系统软件框架

下面我们简要说明下pinctrl 子系统的软件框架。从整体上理解pinctrl子系统的设计。如下图所示即为pinctrl子系统的主要分层,可分为pinctrl device、pinctrl map、pinctrl 对外接口等几部分。

  1. 抽象pin ctrl device,作为对pin controller 的逻辑抽象,每一个soc型号可抽象一个pin ctrl device;
  2. 每一个pin ctrl device,包括设置pin controller的方法,包括引脚复用的设置方法、引脚配置的设置方法等、该pin controller支持的pin定义、group定义、function定义等
  3. 一个pin ctrl device,可以对应多个pin maps,因为我们可能针对一款soc设置多款board,每款board只是引脚复用、外设等有所差别,因此使用pin ctrl maps表示一款board的引脚复用情况,从而一个pin ctrl device可以对应多个pin maps;
  4. Pin ctrl 子系统提供了引脚复用接口、引脚配置接口、pinctrl device注册与注销接口、也提供了pin maps注册与注销的接口
  5. 针对内核支持设备树的情况,则在进行device、driver绑定时(调用pinctrl_bind_pins),则会解析设备树参数,实现pin maps的注册,并调用pinctrl_select_state,进行引脚复用及配置的设置等;
  6. 针对内核不支持设备树的情况,若要使用pinctrl子系统,则可以在soc对应的板级文件中,调用pinctrl_register_maps完成pin maps的注册,然后在进行device、driver绑定时(调用pinctrl_bind_pins),则调用pinctrl_select_state,进行引脚复用及配置的设置等;



以上即是pinctrl子系统的框架,pinctrl 子系统确实解决了引脚复用的功能,且pinctrl子系统通过对pin controller抽象、pin mux、pin config、pin group、pin group、pin function、pinctrl_map等抽象,个人感觉pinctrl device、pinctrl_map的抽象真的很好,将soc pin controller引脚定义及操作、基于某一个soc设计多个开发板对应的引脚复用情况抽象为pinctrl_map,这样就将soc pin 复用功能、不同开发板的引脚复用配置给区分开。


相关推荐