1、前言
在嵌入式系统中,许多SoC的内部都包含了pin控制器,通过芯片内部的pin控制器,我们可以配置一个或者一组引脚的状态和功能特性,Linux内核为了统一各SoC厂商的引脚管理,提供了pinctrl子系统。
2、引脚功能分类
嵌入式芯片手册往往有一个GPIO控制的章节来描述SoC的引脚如何进行配置,该描述具有大量的寄存器操作,但是通过配置这些寄存器实现的功能基本有三类,如下:
(1)通过设置pin controller硬件的控制单元,可以实现
(1.1)引脚的功能配置,例如设定I/O引脚是普通的GPIO输入输出功能,还是具有特殊功能的引脚;
(1.2)引脚特性配置,例如引脚内部的上/下拉电阻和驱动强度的设定。
(2)如果一组pin被配置成SPI,则将会和SPI controller连接,如果配置成了GPIO,则将会和GPIO controller进行连接,通过配置GPIO controller的寄存器,可以实现
(2.1)设置GPIO的方向,例如输入或者输出;
(2.2)当GPIO设置为输出方向时,能够设定该引脚的电平是高电平还是低电平;
(2.3)当GPIO设置为输入方向时,能够读取该引脚的电平状态。
(3)如果IO口具有中断控制功能时,通过访问IO口的中断控制寄存器,可以实现
(3.1)设置中断控制是否使能;
(3.2)设置中断的触发方式,例如上升沿/下降沿触发;
(3.3)通过设置寄存器将中断状态清除。
3、通过软件抽象来掩盖硬件差异
在Linux的内核的pinctrl系统架构中,使用了3个软件模块来对应上述的三类功能,如下:
(1)pinctrl子系统,用于pin controller硬件的驱动软件子系统;
(2)GPIO subsystem,用于GPIO controller硬件的驱动软件子系统;
(3)GPIO interrupt chip driver,该模块作为interrupt subsystem的底层硬件驱动模块存在。
下图为pinctrl subsystem的模块图:
底层的specific pin controller driver是硬件相关的模块,与嵌入式SoC相关,pin control core模块是一个与硬件无关的模块,它抽象了所有pin controller的硬件特性,它对用户(other driver)提供了顶层的接口函数,因此,用户不再需要关注pin controller的硬件底层相关知识。
下图则是GPIO subsystem的模块图:
该软件框架图和pinctrl subsystem的软件框架图一样,其软件抽象的思想是一样的,内部的具体实现不一样。
4、pinctrl子系统相关文件
(1)核心源文件
在kernel/drivers/pinctrl目录下,包含了pinctrl子系统的核心驱动文件:
在最后的源文件pinctrl-xxx.c,举个例子,例如高通msm提供的pinctrl子系统底层驱动文件有如下文件pinctrl-msm.c、pinctrl-msm.h、pinctrl-msm-tlmm.c。
(2)内核模块提供的接口文件
Linux内核中很多模块需要用到pinctrl子系统的服务,因此需要提供pinctrl子系统的外部接口和相关的数据结构,这些头文件在kernel/include/linux/pinctrl目录下,列表如下:
(3)与SoC相关的底层pinctrl子系统驱动接口
pinctrl子系统提供给底层驱动实现的头文件如下:
5、pinctrl子系统与其它内核模块关系
pinctrl子系统与其它内核模块的关系图如下所示:
在上图可以看到,GPIO子系统的管理归属于pinctrl子系统,并且pinctrl子系统与设备驱动模型也有密切的联系。