一.? 简介
本文简单了解一下Linux内核代码中, pinctrl子系统的驱动实现。
注意:本文会涉及到
Linux
驱动分层与分离、平台设备驱动等还未讲解的知识
,所以,也不会影响后续的实验。
二.? Linux内核pinctrl子系统驱动
1.??probe函数
所有的东西都已经准备好了,包括寄存器地址和寄存器值,
Linux
内核相应的驱动文件就会根据这些值来做相应的初始化。
接下来就找一下哪个驱动文件来做这一件事情,设备节点
iomuxc
中
compatible
属性的值为“
fsl,imx6ul-iomuxc
”,在
Linux
内核源码中(NXP官方提供的)全局搜索“
fsl,imx6ul-iomuxc
”
字符串,就会找到对应的驱动文件。
在文件
drivers/pinctrl/freescale/pinctrl-imx6ul.c
中有如下内容:
static struct of_device_id imx6ul_pinctrl_of_match[] = {
{ .compatible = "fsl,imx6ul-iomuxc", .data = &imx6ul_pinctrl_info, },
{ .compatible = "fsl,imx6ull-iomuxc-snvs", .data = &imx6ull_snvs_pinctrl_info, },
{ /* sentinel */ }
};
static int imx6ul_pinctrl_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct imx_pinctrl_soc_info *pinctrl_info;
match = of_match_device(imx6ul_pinctrl_of_match, &pdev->dev);
if (!match)
return -ENODEV;
pinctrl_info = (struct imx_pinctrl_soc_info *) match->data;
return imx_pinctrl_probe(pdev, pinctrl_info);
}
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,
};
第
1~5
行,
of_device_id
结构体数组,前面说过,
of_device_id
里面保存着这个驱动文件的兼容性值,设备树中的
compatible
属性值会和
of_device_id
中的所
有兼容性字符串比较,查看是否可以使用此驱动。
imx6ul_pinctrl_of_match
结构体数组一共有两
个兼容性字符串,分别为“
fsl,imx6ul-iomuxc
”和“
fsl,imx6ull-iomuxc-snvs
”,因此,
iomuxc
节点
与此驱动匹配,所以
pinctrl-imx6ul.c
会完成
I.MX6ULL
的
PIN
配置工作。
第
22~30
行,
platform_driver
是平台设备驱动,
platform_driver
是个结构体,有个
probe
成员变量。在这里大家只需要知道,当设备和驱动匹配
成功以后,
platform_driver
的
probe
成员变量所代表的函数就会执行。
在28
行设置
probe
成员变
量为
imx6ul_pinctrl_probe
函数,因此,
imx6ul_pinctrl_probe
这个函数就会执行,可
以认为
imx6ul_pinctrl_probe
函数就是
I.MX6ULL
这个
SOC
的
PIN
配置入口函数。
2. ? pinctrl子系统驱动框架
以此为入口,如下图
所示的函数调用路径:
下一篇文章具体了解 pinctrl子系统驱动所做的工作。