linux 平台总线驱动模型

内核:Linux-3.14.27
一、 Linux总线设备驱动模型框架
(1) 什么是Linux总线设备驱动?
平台(platform)总线是一种虚拟的总线,在 /sys/bus/platform 目录可以看到。
平台总线三要素:平台总线、平台设备、平台驱动
平台总线原则:先分离,后合并
分离:
将设备信息封装成 platform_device,将驱动信息封装成 platform_driver,并为各自起名称,然后将 platform_device 中的 struct device 和 platform_driver 中的 struct device_driver 分别注册到设备链表和驱动链表中。
int platform_device_register(struct platform_device *pdev)
  return platform_device_add(pdev);
    ret = device_add(&pdev->dev);
int platform_driver_register(struct platform_driver *drv)
  return driver_register(&drv->driver);
    ret = bus_add_driver(drv);
(2) 为什么需要linux总线设备驱动?
随着SOC的升级,每个版本的代码都不相同,需要重写代码。人们为了提高效率,发现控制器的操作逻辑(方法)是一样的,只有寄存器地址不一样,如果将与硬件有关的
代码(platform_device)和驱动代码(platform_driver)分开,升级soc后,因为驱动方式一样,
只需要修改与硬件有关的代码就可以,实现一个驱动控制多个设备。
(3)如何使用linux 总线设备驱动?
从Linux2.6开始Linux加入了一套驱动管理和注册机制—platform平台总线驱动模型。platform平台总线是一条虚拟总线。
platform_device为相应的设备。
platform_driver为相应的驱动。
与传统的bus/device/driver机制相比,platform由内核统一进行管理,提高了代码的可移植性和安全性。所谓的platform_device并不是与字符设备、块设备和网络设备并列的概念,而是Linux系统提供的一种附加手段。Linux总线设备驱动模型的框架如下图所示:
 

linux 平台总线驱动模型_第1张图片


从图中我们可以很清楚的看出Linux平台总线设备驱动模型的整体架构。在总线设备驱动模型中,需关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。
当系统向内核注册每一个驱动程序时,都要通过调用platform_driver_register函数将驱动程序注册到总线,并将其放入所属总线的drv链表中,注册驱动的时候会调用所属总线的match函数寻找该总线上与之匹配的每一个设备,如果找到与之匹配的设备则会调用相应的probe函数将相应的设备和驱动进行绑定;
同样的当系统向内核注册每一个设备时,都要通过调用platform_device_register函数将设备注册到总线,并将其放入所属总线的dev链表中,注册设备的时候同样也会调用所属总线的match函数寻找该总线上与之匹配的每一个驱动程序,如果找到与之匹配的驱动程序时会调用相应的probe函数将相应的设备和驱动进行绑定;而这一匹配的过程是由总线自动完成的。
    接下来我们就以Linux-3.14.27版本的内核,分析一下总线设备驱动模型的执行机制。
二、platform驱动的相关数据结构
1. 结构体驱动对应的结构体platform_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;
 bool prevent_deferred_probe;
};
    可以看到platform_driver结构体中包含了probe和remove等相关操作,同时还内嵌了device_driver结构体。
2. device_driver结构体
struct device_driver {
 const char  *name;  // 驱动的名字
 struct bus_type  *bus;  // 所属总线

 struct module  *owner;
 const char  *mod_name; /* used for built-in modules */

 bool suppress_bind_attrs; /* disables bind/unbind via sysfs */

 const struct of_device_id *of_match_table;
 const struct acpi_device_id *acpi_match_table;

 int (*probe) (struct device *dev); // 驱动挂载的时候调用
 int (*remove) (struct device *dev); // 驱动卸载的时候调用
 void (*shutdown) (struct device *dev);
 int (*suspend) (struct device *dev, pm_message_t state);
 int (*resume) (struct device *dev);
 const struct attribute_group **groups;

 const struct dev_pm_ops *pm;

 struct driver_private *p;
};
    其中有一个指向driver_private的指针p,一些与其他的组件相关的联系都被移到这个结构变量中。
