Linux 内核提供了pinctrl 和gpio 子系统用于GPIO 驱动。pinctrl_ctrl 子系统从设备树中获取pin 信息,然后配置pin复用 和pin电气特征(上/下拉,速度,驱动能力等)。
如下是一个led 在设备树中的pin信息:
pinctrl_led:ledgrp{fsl,pins = };
我们在设备树中添加了pin 信息,但是我们写设备驱动程序的时候,并没有调用API 去初始化pin,在哪个阶段,初始化了pin 信息呢?
我们将GPIO1 IO03 这个IO 用于led 控制,来进行这个过程的说明。
iomuxc 在 设备树头文件 imx6ull.dtsi 的描述如下:
iomuxc: iomuxc@020e0000 {compatible = "fsl,imx6ul-iomuxc";reg = <0x020e0000 0x4000>;};
GPIO1 IO03 这个IO 属于 IOMUXC (通用域),pin 信息要添加在 设备树 IOMUXC 节点里面,作为子节点。
Linux 内核根据 IOMUXC 的compatible 属性值查找IOMUXC 的驱动程序,找到 imx6ul_pinctrl_driver 这个驱动,这个驱动of_match 表中的compatible 属性值与IOMUXC 的compatible 值一致。源码在pinctrl-imx6ul.c 中。
imx6ul_pinctrl_driver 是platform 框架下的设备驱动程序,当设备和驱动匹配的时候,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 信息的初始化。