Platform Bus

Posted 四季帆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Platform Bus相关的知识,希望对你有一定的参考价值。

1. 注册driver概述

platform_driver_register()注册driver的过程

platform_driver_register
    -->driver_register
        -->bus_add_driver
            -->driver_attach
                -->bus_for_each_dev      //传入函数指针__driver_attach
                    -->__driver_attach
                        -->driver_match_device(drv, dev) //先匹配
                            -->platform_match
                        -->driver_probe_device(drv, dev) //匹配上以后再进行绑定
                           -->really_probe(dev, drv)
                               -->drv->probe(dev)    //执行该driver提供的probe函数,注意platform bus并没有提供probe函数

2. 具体代码分析

注册driver到platform bus(总线)上

int platform_driver_register(struct platform_driver *drv)
{
	drv->driver.bus = &platform_bus_type;   //将driver 挂载到platform bus
	if (drv->probe)
		drv->driver.probe = platform_drv_probe;
    ······
	return driver_register(&drv->driver);
}

int driver_register(struct device_driver *drv)
{
	other = driver_find(drv->name, drv->bus);
	if (other) {
		//在drv所在的bus上遍历,如果在该bus上找到该drv的名称,则返回错误码
		return -EBUSY;
	}   
	ret = bus_add_driver(drv);   //drv对应的bus上没有该drv,此时将该drv注册到它所属的drv
}

int bus_add_driver(struct device_driver *drv)
{
	if (drv->bus->p->drivers_autoprobe) 
		error = driver_attach(drv);
	kobject_uevent(&priv->kobj, KOBJ_ADD);
	return 0;
 }

将刚刚注册的driver 和platform bus 上挂载的所有device 进行匹配

int driver_attach(struct device_driver *drv)
{  
	return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}

int bus_for_each_dev(struct bus_type *bus, struct device *start,
		     void *data, int (*fn)(struct device *, void *))
{
    //遍历设备链表,通过fn()函数将每一个device和传进来的drv进行匹配
	while ((dev = next_device(&i)) && !error)
		error = fn(dev, data);   //fn()是回调函数__driver_attach
}

static int __driver_attach(struct device *dev, void *data)
{
	struct device_driver *drv = data;

	if (!driver_match_device(drv, dev))    //不匹配就直接返回0
		return 0;
	if (!dev->driver)                      //此时已经匹配上了,但是dev和drv还没联系起来(或者说还没绑定)
		driver_probe_device(drv, dev);  //调用probe()进行设备的初始化
	return 0;
}

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);
}

匹配之后将driver 和device 绑定

int driver_probe_device(struct device_driver *drv, struct device *dev)
{
	ret = really_probe(dev, drv);
 }

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的主要内容,如果未能解决你的问题,请参考以下文章

Platform Bus

linux设备驱动之platform平台总线工作原理

Platform Bus

Platform Bus

linux platform device/driver--Platform Device和Platform_driver注册过程之代码对比

[platform]Device和Driver注册顺序