3. driver_private结构体
struct driver_private {
 struct kobject kobj;  // 在sysfs中代表目录本身
 struct klist klist_devices; // 驱动链表即我们上面所说的drv链表
 struct klist_node knode_bus; // 挂载在总线上的驱动链表的节点
 struct module_kobject *mkobj; // driver与相关的module之间的联系
 struct device_driver *driver;
};
#define to_driver(obj) container_of(obj, struct driver_private, kobj)
三、platform设备的相关数据结构
1. platform设备对应的结构体platform_device
struct platform_device {
 const char *name;  // 设备的名字这将代替device->dev_id,用作sys/device下显示的目录名
 int  id;  // 设备id,用于给插入给该总线并且具有相同name的设备编号,如果只有一个设备的话填-1。
 bool  id_auto;
 struct device dev;  // 内嵌device结构
 u32  num_resources; // 资源的数目
 struct resource *resource; // 资源

 const struct platform_device_id *id_entry;

 /* MFD cell pointer */
 struct mfd_cell *mfd_cell;

 /* arch specific additions */
 struct pdev_archdata archdata;
};
    可以看出platform_device结构体中包含了名字、id、资源和内嵌device结构体。
2. resource结构体
struct resource {
 resource_size_t start; // 资源的起始地址
 resource_size_t end; // 资源的结束地址
 const char *name;
 unsigned long flags; // 资源的类型
 struct resource *parent, *sibling, *child;
};
    该结构体非常重要,用于存放设备的资源信息,如IO地址、中断号等。
四、platform_driver的注册过程
platform_driver的注册过程可以简化为如下过程:
platform_driver *drv;   // 定义一个平台驱动并初始化
platform_driver_register(drv)  // 注册
 ->>__platform_driver_register(drv, THIS_MODULE)
  ->>driver_register(&drv->driver)
   ->>bus_add_driver(&drv->driver)
    ->>driver_attach(&drv->driver)
     ->>bus_for_each_dev((&drv->driver)->bus, NULL, &drv->driver, __driver_attach);
      ->>__driver_attach(&drv->driver, dev)
       ->>driver_probe_device(&drv->driver, dev)
        ->>really_probe(dev, &drv->driver)
         ->>dev->bus->probe(dev) 或 ->>&drv->driver->probe(dev)
将此过程展开如下:
1. 分配一个platform_driver结构并调用platform_driver_register函数进行注册
#define platform_driver_register(drv) \
 __platform_driver_register(drv, THIS_MODULE)
int __platform_driver_register(struct platform_driver *drv,
    struct module *owner)
{
 drv->driver.owner = owner;
 drv->driver.bus = &platform_bus_type; // 设置driver的bus的类型为platform_bus_type
 if (drv->probe)    // 如果drv含有probe(device_driver类型)则driver上的probe指向总线的probe函数
  drv->driver.probe = platform_drv_probe;
 if (drv->remove)   // 如果drv含有remove(device_driver类型)则driver上的remove指向总线的remove函数
  drv->driver.remove = platform_drv_remove;
 if (drv->shutdown)   // 如果drv含有shutdown(device_driver类型)则driver上的shutdown指向总线的shutdown函数
  drv->driver.shutdown = platform_drv_shutdown;

 return driver_register(&drv->driver); // 注册平台驱动
}
2. 调用driver_register函数将驱动添加到总线的drv链表(其中大部分工作通过调用bus_add_driver函数来完成)
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) {
  printk(KERN_ERR "Error: Driver '%s' is already registered, "
   "aborting...\n", drv->name);
  return -EBUSY;
 }

 ret = bus_add_driver(drv); // 添加驱动到总线驱动链表即我们上面所说的drv链表
 if (ret)
  return ret;
 ret = driver_add_groups(drv, drv->groups);
 if (ret) {
  bus_remove_driver(drv);
  return ret;
 }
 kobject_uevent(&drv->p->kobj, KOBJ_ADD);

 return ret;
}
3. 调用bus_add_driver函数添加驱动到总线
int bus_add_driver(struct device_driver *drv)
{
 struct bus_type *bus;
 struct driver_private *priv;
 int error = 0;

 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);  // 分配一个driver_private结构并初始化(也就是drv->p)
 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);  //将drv加入sysfs
 if (error)
  goto out_unregister;

 klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); //将drv挂入到总线的链表中
 if (drv->bus->p->drivers_autoprobe) {
  error = driver_attach(drv);    //如果总线可以自动的probe,就会调用匹配函数
  if (error)
   goto out_unregister;
 }
 module_add_driver(drv->owner, drv);   //创建driver相关的模块

 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_groups(drv, bus->drv_groups);
 if (error) {
  /* How the hell do we get out of this pickle? Give up */
  printk(KERN_ERR "%s: driver_create_groups(%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);
  }
 }

 return 0;
