参考博客:https://blog.csdn.net/thisway_diy/category_11311709.html
一、概述
Linux
驱动讲究驱动分离与分层,pinctrl
和 gpio
子系统就是驱动分离与分层思想下的产物,驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架。
无论哪种芯片都有类似下图结构:
要想让 pin A
、pin B
用于 GPIO
,需要设置 IOMUX
让它们连接到 GPIO
模块;
要想让 pinA
、pin B
用于 I2C
,需要设置 IOMUX
让它们连接到 I2C
模块。
所以 GPIO
、I2C
应该是并列的关系,它们能够使用之前,需要设置 IOMUX
。有时候并不仅仅是设置 IOMUX
,还要配置引脚,比如上拉、下拉、开漏等等。
现在的芯片动辄几百个引脚,在使用到 GPIO
功能时,让你一个引脚一个引脚去找对应的寄存器,效率低下且工作重复,因此,产生一个专业职业 - BSP
工程师。BSP
工程师要把引脚的复用、配置抽出来,做成 Pinctrl
子系统,给 GPIO
、I2C
等模块使用,将 GPIO
功能抽出来,做成 GPIO
子系统( BSP
工程师是更懂他自家的芯片)。这样效率更高,且避免重复开发。
二、为什么需要 GPIO 子系统
大多数的芯片,没有单独的 IOMUX
模块,引脚的复用、配置等等,就是在 GPIO
模块内部实现的。在硬件上 GPIO
和 Pinctrl
是如此密切相关,在软件上它们的关系也非常密切。
三、重要概念
主要参考文档:Documentation\devicetree\bindings\pinctrl\pinctrl-bindings.txt
。
这会涉及 2
个对象:pin controller
、client device
。
pin controller
:可以用它来复用引脚、配置引脚。
client device
:声明自己要使用哪些引脚的哪些功能,怎么配置它们。
1、pin controller
在芯片手册里找不到 pin controller
,它是一个软件上的概念。可以认为它对应 IOMUX
- 用来复用引脚,还可以配置引脚(比如上下拉电阻等)。
注意,pin controller
和 GPIO Controller
不是一回事,前者控制的引脚可用于 GPIO
功能、I2C
功能;后者只是把引脚配置为输入、输出等简单的功能。即先用 pin controller
把引脚配置为 GPIO
,再用 GPIO Controler
把引脚配置为输入或输出。
2、client device
“客户设备”,谁的客户?Pinctrl
系统的客户,那就是使用 Pinctrl
系统的设备,使用引脚的设备。
它在设备树里会被定义为一个节点,在节点里声明要用哪些引脚。
3、总结
第 1
张图是 client device
节点。
第 2、3、4
张图是 pin controller
节点。
以上图片截取正点原子提供 imx6ull
源码。
1、pin state
对于一个 “client device”
来说,比如对于一个 usdhc1
设备,它有多个 “状态”:default
、state_100mhz
、state_200mhz
等,那对应的引脚也有这些状态。
以上现象该如何理解?
上图中 pinctrl-names
里定义了 2
种状态::default
、state_100mhz
、state_200mhz
。
第 0
种状态用到的引脚在 pinctrl-0
中定义,它是 pinctrl_usdhc1
。
第 1
种状态用到的引脚在 pinctrl-1
中定义,它是 pinctrl_usdhc1_100mhz
。
第 2
种状态用到的引脚在 pinctrl-2
中定义,它是 pinctrl_usdhc1_200mhz
。
当这个设备处于 default
状态时,pinctrl
子系统会自动根据上述信息把所用引脚配置为 pinctrl_usdhc1
中相关值。
当这个设备处于 pinctrl_usdhc1_100mhz
状态时,pinctrl
子系统会自动根据上述信息把所用引脚配置为 pinctrl_usdhc1_100mhz
中相关值。
当这个设备处于 state_200mhz
状态时,pinctrl
子系统会自动根据上述信息把所用引脚配置为 pinctrl_usdhc1_200mhz
中相关值。
2、groups和function
一个设备会用到一个或多个引脚,这些引脚就可以归为一组 (group
);
这些引脚可以复用为某个功能:function
。
当然:一个设备可以用到多组引脚,比如 A1
、A2
两组引脚,A1
组复用为 F1
功能,A2
组复用为 F2
功能。
3、Generic pin multiplexing node和Generic pin configuration node
在上图左边的 pin controller
节点中,有子节点或孙节点,它们是给 client device
使用的。
可以用来描述复用信息:哪组(group
)引脚复用为哪个功能(function
);
可以用来描述配置信息:哪组(group
)引脚配置为哪个设置功能(setting
),比如上拉、下拉等。
注意:pin controller
节点的格式,没有统一的标准!!!!每家芯片都不一样。甚至上面的 group
、function
关键字也不一定有,但是概念是有的。
四、pinctrl子系统使用
这是透明的,我们的驱动基本不用管。当设备切换状态时,对应的pinctrl就会被调用。
1、设备树
2、驱动代码执行流程
驱动程序位置:
drivers\pinctrl\freescale\pinctrl-imx6ul.c
drivers\pinctrl\freescale\pinctrl-imx.c
调用过程:
imx6ul_pinctrl_probe
imx_pinctrl_probe(pdev, pinctrl_info);
imx_pinctrl_desc->name = dev_name(&pdev->dev);
imx_pinctrl_desc->pins = info->pins;
imx_pinctrl_desc->npins = info->npins;
imx_pinctrl_desc->pctlops = &imx_pctrl_ops;
imx_pinctrl_desc->pmxops = &imx_pmx_ops;
imx_pinctrl_desc->confops = &imx_pinconf_ops;
imx_pinctrl_desc->owner = THIS_MODULE;
ret = imx_pinctrl_probe_dt(pdev, info);
ipctl->pctl = devm_pinctrl_register(&pdev->dev,
imx_pinctrl_desc, ipctl);