Platform Bus
Posted 四季帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Platform Bus相关的知识,希望对你有一定的参考价值。
1. 注册device概述
platform_device_register()注册device的过程
platform_device_register
-->platform_device_add
-->device_add
-->bus_probe_device
-->device_attach
-->bus_for_each_drv //传入函数指针__device_attach
-->__device_attach
-->driver_match_device(drv, dev) //先匹配
-->platform_match
-->driver_probe_device(drv, dev) //匹配上以后再进行绑定
-->really_probe(dev, drv);
-->drv->probe(dev) //执行与该device绑定的driver提供的probe函数,注意platform bus并没有提供probe函数
2. 具体代码分析
int platform_device_register(struct platform_device *pdev)
{
device_initialize(&pdev->dev);
return platform_device_add(pdev);
}
int platform_device_add(struct platform_device *pdev)
{
if (!pdev->dev.parent)
pdev->dev.parent = &platform_bus;
pdev->dev.bus = &platform_bus_type; //将device挂载到platform bus
if (pdev->id != -1) //device命名的两种方式
dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
else
dev_set_name(&pdev->dev, "%s", pdev->name);
ret = device_add(&pdev->dev);
}
int device_add(struct device *dev)
{
error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
······
bus_probe_device(dev);
}
void bus_probe_device(struct device *dev)
{
struct bus_type *bus = dev->bus;
//bus->p是在bus_register()中赋值的,前面有分析到
if (bus && bus->p->drivers_autoprobe)
ret = device_attach(dev);
}
将刚刚注册的device 和platform bus 上挂载的所有drivers 进行匹配
int device_attach(struct device *dev)
{
if (dev->driver) { //device已经和driver匹配上时。注意和driver_register流程中的really_probe()中的操作相呼应
ret = device_bind_driver(dev);
} else { //device还没和driver匹配时,遍历drivers链表,与driver匹配
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
}
}
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
void *data, int (*fn)(struct device_driver *, void *))
{
while ((drv = next_driver(&i)) && !error)
error = fn(drv, data); //fn()回调函数__device_attach
return error;
}
static int __device_attach(struct device_driver *drv, void *data)
{
struct device *dev = data;
if (!driver_match_device(drv, dev)) //dev和drv不匹配就直接返回0
return 0;
return driver_probe_device(drv, dev); //此时已经匹配上了,但是dev和drv还没联系起来(或者说还没绑定)
}
static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{ //platform总线在初始化的时候提供了match函数,所以这里会调用platform_match(dev, drv)进行匹配
return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
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);
/*首先通过查看driver的id_table中有没有支持该dev,来确定driver和device是否匹配*/
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL;
/*如果driver中没有提供id_table,就通过比较driver和device的名字来确定是否匹配*/
return (strcmp(pdev->name, drv->name) == 0);
}
匹配之后将device 和driver 绑定
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
ret = really_probe(dev, drv);
return ret;
}
static int really_probe(struct device *dev, struct device_driver *drv)
{
dev->driver = drv; //匹配成功以后,要将dev和driver联系起来(或者说绑定)
//platform总线初始化的时候并没有提供probe()
if (dev->bus->probe) { //所以这里判断不成立
ret = dev->bus->probe(dev);
} else if (drv->probe) { //由此可见,所有的platform device和driver匹配成功后都是直接调用driver的probe()
ret = drv->probe(dev);
}
}
以上是关于Platform Bus的主要内容,如果未能解决你的问题,请参考以下文章
linux platform device/driver--Platform Device和Platform_driver注册过程之代码对比