out_unregister:
 kobject_put(&priv->kobj);
 kfree(drv->p);
 drv->p = NULL;
out_put_bus:
 bus_put(bus);
 return error;
}
4. 调用driver_attach函数,对总线drv链表中的驱动与总线dev链表中的设备进行匹配
int driver_attach(struct device_driver *drv)
{
 return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
(1)bus_for_each_dev函数源码:
int bus_for_each_dev(struct bus_type *bus, struct device *start,
       void *data, int (*fn)(struct device *, void *))
{
 struct klist_iter i;
 struct device *dev;
 int error = 0;

 if (!bus || !bus->p)
  return -EINVAL;

 klist_iter_init_node(&bus->p->klist_devices, &i,
        (start ? &start->p->knode_bus : NULL));
 while ((dev = next_device(&i)) && !error)  // 遍历总线dev链表中的所有设备
  error = fn(dev, data);    // 判断驱动与设备是否匹配,若匹配则将二者绑定
 klist_iter_exit(&i);
 return error;
}
(2)__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)) // 调用bus的match函数对设备和驱动进行匹配,若不匹配driver_match_device函数的返回值为1,则程序立即返回,若匹配则继续向下执行
  return 0;

 if (dev->parent) /* Needed for USB */
  device_lock(dev->parent);
 device_lock(dev);
 if (!dev->driver)
  driver_probe_device(drv, dev); // 若设备和驱动匹配且设备的驱动程序为空,则将该驱动程序绑定到该设备(调用驱动程序的probe函数)
 device_unlock(dev);
 if (dev->parent)
  device_unlock(dev->parent);

 return 0;
}
5. 调用driver_probe_device函数,将设备与驱动程序进行绑定(调用probe函数)
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
 int ret = 0;

 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_barrier(dev);
 ret = really_probe(dev, drv);   // 调用probe
 pm_request_idle(dev);

 return ret;
}
static int really_probe(struct device *dev, struct device_driver *drv)
{
 int ret = 0;
 int local_trigger_count = atomic_read(&deferred_trigger_count);

 

 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 using pinctrl, bind pins now before probing */
 ret = pinctrl_bind_pins(dev);
 if (ret)
  goto probe_failed;

 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函数,那么就调用驱动程序的probe函数
  ret = drv->probe(dev);//此处进行绑定操作
  if (ret)
   goto probe_failed;
 }

 driver_bound(dev);
 ret = 1;
 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;
 dev_set_drvdata(dev, NULL);

 if (ret == -EPROBE_DEFER) {
  /* Driver requested deferred probing */
  dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
  driver_deferred_probe_add(dev);
  /* Did a trigger occur while probing? Need to re-trigger if yes */
  if (local_trigger_count != atomic_read(&deferred_trigger_count))
   driver_deferred_probe_trigger();
 } else 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);
 } else {
  pr_debug("%s: probe of %s rejects match %d\n",
         drv->name, dev_name(dev), ret);
 }
 /*
  * Ignore errors returned by ->probe so that the next driver can try
  * its luck.
  */
 ret = 0;
