Linux Platform Bus(3) - 平台设备注册

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;
    if (!bus)     /不是所有的dev都有bus,比如input dev/
    	return;
   //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);
	}
 }

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值