int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;/*关联总线*/
/*关联driver的设备方法*/
if (drv->probe)
drv->driver.probe = platform_drv_probe;
if (drv->remove)
drv->driver.remove = platform_drv_remove;
if (drv->shutdown)
drv->driver.shutdown = platform_drv_shutdown; return driver_register(&drv->driver);/*注册驱动*/
} /******************************************************************************/
struct platform_driver {
int (*probe)(struct platform_device *);/*匹配到设备后调用,下面分析内核代码怎么调用的*/
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
}; struct bus_type platform_bus_type = {
.name = "platform",
.dev_attrs = platform_dev_attrs,
.match = platform_match,
.uevent = platform_uevent,
.pm = &platform_dev_pm_ops,
};
/********************************************************************************/ int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other; BUG_ON(!drv->bus->p); if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name); other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
} ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
} int bus_add_driver(struct device_driver *drv)
{
struct bus_type *bus;
struct driver_private *priv;
int error = ; bus = bus_get(drv->bus);
if (!bus)
return -EINVAL; pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
error = -ENOMEM;
goto out_put_bus;
}
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister; if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
module_add_driver(drv->owner, drv); error = driver_create_file(drv, &driver_attr_uevent);
if (error) {
printk(KERN_ERR "%s: uevent attr (%s) failed\n",
__func__, drv->name);
}
error = driver_add_attrs(bus, drv);
if (error) {
/* How the hell do we get out of this pickle? Give up */
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name);
} if (!drv->suppress_bind_attrs) {
error = add_bind_files(drv);
if (error) {
/* Ditto */
printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
__func__, drv->name);
}
} kobject_uevent(&priv->kobj, KOBJ_ADD);
return ; out_unregister:
kobject_put(&priv->kobj);
kfree(drv->p);
drv->p = NULL;
out_put_bus:
bus_put(bus);
return error;
} int driver_attach(struct device_driver *drv)
{
/*对总线上的每一个设备都调用__driver_attach*/
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
} static int __driver_attach(struct device *dev, void *data)
{
struct device_driver *drv = data; /*
* Lock device and try to bind to it. We drop the error
* here and always return 0, because we need to keep trying
* to bind to devices and some drivers will return an error
* simply if it didn't support the device.
*
* driver_probe_device() will spit a warning if there
* is an error.
*/ if (!driver_match_device(drv, dev))
return ; if (dev->parent) /* Needed for USB */
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
device_unlock(dev);
if (dev->parent)
device_unlock(dev->parent); return ;
} static inline int driver_match_device(struct device_driver *drv,
struct device *dev)
{
/*调用总线的match去匹配设备和驱动*/
return drv->bus->match ? drv->bus->match(dev, drv) : ;
} int driver_probe_device(struct device_driver *drv, struct device *dev)
{
int ret = ; if (!device_is_registered(dev))
return -ENODEV; pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name); pm_runtime_get_noresume(dev);
pm_runtime_barrier(dev);
ret = really_probe(dev, drv);
pm_runtime_put_sync(dev); return ret;
}
static int really_probe(struct device *dev, struct device_driver *drv)
{
int ret = ; atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
WARN_ON(!list_empty(&dev->devres_head)); dev->driver = drv;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
__func__, dev_name(dev));
goto probe_failed;
}
/**********************************************************************************/
if (dev->bus->probe) {/*首先看总线有没有probe函数,若有则调用,而平台总线没有probe*/
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;
} else if (drv->probe) {/*然后看驱动有没有probe函数,若有则调用,*/
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
/************************************************************************************/ driver_bound(dev);
ret = ;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
goto done; probe_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL; if (ret != -ENODEV && ret != -ENXIO) {
/* driver matched but the probe failed */
printk(KERN_WARNING
"%s: probe of %s failed with error %d\n",
drv->name, dev_name(dev), ret);
}
/*
* Ignore errors returned by ->probe so that the next driver can try
* its luck.
*/
ret = ;
done:
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
} /*平台总线的match逻辑*/
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); /* match against the id table first */
if (pdrv->id_table)
return platform_match_id(pdrv->id_table, pdev) != NULL; /* fall-back to driver name match */
return (strcmp(pdev->name, drv->name) == );/*驱动名字与设备名字要匹配*/
}

总结一下:

platform_driver_register

  driver_register

    bus_add_driver

      driver_attach

        __driver_attach

          driver_probe_device

            really_probe

               if (dev->bus->probe) {/*首先看总线有没有probe函数,若有则调用,而平台总线没有probe*/
                                                ret = dev->bus->probe(dev);
                                        if (ret)
                                                goto probe_failed;
                                         } else if (drv->probe) {/*然后看驱动有没有probe函数,若有则调用,*/
                                                 ret = drv->probe(dev);
                                         if (ret)
                                                goto probe_failed;
                                        }