done:
 atomic_dec(&probe_count);
 wake_up(&probe_waitqueue);
 return ret;
}
注:若调用probe函数时为drv->probe(dev),则实际调用的函数为platform_drv_probe其源码为
static int platform_drv_probe(struct device *_dev)
{
 struct platform_driver *drv = to_platform_driver(_dev->driver);
 struct platform_device *dev = to_platform_device(_dev);
 int ret;

 if (ACPI_HANDLE(_dev))
  acpi_dev_pm_attach(_dev, true);

 ret = drv->probe(dev);    // 此处间接地调用了platform_driver提供的probe函数
 if (ret && ACPI_HANDLE(_dev))
  acpi_dev_pm_detach(_dev, true);

 if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
  dev_warn(_dev, "probe deferral not supported\n");
  ret = -ENXIO;
 }

 return ret;
}
注:platform_driver提供的probe函数即为注册平台驱动时程序员自己编写的probe函数
以上的函数调用关系就是讲了自己写的probe 是如何被调用的。
五、platform_device的注册过程
platform_device的注册过程可以简化为以下过程:
struct platform_device *pdev;  // 定义一个平台设备并初始化
platform_device_register(pdev)  // 注册
 ->>platform_device_add(pdev)
  ->>device_add(&pdev->dev)
   ->>bus_probe_device(&pdev->dev)
    ->>device_attach(&pdev->dev)
     ->>bus_for_each_drv(&(pdev->dev)->bus, NULL, &pdev->dev, __device_attach)
      ->>__device_attach(drv, &pdev->dev)
       ->>driver_probe_device(drv, &pdev->dev)
        ->>really_probe(&pdev->dev, drv)
         ->>&pdev->dev->bus->probe(dev) 或 drv->probe(dev)
