在上一篇文章中,dt_to_map_one_config函数中,需要调用具体pinctrl driver向子系统注册的pin desc结构体中的底层硬件配置函数,pin desc结构体是由子系统抽象出的用来描述一个pin controller的结构体。本篇文章从一个具体pinctrl platform driver和由设备树生成中pinctrl platform device的match过程开始,一步步分析pin desc结构体的创建和注册过程。
pinctrl_0: pinctrl@56000000 {
compatible = "samsung,s3c2440-pinctrl"
reg = <0x56000000 0x1000>;
gpa: gpa {
gpio-controller;
#gpio-cells = <2>; /* 以后想使用gpa bank中的引脚时, 需要2个u32来指定引脚 */
};
gpb: gpb {
gpio-controller;
#gpio-cells = <2>;
};
uart0_data: uart0-data {
samsung,pins = "gph-0", "gph-0";
samsung,pin-function = <2>;
/* 在GPHCON寄存器中gph0,gph1可以设置以下值:0 --- 输入功能 1 --- 输出功能 2 --- 串口功能*/
};
uart0_sleep: uart0_sleep {
samsung,pins = "gph-0", "gph-1";
samsung,pin-function = <0>;
};
};
serial@50000000 {
......
pinctrl-names = "default", "sleep"; /* 既是名字, 也称为state(状态) */
pinctrl-0 = <&uart0_data>;
pinctrl-1 = <&uart0_sleep>;
};
linux kernel使用统一设备模型,bus、driver和device形成了设备模型中的铁三角。对于platform这种类型的bus,其铁三角数据是platform_bus_type(表示platform这种类型的bus)、struct platform_device(platform bus上的device)、struct platform_driver(platform bus上的driver)。每次系统增加一个platform_driver或platform_device,platform_bus_type都会启动scan过程,找到相互匹配的platform_driver和platform_device之后,就调用platform_driver的probe函数。
static int platform_match(struct device *dev, struct device_driver *drv)
{
struct platform_device *pdev = to_platform_device(dev);
struct platform_driver *pdrv = to_platform_driver(drv);
...
/* Attempt an OF style match first */
if (of_driver_match_device(dev, drv))
return 1;
...
}
static inline int of_driver_match_device(struct device *dev,
const struct device_driver *drv)
{
return of_match_device(drv->of_match_table, dev) != NULL;
}
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev)
{
if ((!matches) || (!dev->of_node))
return NULL;
return of_match_node(matches, dev->of_node);
}
OF style的匹配过程主要通过platform_driver的struct of_device_id和platform_device的设备树节点内容进行对比,例子中的pinctrl节点的compatible = "samsung,s3c2440-pinctrl",三星提供的pinctrl-samsung.c文件中的驱动程序可以匹配种类型的pinctrl,当然也支持s3c2440,在该文件中,可以找到对应的struct of_device_id表如下所示,该表用来填充struct platform_driver。
static const struct of_device_id samsung_pinctrl_dt_match[] = {
{ .compatible = "samsung,exynos3250-pinctrl",
.data = (void *)exynos3250_pin_ctrl },
...
{ .compatible = "samsung,s3c2440-pinctrl",
.data = s3c2440_pin_ctrl },
...
};
static struct platform_