platform_driver_register()--如何match之后调用probe的更多相关文章

  1. (转)platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备

     platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备 2011-10-24 19:47:07 分类: LINUX   kernel_init中d ...

  2. platform_driver_register,什么时候调用PROBE函数 注册后如何找到驱动匹配的设备【转】

    转自:http://blog.chinaunix.net/uid-25508271-id-2979412.html kernel_init中do_basic_setup()->driver_in ...

  3. 注册驱动时如何调用probe函数 ?

    platform_driver_register       driver_register             bus_add_driver    //把驱动放入总线的驱动链表里         ...

  4. platform_device和platform_driver的注册过程,及probe函数何时调用的分析 ⭐⭐⭐

    add  platform_device之后,需要注意的一个地方是这里,add是通过系统初始化里边调用platform_add_devices把所有放置在板级platform_device数组中的所有 ...

  5. linux设备驱动归纳总结(八):2.match.probe.remove

    linux设备驱动归纳总结(八):2.总线.设备和驱动的关系 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  6. [驱动注册]platform_driver_register()与platform_device_register()

    [驱动注册]platform_driver_register()与platform_device_register()      设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册时进行绑定. ...

  7. (linux)platform_driver_probe与platform_driver_register的区别

      [驱动注册]platform_driver_register()与platform_device_register()          设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册 ...

  8. Linux+I2C总线分析(主要是probe的方式)

    Linux I2C 总线浅析 ㈠ Overview Linux的I2C体系结构分为3个组成部分: ·I2C核心: I2C核心提供了I2C总线驱动和设备驱动的注册.注销方法,I2C通信方法(即“algo ...

  9. I2C驱动程序框架probe道路

    基于Linux的I2C驱动器.采纳probe道路.根据这个框架,如下面就可以写任何支持I2C总线设备Linux驱动器. I2C设备连接到cpu具体i2c接口.被安装在cpu的i2c适配器.i2c设备和 ...

随机推荐

  1. Spring3之事务管理

    事务管理是企业应用开发中确保数据完整性和一致性的关键技术.对于并发和分布式坏境中从不可预期的错误中恢复来说,事务管理特别重要.Spring作为一个企业应用框架,在不同的事务管理API之上提供了一个抽象 ...

  2. Android 开发中的屏幕适配技术详解

    本文主要介绍Android开发中比较头疼繁琐的一个问题-屏幕适配问题.主要从适配原因.基本核心概念.适配方法等方面介详细 介绍从而是的深入或者进一步对Android屏幕适配技术的掌握和理解. 真题园网 ...

  3. c++下new与delete基础用法

    delete 释放new分配的单个对象指针指向的内存 delete[] 释放new分配的对象数组指针指向的内存那么,按照教科书的理解,我们看下下面的代码: ]; delete a; //方式1 del ...

  4. Find security bugs学习笔记V1.0

    Find security bugs学习笔记V1.0 http://www.docin.com/p-779309481.html

  5. nginx 安装部署

    1. 安装passenger:sudo gem install passenger 2. 找到passenger的安装目录,一般是 cd  /var/lib/gems/2.0.0/gems/passe ...

  6. asp发布至IIS

    最近做的一个任务是使用asp写的,显示的是数据库的报表,但是将报表当前目录发布至IIS后,发现还是运行不了 Set conn = Server.CreateObject("ADODB.Con ...

  7. JDBC的几个步骤

    JDBC:JAVA访问数据库的解决方案.几个步骤:1.加载驱动类; 2.与数据库建立连接:         3.执行SQL语句   4.处理结果集 5.关闭连接1. 第一步:加载驱动类: 需要注意:不 ...

  8. Spark技术内幕:Client,Master和Worker 通信源码解析

    http://blog.csdn.net/anzhsoft/article/details/30802603 Spark的Cluster Manager可以有几种部署模式: Standlone Mes ...

  9. asp中的几个取整函数fix(),int(),round()的用法

    asp中的几个取整函数是:fix(),int(),round(); Int(number).Fix(number)函数返回数字的整数部分.number 参数可以是任意有效的数值表达式.如果 numbe ...

  10. 转载:flash 跨域 crossdomain.xml

    转载自http://hi.baidu.com/bozz_/item/e8b1c7c4ca31317489ad9e91 flash 跨域 crossdomain.xml 一.概述 位于www.cross ...