将此过程展开如下:
1. 分配一个platform_device结构并调用platform_device_register函数进行注册
int platform_device_register(struct platform_device *pdev)
{
 device_initialize(&pdev->dev);  // 初始化platform_device的device成员
 arch_setup_pdev_archdata(pdev);
 return platform_device_add(pdev);  // 向内核添加一个平台设备
}
2. 调用platform_device_add函数向内核添加一个平台设备
int platform_device_add(struct platform_device *pdev)
{
 int i, ret;

 if (!pdev)
  return -EINVAL;

 if (!pdev->dev.parent)    //如果pdev->dev.parent为空则将pdev->dev.parent设置为platform_bus
  pdev->dev.parent = &platform_bus;

 pdev->dev.bus = &platform_bus_type;  // 设置总线类型为platform_bus_type

 switch (pdev->id) {    // 分配名字
 default:
  dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
  break;
 case PLATFORM_DEVID_NONE:
  dev_set_name(&pdev->dev, "%s", pdev->name);
  break;
 case PLATFORM_DEVID_AUTO:
  /*
   * Automatically allocated device ID. We mark it as such so
   * that we remember it must be freed, and we append a suffix
   * to avoid namespace collision with explicit IDs.
   */
  ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
  if (ret < 0)
   goto err_out;
  pdev->id = ret;
  pdev->id_auto = true;
  dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
  break;
 }
 for (i = 0; i < pdev->num_resources; i++) {   // 获取资源
  struct resource *p, *r = &pdev->resource[i];

  if (r->name == NULL)
   r->name = dev_name(&pdev->dev);

  p = r->parent;
  if (!p) {    // 设置资源类型
   if (resource_type(r) == IORESOURCE_MEM)
    p = &iomem_resource;
   else if (resource_type(r) == IORESOURCE_IO)
    p = &ioport_resource;
  }

  if (p && insert_resource(p, r)) {
   dev_err(&pdev->dev, "failed to claim resource %d\n", i);
   ret = -EBUSY;
   goto failed;
  }
 }

 pr_debug("Registering platform device '%s'. Parent at %s\n",
   dev_name(&pdev->dev), dev_name(pdev->dev.parent));

 ret = device_add(&pdev->dev);  // 向内核添加一个device
 if (ret == 0)
  return ret;

 failed:
 if (pdev->id_auto) {
  ida_simple_remove(&platform_devid_ida, pdev->id);
  pdev->id = PLATFORM_DEVID_AUTO;
 }

 while (--i >= 0) {
  struct resource *r = &pdev->resource[i];
  unsigned long type = resource_type(r);

  if (type == IORESOURCE_MEM || type == IORESOURCE_IO)
   release_resource(r);
 }

 err_out:
 return ret;
}
3. 调用device_add函数向内核添加一个device
int device_add(struct device *dev)
{
 struct device *parent = NULL;
 struct kobject *kobj;
 struct class_interface *class_intf;
 int error = -EINVAL;

 dev = get_device(dev);
 if (!dev)
  goto done;

 if (!dev->p) {
  error = device_private_init(dev);
  if (error)
   goto done;
 }

 /*
  * for statically allocated devices, which should all be converted
  * some day, we need to initialize the name. We prevent reading back
  * the name, and force the use of dev_name()
  */
 if (dev->init_name) {
  dev_set_name(dev, "%s", dev->init_name);
  dev->init_name = NULL;
 }

 /* subsystems can specify simple device enumeration */
 if (!dev_name(dev) && dev->bus && dev->bus->dev_name)
  dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);

 if (!dev_name(dev)) {
  error = -EINVAL;
  goto name_error;
 }

 pr_debug("device: '%s': %s\n", dev_name(dev), __func__);

 parent = get_device(dev->parent);
 kobj = get_device_parent(dev, parent);
 if (kobj)
  dev->kobj.parent = kobj;

 /* use parent numa_node */
 if (parent)
  set_dev_node(dev, dev_to_node(parent));

 /* first, register with generic layer. */
 /* we require the name to be set before, and pass NULL */
 error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
 if (error)
  goto Error;

 /* notify platform of device entry */
 if (platform_notify)
  platform_notify(dev);

 error = device_create_file(dev, &dev_attr_uevent);
 if (error)
  goto attrError;

 if (MAJOR(dev->devt)) {
  error = device_create_file(dev, &dev_attr_dev);
  if (error)
   goto ueventattrError;

  error = device_create_sys_dev_entry(dev);
  if (error)
   goto devtattrError;

  devtmpfs_create_node(dev);
 }

 error = device_add_class_symlinks(dev);
 if (error)
  goto SymlinkError;
 error = device_add_attrs(dev);
 if (error)
  goto AttrsError;
 error = bus_add_device(dev);
 if (error)
  goto BusError;
 error = dpm_sysfs_add(dev);
 if (error)
  goto DPMError;
 device_pm_add(dev);

 /* Notify clients of device addition.  This call must come
  * after dpm_sysfs_add() and before kobject_uevent().
  */
 if (dev->bus)
  blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
          BUS_NOTIFY_ADD_DEVICE, dev);

 kobject_uevent(&dev->kobj, KOBJ_ADD);
 bus_probe_device(dev);    // 为总线上的设备寻找驱动
 if (parent)
  klist_add_tail(&dev->p->knode_parent,
          &parent->p->klist_children);

 if (dev->class) {
  mutex_lock(&dev->class->p->mutex);
  /* tie the class to the device */
  klist_add_tail(&dev->knode_class,
          &dev->class->p->klist_devices);

  /* notify any interfaces that the device is here */
  list_for_each_entry(class_intf,
        &dev->class->p->interfaces, node)
   if (class_intf->add_dev)
    class_intf->add_dev(dev, class_intf);
  mutex_unlock(&dev->class->p->mutex);
 }
done:
 put_device(dev);
 return error;
 DPMError:
 bus_remove_device(dev);
 BusError:
 device_remove_attrs(dev);
 AttrsError:
 device_remove_class_symlinks(dev);
 SymlinkError:
 if (MAJOR(dev->devt))
  devtmpfs_delete_node(dev);
 if (MAJOR(dev->devt))
  device_remove_sys_dev_entry(dev);
 devtattrError:
 if (MAJOR(dev->devt))
  device_remove_file(dev, &dev_attr_dev);
 ueventattrError:
 device_remove_file(dev, &dev_attr_uevent);
 attrError:
 kobject_uevent(&dev->kobj, KOBJ_REMOVE);
 kobject_del(&dev->kobj);
 Error:
 cleanup_device_parent(dev);
 if (parent)
  put_device(parent);
