一、开发环境
- SOC : IMX6ULL
- 系统内核:4.1.15
二、问题描述
Linux 内核提供了pinctrl 和gpio 子系统用于GPIO 驱动。pinctrl_ctrl 子系统从设备树中获取pin 信息,然后配置pin复用 和pin电气特征(上/下拉,速度,驱动能力等)。
如下是一个led 在设备树中的pin信息:
pinctrl_led:ledgrp{
fsl,pins = <
MX6UL_PAD_GPIO1_IO03__GPIO1_IO03 0x10B0
>
};
我们在设备树中添加了pin 信息,但是我们写设备驱动程序的时候,并没有调用API 去初始化pin,在哪个阶段,初始化了pin 信息呢?
三、过程分析
我们将GPIO1 IO03 这个IO 用于led 控制,来进行这个过程的说明。
3.1 I.MX6U IO
I.MX6U IO 分为两个域
- IOMUXC_SNVS ( SNVS 域)
- IOMUXC (通用域)
IOMUXC 域的设备树描述
iomuxc 在 设备树头文件 imx6ull.dtsi 的描述如下:
iomuxc: iomuxc@020e0000 {
compatible = "fsl,imx6ul-iomuxc";
reg = <0x020e0000 0x4000>;
};
3.2 pin 信息
GPIO1 IO03 这个IO 属于 IOMUXC (通用域),pin 信息要添加在 设备树 IOMUXC 节点里面,作为子节点。
3.3 IOMUXC 对应的驱动程序
Linux 内核根据 IOMUXC 的compatible 属性值查找IOMUXC 的驱动程序,找到 imx6ul_pinctrl_driver 这个驱动,这个驱动of_match 表中的compatible 属性值与IOMUXC 的compatible 值一致。源码在pinctrl-imx6ul.c 中。
imx6ul_pinctrl_driver 是platform 框架下的设备驱动程序,当设备和驱动匹配的时候,probe 函数会执行。
3.4 imx6ul_pinctrl_probe
static struct platform_driver imx6ul_pinctrl_driver = {
.driver = {
.name = "imx6ul-pinctrl",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(imx6ul_pinctrl_of_match),
},
.probe = imx6ul_pinctrl_probe,
.remove = imx_pinctrl_remove,
};
从 imx6ul_pinctrl_probe 逐层查看源码实现,发现最终是在 imx_pinctrl_probe_dt 函数负责读取pin 信息,并通过pinctrl_register 注册到系统。
四、结论
在系统启动过程中,当pinctrl 驱动程序和设备树中的设备节点匹配时,pinctrl 驱动程序的probe 函数会执行,完成pin 信息的初始化。