name_error:
 kfree(dev->p);
 dev->p = NULL;
 goto done;
}
4. 调用bus_probe_device函数为总线上的设备寻找驱动
void bus_probe_device(struct device *dev)
{
 struct bus_type *bus = dev->bus;
 struct subsys_interface *sif;
 int ret;

 if (!bus)
  return;

 if (bus->p->drivers_autoprobe) {
  ret = device_attach(dev);  // 调用device_attach()进行实际的寻找
  WARN_ON(ret < 0);
 }

 mutex_lock(&bus->p->mutex);
 list_for_each_entry(sif, &bus->p->interfaces, node)
  if (sif->add_dev)
   sif->add_dev(dev, sif);
 mutex_unlock(&bus->p->mutex);
}
int device_attach(struct device *dev)
{
 int ret = 0;

 device_lock(dev);
 if (dev->driver) {
  if (klist_node_attached(&dev->p->knode_driver)) {
   ret = 1;
   goto out_unlock;
  }
  ret = device_bind_driver(dev);
  if (ret == 0)
   ret = 1;
  else {
   dev->driver = NULL;
   ret = 0;
  }
 } else {
  ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); // 遍历bus的drv链表为设备寻找驱动
  pm_request_idle(dev);
 }
out_unlock:
 device_unlock(dev);
 return ret;
}
(1) bus_for_each_drv函数源码:
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
       void *data, int (*fn)(struct device_driver *, void *))
{
 struct klist_iter i;
 struct device_driver *drv;
 int error = 0;

 if (!bus)
  return -EINVAL;

 klist_iter_init_node(&bus->p->klist_drivers, &i,
        start ? &start->p->knode_bus : NULL);
 while ((drv = next_driver(&i)) && !error) // 遍历整个drv链表
  error = fn(drv, data);   // 寻找该设备匹配的驱动程序,若匹配则将二者绑定
 klist_iter_exit(&i);
 return error;
}
(2)__device_attach函数源码:
static int __device_attach(struct device_driver *drv, void *data)
{
 struct device *dev = data;

 

 if (!driver_match_device(drv, dev))  // 调用bus的match函数对设备和驱动进行匹配,若不匹配driver_match_device函数的返回值为1,则程序立即返回,若匹配则继续向下执行
  return 0; 

 return driver_probe_device(drv, dev);  // 若设备和驱动匹配,则将该驱动程序绑定到该设备
}
static inline int driver_match_device(struct device_driver *drv,
          struct device *dev)
{
 return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}
5. 调用driver_probe_device将设备与驱动程序进行绑定(调用probe函数)
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
 int ret = 0;

 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_barrier(dev);
 ret = really_probe(dev, drv);   // 调用probe
 pm_request_idle(dev);

 return ret;
}
static int really_probe(struct device *dev, struct device_driver *drv)
{
 int ret = 0;
 int local_trigger_count = atomic_read(&deferred_trigger_count);

 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 using pinctrl, bind pins now before probing */
 ret = pinctrl_bind_pins(dev);
 if (ret)
  goto probe_failed;

 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函数,那么就调用驱动程序的probe函数
  ret = drv->probe(dev);
  if (ret)
   goto probe_failed;
 }

 driver_bound(dev);
 ret = 1;
 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;
 dev_set_drvdata(dev, NULL);

 if (ret == -EPROBE_DEFER) {
  /* Driver requested deferred probing */
  dev_info(dev, "Driver %s requests probe deferral\n", drv->name);
  driver_deferred_probe_add(dev);
  /* Did a trigger occur while probing? Need to re-trigger if yes */
  if (local_trigger_count != atomic_read(&deferred_trigger_count))
   driver_deferred_probe_trigger();
 } else 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);
 } else {
  pr_debug("%s: probe of %s rejects match %d\n",
         drv->name, dev_name(dev), ret);
 }
 /*
  * Ignore errors returned by ->probe so that the next driver can try
  * its luck.
  */
 ret = 0;
done:
 atomic_dec(&probe_count);
 wake_up(&probe_waitqueue);
 return ret;
}
   到此Linux内核的总线设备驱动模型分析完毕。从上面的分析过程可以看出,所谓的platform_device并不是与字符设备、块设备和网络设备并列的概念,而是Linux系统提供的一种附加手段。

你可能感兴趣的:(linux,驱动)