zoukankan      html  css  js  c++  java
  • Linux spi驱动分析(二)----SPI核心(bus、device_driver和device)

    一、spi总线注册

            这里所说的SPI核心,就是指/drivers/spi/目录下spi.c文件中提供给其他文件的函数,首先看下spi核心的初始化函数spi_init(void)。程序如下:

    点击(此处)折叠或打开

    1. static int __init spi_init(void)
    2. {
    3.     int    status;
    4.     buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL);
    5.     if (!buf) {
    6.         status = -ENOMEM;
    7.         goto err0;
    8.     }
    9.     status = bus_register(&spi_bus_type);
    10.     if (status < 0)
    11.         goto err1;
    12.     status = class_register(&spi_master_class);
    13.     if (status < 0)
    14.         goto err2;
    15.     return 0;
    16. err2:
    17.     bus_unregister(&spi_bus_type);
    18. err1:
    19.     kfree(buf);
    20.     buf = NULL;
    21. err0:
    22.     return status;
    23. }
    24. postcore_initcall(spi_init);

            说明:
            1) 由postcore_initcall(spi_init);可以看出,此宏在系统初始化时是先于module_init()执行的。

            2) 申请的buf空间用于在spi数据传输中。

            3) 接下来是总线注册和类注册,首先看下总线注册。

    点击(此处)折叠或打开

    1. struct subsys_private {
    2.     struct kset subsys;
    3.     struct kset *devices_kset;
    4.     struct kset *drivers_kset;
    5.     struct klist klist_devices;
    6.     struct klist klist_drivers;
    7.     struct blocking_notifier_head bus_notifier;
    8.     unsigned int drivers_autoprobe:1;
    9.     struct bus_type *bus;
    10.     struct list_head class_interfaces;
    11.     struct kset glue_dirs;
    12.     struct mutex class_mutex;
    13.     struct class *class;
    14. };
    15. struct bus_type {
    16.     const char        *name;
    17.     struct bus_attribute    *bus_attrs;
    18.     struct device_attribute    *dev_attrs;
    19.     struct driver_attribute    *drv_attrs;
    20.     int (*match)(struct device *dev, struct device_driver *drv);
    21.     int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
    22.     int (*probe)(struct device *dev);
    23.     int (*remove)(struct device *dev);
    24.     void (*shutdown)(struct device *dev);
    25.     int (*suspend)(struct device *dev, pm_message_t state);
    26.     int (*resume)(struct device *dev);
    27.     const struct dev_pm_ops *pm;
    28.     struct subsys_private *p;
    29. };
    30. struct bus_type spi_bus_type = {
    31.     .name        = "spi",
    32.     .dev_attrs    = spi_dev_attrs,
    33.     .match        = spi_match_device,
    34.     .uevent        = spi_uevent,
    35.     .pm        = &spi_pm,
    36. };
    37. int bus_register(struct bus_type *bus)
    38. {
    39.     int retval;
    40.     struct subsys_private *priv;
    41.     priv = kzalloc(sizeof(struct subsys_private), GFP_KERNEL);
    42.     if (!priv)
    43.         return -ENOMEM;
    44.     priv->bus = bus;
    45.     bus->p = priv;
    46.     BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);
    47.     //总线的名字”spi”,我们说过了一个kobject对应一个目录,这里为这个目录赋值名字
    48.     retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
    49.     if (retval)
    50.         goto out;
    51.     priv->subsys.kobj.kset = bus_kset;
    52.     priv->subsys.kobj.ktype = &bus_ktype;
    53.     priv->drivers_autoprobe = 1;
    54.     //创建devices命名的目录
    55.     retval = kset_register(&priv->subsys);
    56.     if (retval)
    57.         goto out;
    58.     //创建属性文件
    59.     retval = bus_create_file(bus, &bus_attr_uevent);
    60.     if (retval)
    61.         goto bus_uevent_fail;
    62.     priv->devices_kset = kset_create_and_add("devices", NULL,
    63.                          &priv->subsys.kobj);
    64.     if (!priv->devices_kset) {
    65.         retval = -ENOMEM;
    66.         goto bus_devices_fail;
    67.     }
    68.     priv->drivers_kset = kset_create_and_add("drivers", NULL,
    69.                          &priv->subsys.kobj);
    70.     if (!priv->drivers_kset) {
    71.         retval = -ENOMEM;
    72.         goto bus_drivers_fail;
    73.     }
    74.     klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put);
    75.     klist_init(&priv->klist_drivers, NULL, NULL);
    76.     retval = add_probe_files(bus);    //添加探测属性
    77.     if (retval)
    78.         goto bus_probe_files_fail;
    79.     retval = bus_add_attrs(bus);    //添加其他属性
    80.     if (retval)
    81.         goto bus_attrs_fail;
    82.     pr_debug("bus: '%s': registered ", bus->name);
    83.     return 0;
    84. bus_attrs_fail:
    85.     remove_probe_files(bus);
    86. bus_probe_files_fail:
    87.     kset_unregister(bus->p->drivers_kset);
    88. bus_drivers_fail:
    89.     kset_unregister(bus->p->devices_kset);
    90. bus_devices_fail:
    91.     bus_remove_file(bus, &bus_attr_uevent);
    92. bus_uevent_fail:
    93.     kset_unregister(&bus->p->subsys);
    94. out:
    95.     kfree(bus->p);
    96.     bus->p = NULL;
    97.     return retval;
    98. }

            说明:

            1)  首先不管是设备还是驱动,都是挂接在某条总线上的,也就是说我们根据总线类型的不同来区分各种设备和驱动。

            2) 从总线注册函数bus_register(struct bus_type *bus)中可以发现,首先申请了一个subsys_private结构体内存。该结构体中包含了三个kset结构,分别是struct kset subsys、struct kset *devices_kset和struct kset *drivers_kset。

            3) subsys是用来向上链接的。

            4) 当发现一个设备或者驱动的时候,对于每一次设备或者驱动注册(设备是被插入了,驱动就是.ko模块被加载),都得分配一个device或者device_drive结构,每一次都需要将device结构挂入drivers或devices(kset结构)链表中,这样才能通过总线找到挂接在这个总线上的所有设备和驱动。这里仅仅将设备和驱动挂接在总线上,并不能表明设备和驱动之间的关系,这样的处理仅仅表明了驱动、设备与总线的关系,它们申明了我现在挂接在这条总线上,以后操作我就通过这条总线。

            5) 总线的目录名为”spi”。也就是说在/sys/bus目录下有一个spi目录,即/sys/bus/spi。内核中有spi总线驱动,bus_register(&spi_bus_type)就是用来注册总线的,该函数调用完成后,就会在/sys/bus/目录下创建spi目录。

            接下来看下总线中spi_match_device()函数,此函数在(四)中的设备注册中会调用,如下:

    点击(此处)折叠或打开

    1. static int spi_match_device(struct device *dev, struct device_driver *drv)
    2. {
    3.     const struct spi_device    *spi = to_spi_device(dev);
    4.     const struct spi_driver    *sdrv = to_spi_driver(drv);
    5.     /* Attempt an OF style match */
    6.     if (of_driver_match_device(dev, drv))
    7.         return 1;
    8.     if (sdrv->id_table)
    9.         return !!spi_match_id(sdrv->id_table, spi);
    10.     return strcmp(spi->modalias, drv->name) == 0;
    11. }

            说明:

            1) 首先查看驱动和设备是否匹配,如果不匹配,退出。

            2) 判断驱动中是否支持id数组,如果支持,查找匹配此id的spi_device。

            3) 比较设备的名字的和驱动的名字是否相同。

    二、spi驱动注册

            在《Linux spi驱动分析(四)----SPI设备驱动(W25Q32BV)》中,执行语句spi_register_driver(&w25q_driver);,从而注册spi驱动。函数如下:

    点击(此处)折叠或打开

    1. struct spi_driver {
    2.     const struct spi_device_id *id_table;
    3.     int            (*probe)(struct spi_device *spi);
    4.     int            (*remove)(struct spi_device *spi);
    5.     void            (*shutdown)(struct spi_device *spi);
    6.     int            (*suspend)(struct spi_device *spi, pm_message_t mesg);
    7.     int            (*resume)(struct spi_device *spi);
    8.     struct device_driver    driver;
    9. };
    10. static struct spi_driver w25q_driver = {
    11.     .driver    = {
    12.         .name    = "spi-w25q",
    13.         .owner    = THIS_MODULE,
    14.     },
    15.     //.id_table    = w25q_ids,
    16.     .probe    = w25q_probe,
    17.     .remove    = __devexit_p(w25q_remove),
    18. };
    19. int spi_register_driver(struct spi_driver *sdrv)
    20. {
    21.     sdrv->driver.bus = &spi_bus_type;
    22.     if (sdrv->probe)
    23.         sdrv->driver.probe = spi_drv_probe;
    24.     if (sdrv->remove)
    25.         sdrv->driver.remove = spi_drv_remove;
    26.     if (sdrv->shutdown)
    27.         sdrv->driver.shutdown = spi_drv_shutdown;
    28.     return driver_register(&sdrv->driver);
    29. }

            说明:

            1) 驱动是如何插入到/sys/bus/drivers/spi目录下的?在driver_register->driver_register->bus_add_driver函数中有个重要的语句drv->kobj.kset = &bus->drivers,这里就是将driver的kobj所属的kset挂接上总线的kset。

            2) 在struct spi_driver中指明驱动的名称,这里是"spi-w25q"。

            3) spi_register_driver()函数的参数为spi_driver结构。函数定义了bus_type,也就是驱动挂接的总线类型。函数接下来对结构体spi_driver中的device_driver成员赋值。

            4) 驱动注册,程序如下:

    点击(此处)折叠或打开

    1. struct device_driver {
    2.     const char        *name; //设备驱动的名字
    3.     struct bus_type        *bus; //设备驱动挂接的总线类型
    4.     struct module        *owner;
    5.     const char        *mod_name;    /* used for built-in modules */
    6.     bool suppress_bind_attrs;    /* disables bind/unbind via sysfs */
    7.     const struct of_device_id    *of_match_table;
    8.     int (*probe) (struct device *dev);
    9.     int (*remove) (struct device *dev);
    10.     void (*shutdown) (struct device *dev);
    11.     int (*suspend) (struct device *dev, pm_message_t state);
    12.     int (*resume) (struct device *dev);
    13.     const struct attribute_group **groups;
    14.     const struct dev_pm_ops *pm;
    15.     struct driver_private *p;
    16. };
    17. int driver_register(struct device_driver *drv)
    18. {
    19.     int ret;
    20.     struct device_driver *other;
    21.     BUG_ON(!drv->bus->p);
    22.     if ((drv->bus->probe && drv->probe) ||
    23.      (drv->bus->remove && drv->remove) ||
    24.      (drv->bus->shutdown && drv->shutdown))
    25.         printk(KERN_WARNING "Driver '%s' needs updating - please use "
    26.             "bus_type methods ", drv->name);
    27.     /* 在kobject结构组成的链表中查找是否已经存在这个驱动,前面讲过,驱动必然挂接在某个总线
    28.        上,返回值是device_driver结构的指针 */
    29.     other = driver_find(drv->name, drv->bus);
    30.     if (other) {
    31.         put_driver(other);
    32.         printk(KERN_ERR "Error: Driver '%s' is already registered, "
    33.             "aborting... ", drv->name);
    34.         return -EBUSY;
    35.     }
    36.     ret = bus_add_driver(drv);
    37.     if (ret)
    38.         return ret;
    39.     ret = driver_add_groups(drv, drv->groups);
    40.     if (ret)
    41.         bus_remove_driver(drv);
    42.     return ret;
    43. }

            说明:

            1) driver_register()完成挂接驱动至总线及生成设备树的过程。

            2) 首先调用driver_find()函数在spi总线上查找该驱动是否已经存在,如果存在,忙退出。

            3) 如果该驱动在SPI总线上不存在,调用bus_add_driver(drv)增加该驱动。

            4) 调用driver_add_groups(drv, drv->groups)函数增加驱动组。

            接下来看bus_add_driver函数,程序如下:

    点击(此处)折叠或打开

    1. int bus_add_driver(struct device_driver *drv)
    2. {
    3.     struct bus_type *bus;
    4.     struct driver_private *priv;
    5.     int error = 0;
    6.     bus = bus_get(drv->bus);
    7.     if (!bus)
    8.         return -EINVAL;
    9.     pr_debug("bus: '%s': add driver %s ", bus->name, drv->name);
    10.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    11.     if (!priv) {
    12.         error = -ENOMEM;
    13.         goto out_put_bus;
    14.     }
    15.     klist_init(&priv->klist_devices, NULL, NULL);
    16.     priv->driver = drv;
    17.     drv->p = priv;
    18.     priv->kobj.kset = bus->p->drivers_kset;
    19.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
    20.                  "%s", drv->name);
    21.     if (error)
    22.         goto out_unregister;
    23.     if (drv->bus->p->drivers_autoprobe) {
    24.         error = driver_attach(drv);     //这个函数是重点.
    25.         if (error)
    26.             goto out_unregister;
    27.     }
    28.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
    29.     module_add_driver(drv->owner, drv);
    30.     error = driver_create_file(drv, &driver_attr_uevent);
    31.     if (error) {
    32.         printk(KERN_ERR "%s: uevent attr (%s) failed ",
    33.             __func__, drv->name);
    34.     }
    35.     error = driver_add_attrs(bus, drv);
    36.     if (error) {
    37.         /* How the hell do we get out of this pickle? Give up */
    38.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed ",
    39.             __func__, drv->name);
    40.     }
    41.     if (!drv->suppress_bind_attrs) {
    42.         error = add_bind_files(drv);
    43.         if (error) {
    44.             /* Ditto */
    45.             printk(KERN_ERR "%s: add_bind_files(%s) failed ",
    46.                 __func__, drv->name);
    47.         }
    48.     }
    49.     kobject_uevent(&priv->kobj, KOBJ_ADD);
    50.     return 0;
    51. out_unregister:
    52.     kobject_put(&priv->kobj);
    53.     kfree(drv->p);
    54.     drv->p = NULL;
    55. out_put_bus:
    56.     bus_put(bus);
    57.     return error;
    58. }

            说明:

            1) 首先创建struct driver_private *priv结构体内存,注意此结构体是struct device_driver的成员变量。

            2) 初始化priv成员变量。

            3) 如果驱动总线支持自动探测,则调用error = driver_attach(drv); 实现探测。由(二)中bus_register()函数可以看出,bus->p->drivers_autoprobe = 1,支持自动探测。

            4) driver_attach(drv); 的作用是:如果驱动还未挂接在总线上,挂接它并且调用probe函数进行探测。

    点击(此处)折叠或打开

    1. int driver_attach(struct device_driver *drv)
    2. {
    3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
    4. }

            这个函数会调用__driver_attach函数,如下:

    点击(此处)折叠或打开

    1. static int __driver_attach(struct device *dev, void *data)
    2. {
    3.     struct device_driver *drv = data;
    4.     /*
    5.      * Lock device and try to bind to it. We drop the error
    6.      * here and always return 0, because we need to keep trying
    7.      * to bind to devices and some drivers will return an error
    8.      * simply if it didn't support the device.
    9.      *
    10.      * driver_probe_device() will spit a warning if there
    11.      * is an error.
    12.      */
    13.     if (!driver_match_device(drv, dev))
    14.         return 0;
    15.     if (dev->parent)    /* Needed for USB */
    16.         device_lock(dev->parent);
    17.     device_lock(dev);
    18.     if (!dev->driver)
    19.         driver_probe_device(drv, dev);    //此函数就是我们要找的函数
    20.     device_unlock(dev);
    21.     if (dev->parent)
    22.         device_unlock(dev->parent);
    23.     return 0;
    24. }

            driver_probe_device()函数如下:

    点击(此处)折叠或打开

    1. int driver_probe_device(struct device_driver *drv, struct device *dev)
    2. {
    3.     int ret = 0;
    4.     if (!device_is_registered(dev))
    5.         return -ENODEV;
    6.     pr_debug("bus: '%s': %s: matched device %s with driver %s ",
    7.          drv->bus->name, __func__, dev_name(dev), drv->name);
    8.     pm_runtime_get_noresume(dev);
    9.     pm_runtime_barrier(dev);
    10.     ret = really_probe(dev, drv);
    11.     pm_runtime_put_sync(dev);
    12.     return ret;
    13. }

              driver_probe_device函数中有一个really_probe函数,这是我们的最终目的地。

    点击(此处)折叠或打开

    1. static int really_probe(struct device *dev, struct device_driver *drv)
    2. {
    3.     int ret = 0;
    4.     atomic_inc(&probe_count);
    5.     pr_debug("bus: '%s': %s: probing driver %s with device %s ",
    6.          drv->bus->name, __func__, drv->name, dev_name(dev));
    7.     WARN_ON(!list_empty(&dev->devres_head));
    8.     dev->driver = drv;
    9.     if (driver_sysfs_add(dev)) {
    10.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed ",
    11.             __func__, dev_name(dev));
    12.         goto probe_failed;
    13.     }
    14.     if (dev->bus->probe) {
    15.         ret = dev->bus->probe(dev);
    16.         if (ret)
    17.             goto probe_failed;
    18.     } else if (drv->probe) {
    19.         ret = drv->probe(dev);
    20.         if (ret)
    21.             goto probe_failed;
    22.     }
    23.     driver_bound(dev);
    24.     ret = 1;
    25.     pr_debug("bus: '%s': %s: bound device %s to driver %s ",
    26.          drv->bus->name, __func__, dev_name(dev), drv->name);
    27.     goto done;
    28. probe_failed:
    29.     devres_release_all(dev);
    30.     driver_sysfs_remove(dev);
    31.     dev->driver = NULL;
    32.     if (ret != -ENODEV && ret != -ENXIO) {
    33.         /* driver matched but the probe failed */
    34.         printk(KERN_WARNING
    35.          "%s: probe of %s failed with error %d ",
    36.          drv->name, dev_name(dev), ret);
    37.     }
    38.     /*
    39.      * Ignore errors returned by ->probe so that the next driver can try
    40.      * its luck.
    41.      */
    42.     ret = 0;
    43. done:
    44.     atomic_dec(&probe_count);
    45.     wake_up(&probe_waitqueue);
    46.     return ret;
    47. }

            说明:

            1) 在if (dev->bus->probe)中,由于此处还没有定义设备,所以不执行if里面的程序。在else if(drv->probe)中,驱动里面有探测函数,所以执行ret = drv->probe(dev);。因为此处还没有定义设备,所以此处执行没有效果。

            在 bus_for_each_dev函数中可以找到device结构:

    点击(此处)折叠或打开

    1. int bus_for_each_dev(struct bus_type *bus, struct device *start,
    2.          void *data, int (*fn)(struct device *, void *))
    3. {
    4.     struct klist_iter i;
    5.     struct device *dev;
    6.     int error = 0;
    7.     if (!bus)
    8.         return -EINVAL;
    9.     klist_iter_init_node(&bus->p->klist_devices, &i,
    10.              (start ? &start->p->knode_bus : NULL));
    11.     
    12.     while ((dev = next_device(&i)) && !error)
    13.         error = fn(dev, data);
    14.     klist_iter_exit(&i);
    15.     return error;
    16. }

            说明:

            1) 查找每个挂接在spi总线上的设备,看他们是否有注册,并调用相应的函数也就是__driver_attach函数。实际上就是查找device结构。

    三、spi设备注册

            在《Linux spi驱动分析(一)----总线驱动》中,spi_new_device()函数调用了spi_add_device(proxy),程序如下:

    点击(此处)折叠或打开

    1. struct device {
    2.     struct device        *parent;
    3.     struct device_private    *p;
    4.     struct kobject kobj;
    5.     const char        *init_name; /* initial name of the device */
    6.     const struct device_type *type;
    7.     struct mutex        mutex;    /* mutex to synchronize calls to
    8.                      * its driver.
    9.                      */
    10.     struct bus_type    *bus;        /* type of bus device is on */
    11.     struct device_driver *driver;    /* which driver has allocated this
    12.                      device */
    13.     void        *platform_data;    /* Platform specific data, device
    14.                      core doesn't touch it */
    15.     struct dev_pm_info    power;
    16.     struct dev_power_domain    *pwr_domain;
    17. #ifdef CONFIG_NUMA
    18.     int        numa_node;    /* NUMA node this device is close to */
    19. #endif
    20.     u64        *dma_mask;    /* dma mask (if dma'able device) */
    21.     u64        coherent_dma_mask;/* Like dma_mask, but for
    22.                      alloc_coherent mappings as
    23.                      not all hardware supports
    24.                      64 bit addresses for consistent
    25.                      allocations such descriptors. */
    26.     struct device_dma_parameters *dma_parms;
    27.     struct list_head    dma_pools;    /* dma pools (if dma'ble) */
    28.     struct dma_coherent_mem    *dma_mem; /* internal for coherent mem
    29.                      override */
    30.     /* arch specific additions */
    31.     struct dev_archdata    archdata;
    32.     struct device_node    *of_node; /* associated device tree node */
    33.     dev_t            devt;    /* dev_t, creates the sysfs "dev" */
    34.     spinlock_t        devres_lock;
    35.     struct list_head    devres_head;
    36.     struct klist_node    knode_class;
    37.     struct class        *class;
    38.     const struct attribute_group **groups;    /* optional groups */
    39.     void    (*release)(struct device *dev);
    40. };
    41. int spi_add_device(struct spi_device *spi)
    42. {
    43.     static DEFINE_MUTEX(spi_add_lock);
    44.     struct device *dev = spi->master->dev.parent;
    45.     struct device *d;
    46.     int status;
    47.     /* Chipselects are numbered 0..max; validate. */
    48.     if (spi->chip_select >= spi->master->num_chipselect) {
    49.         dev_err(dev, "cs%d >= max %d ",
    50.             spi->chip_select,
    51.             spi->master->num_chipselect);
    52.         return -EINVAL;
    53.     }
    54.     /* Set the bus ID string */
    55.     dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
    56.             spi->chip_select);
    57.     /* We need to make sure there's no other device with this
    58.      * chipselect **BEFORE** we call setup(), else we'll trash
    59.      * its configuration. Lock against concurrent add() calls.
    60.      */
    61.     mutex_lock(&spi_add_lock);
    62.     d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev));
    63.     if (d != NULL) {
    64.         dev_err(dev, "chipselect %d already in use ",
    65.                 spi->chip_select);
    66.         put_device(d);
    67.         status = -EBUSY;
    68.         goto done;
    69.     }
    70.     /* Drivers may modify this initial i/o setup, but will
    71.      * normally rely on the device being setup. Devices
    72.      * using SPI_CS_HIGH can't coexist well otherwise...
    73.      */
    74.     status = spi_setup(spi);
    75.     if (status < 0) {
    76.         dev_err(dev, "can't setup %s, status %d ",
    77.                 dev_name(&spi->dev), status);
    78.         goto done;
    79.     }
    80.     /* Device may be bound to an active driver when this returns */
    81.     status = device_add(&spi->dev);
    82.     if (status < 0)
    83.         dev_err(dev, "can't add %s, status %d ",
    84.                 dev_name(&spi->dev), status);
    85.     else
    86.         dev_dbg(dev, "registered child %s ", dev_name(&spi->dev));
    87. done:
    88.     mutex_unlock(&spi_add_lock);
    89.     return status;
    90. }

            说明:

            1) 在设备device的定义中,定义了这个设备挂接的总线和驱动。

            2) spi_add_device()函数首先判断是否超出最大设备数,如果超过,直接退出。

            3) 设置设备名称,此名称即是/sys/bus/spi/devices/下的一个目录。

            4) 在spi总线上寻找此设备,如果找到,退出。

            5) 调用spi_setup(spi)函数。

            6) 调用device_add(&spi->dev)函数对设备进行初始化和注册。程序如下:

    点击(此处)折叠或打开

    1. int device_add(struct device *dev)
    2. {
    3.     struct device *parent = NULL;
    4.     struct class_interface *class_intf;
    5.     int error = -EINVAL;
    6.     dev = get_device(dev);
    7.     if (!dev)
    8.         goto done;
    9.     if (!dev->p) {
    10.         error = device_private_init(dev);
    11.         if (error)
    12.             goto done;
    13.     }
    14.     /*
    15.      * for statically allocated devices, which should all be converted
    16.      * some day, we need to initialize the name. We prevent reading back
    17.      * the name, and force the use of dev_name()
    18.      */
    19.     if (dev->init_name) {
    20.         dev_set_name(dev, "%s", dev->init_name);
    21.         dev->init_name = NULL;
    22.     }
    23.     if (!dev_name(dev)) {
    24.         error = -EINVAL;
    25.         goto name_error;
    26.     }
    27.     pr_debug("device: '%s': %s ", dev_name(dev), __func__);
    28.     parent = get_device(dev->parent);
    29.     setup_parent(dev, parent);
    30.     /* use parent numa_node */
    31.     if (parent)
    32.         set_dev_node(dev, dev_to_node(parent));
    33.     /* first, register with generic layer. */
    34.     /* we require the name to be set before, and pass NULL */
    35.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);
    36.     if (error)
    37.         goto Error;
    38.     /* notify platform of device entry */
    39.     if (platform_notify)
    40.         platform_notify(dev);
    41.     error = device_create_file(dev, &uevent_attr);
    42.     if (error)
    43.         goto attrError;
    44.     if (MAJOR(dev->devt)) {
    45.         error = device_create_file(dev, &devt_attr);
    46.         if (error)
    47.             goto ueventattrError;
    48.         error = device_create_sys_dev_entry(dev);
    49.         if (error)
    50.             goto devtattrError;
    51.         devtmpfs_create_node(dev);
    52.     }
    53.     error = device_add_class_symlinks(dev);
    54.     if (error)
    55.         goto SymlinkError;
    56.     error = device_add_attrs(dev);
    57.     if (error)
    58.         goto AttrsError;
    59.     error = bus_add_device(dev);
    60.     if (error)
    61.         goto BusError;
    62.     error = dpm_sysfs_add(dev);
    63.     if (error)
    64.         goto DPMError;
    65.     device_pm_add(dev);
    66.     /* Notify clients of device addition. This call must come
    67.      * after dpm_sysf_add() and before kobject_uevent().
    68.      */
    69.     if (dev->bus)
    70.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
    71.                      BUS_NOTIFY_ADD_DEVICE, dev);
    72.     kobject_uevent(&dev->kobj, KOBJ_ADD);
    73.     bus_probe_device(dev);
    74.     if (parent)
    75.         klist_add_tail(&dev->p->knode_parent,
    76.              &parent->p->klist_children);
    77.     if (dev->class) {
    78.         mutex_lock(&dev->class->p->class_mutex);
    79.         /* tie the class to the device */
    80.         klist_add_tail(&dev->knode_class,
    81.              &dev->class->p->klist_devices);
    82.         /* notify any interfaces that the device is here */
    83.         list_for_each_entry(class_intf,
    84.                  &dev->class->p->class_interfaces, node)
    85.             if (class_intf->add_dev)
    86.                 class_intf->add_dev(dev, class_intf);
    87.         mutex_unlock(&dev->class->p->class_mutex);
    88.     }
    89. done:
    90.     put_device(dev);
    91.     return error;
    92.  DPMError:
    93.     bus_remove_device(dev);
    94.  BusError:
    95.     device_remove_attrs(dev);
    96.  AttrsError:
    97.     device_remove_class_symlinks(dev);
    98.  SymlinkError:
    99.     if (MAJOR(dev->devt))
    100.         devtmpfs_delete_node(dev);
    101.     if (MAJOR(dev->devt))
    102.         device_remove_sys_dev_entry(dev);
    103.  devtattrError:
    104.     if (MAJOR(dev->devt))
    105.         device_remove_file(dev, &devt_attr);
    106.  ueventattrError:
    107.     device_remove_file(dev, &uevent_attr);
    108.  attrError:
    109.     kobject_uevent(&dev->kobj, KOBJ_REMOVE);
    110.     kobject_del(&dev->kobj);
    111.  Error:
    112.     cleanup_device_parent(dev);
    113.     if (parent)
    114.         put_device(parent);
    115. name_error:
    116.     kfree(dev->p);
    117.     dev->p = NULL;
    118.     goto done;
    119. }

              说明:

              1) 首先获取设备dev,对dev的成员进行初始化。

              2) kobject_add()完成目录的创建。

              3) 创建文件。

              4) bus_probe_device(dev);,总线探测设备,程序如下:

    点击(此处)折叠或打开

    1. void bus_probe_device(struct device *dev)
    2. {
    3.     struct bus_type *bus = dev->bus;
    4.     int ret;
    5.     if (bus && bus->p->drivers_autoprobe) {
    6.         ret = device_attach(dev);
    7.         WARN_ON(ret < 0);
    8.     }
    9. }
    10. int device_attach(struct device *dev)
    11. {
    12.     int ret = 0;
    13.     device_lock(dev);
    14.     if (dev->driver) {
    15.         if (klist_node_attached(&dev->p->knode_driver)) {
    16.             ret = 1;
    17.             goto out_unlock;
    18.         }
    19.         ret = device_bind_driver(dev);
    20.         if (ret == 0)
    21.             ret = 1;
    22.         else {
    23.             dev->driver = NULL;
    24.             ret = 0;
    25.         }
    26.     } else {
    27.         pm_runtime_get_noresume(dev);
    28.         ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
    29.         pm_runtime_put_sync(dev);
    30.     }
    31. out_unlock:
    32.     device_unlock(dev);
    33.     return ret;
    34. }

            说明:
            1) 由(二)中的总线注册函数可知,bus->p->drivers_autoprobe = 1。

            2) 调用device_attach()函数加载设备。

            3) 由于程序还没有对dev->driver进行赋值,所以此处程序走的是else。

            4) bus_for_each_drv()函数调用__device_attach()函数,程序如下:

    点击(此处)折叠或打开

    1. int bus_for_each_drv(struct bus_type *bus, struct device_driver *start,
    2.          void *data, int (*fn)(struct device_driver *, void *))
    3. {
    4.     struct klist_iter i;
    5.     struct device_driver *drv;
    6.     int error = 0;
    7.     if (!bus)
    8.         return -EINVAL;
    9.     klist_iter_init_node(&bus->p->klist_drivers, &i,
    10.              start ? &start->p->knode_bus : NULL);
    11.     while ((drv = next_driver(&i)) && !error)
    12.         error = fn(drv, data);
    13.     klist_iter_exit(&i);
    14.     return error;
    15. }
    16. static inline int driver_match_device(struct device_driver *drv,
    17.                  struct device *dev)
    18. {
    19.     return drv->bus->match ? drv->bus->match(dev, drv) : 1;
    20. }
    21. static int __device_attach(struct device_driver *drv, void *data)
    22. {
    23.     struct device *dev = data;
    24.     if (!driver_match_device(drv, dev))
    25.         return 0;
    26.     return driver_probe_device(drv, dev);
    27. }

            说明:           
            1) __device_attach()函数使用了两个参数,一个参数为dev,另外一个就是bus_for_each_drv()函数提供的。

            2) __device_attach()函数首先使用函数driver_match_device(drv, dev)查看驱动是否匹配设备,如果不匹配,退出。driver_match_device(drv, dev)中,判断是否有drv->bus->match,从(二)总线注册中知道,总线中有match,所以调用(二)中的spi_match_device()函数。

             3) driver_probe_device()函数完成驱动探测,程序如下:

    点击(此处)折叠或打开

    1. int driver_probe_device(struct device_driver *drv, struct device *dev)
    2. {
    3.     int ret = 0;
    4.     if (!device_is_registered(dev))
    5.         return -ENODEV;
    6.     pr_debug("bus: '%s': %s: matched device %s with driver %s ",
    7.          drv->bus->name, __func__, dev_name(dev), drv->name);
    8.     pm_runtime_get_noresume(dev);
    9.     pm_runtime_barrier(dev);
    10.     ret = really_probe(dev, drv);
    11.     pm_runtime_put_sync(dev);
    12.     return ret;
    13. }
    14. static int really_probe(struct device *dev, struct device_driver *drv)
    15. {
    16.     int ret = 0;
    17.     atomic_inc(&probe_count);
    18.     pr_debug("bus: '%s': %s: probing driver %s with device %s ",
    19.          drv->bus->name, __func__, drv->name, dev_name(dev));
    20.     WARN_ON(!list_empty(&dev->devres_head));
    21.     dev->driver = drv;
    22.     if (driver_sysfs_add(dev)) {
    23.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed ",
    24.             __func__, dev_name(dev));
    25.         goto probe_failed;
    26.     }
    27.     if (dev->bus->probe) {
    28.         ret = dev->bus->probe(dev);
    29.         if (ret)
    30.             goto probe_failed;
    31.     } else if (drv->probe) {
    32.         ret = drv->probe(dev);
    33.         if (ret)
    34.             goto probe_failed;
    35.     }
    36.     driver_bound(dev);
    37.     ret = 1;
    38.     pr_debug("bus: '%s': %s: bound device %s to driver %s ",
    39.          drv->bus->name, __func__, dev_name(dev), drv->name);
    40.     goto done;
    41. probe_failed:
    42.     devres_release_all(dev);
    43.     driver_sysfs_remove(dev);
    44.     dev->driver = NULL;
    45.     if (ret != -ENODEV && ret != -ENXIO) {
    46.         /* driver matched but the probe failed */
    47.         printk(KERN_WARNING
    48.          "%s: probe of %s failed with error %d ",
    49.          drv->name, dev_name(dev), ret);
    50.     }
    51.     /*
    52.      * Ignore errors returned by ->probe so that the next driver can try
    53.      * its luck.
    54.      */
    55.     ret = 0;
    56. done:
    57.     atomic_dec(&probe_count);
    58.     wake_up(&probe_waitqueue);
    59.     return ret;
    60. }

            说明:

            1) driver_probe_device()函数调用really_probe()函数。

            2) 在really_probe()函数中,由于设备的总线中没有探测函数,所以不执行if (dev->bus->probe)。

            3) spi驱动中有探测函数,所以执行else if (drv->probe)里面的程序,即ret = drv->probe(dev);,从(三)中的int spi_register_driver(struct spi_driver *sdrv)函数可以看到,驱动的探测函数为spi_drv_probe(),程序如下:

    点击(此处)折叠或打开

    1. static int spi_drv_probe(struct device *dev)
    2. {
    3.     const struct spi_driver        *sdrv = to_spi_driver(dev->driver);
    4.     return sdrv->probe(to_spi_device(dev));
    5. }

            说明:

            1) 首先获取spi_driver结构体。

            2) 调用spi_driver结构体中的探测函数,即为(三)中的w25q_probe()函数。
            在really_probe()函数中,调用driver_bound(dev);函数实现设备与驱动的绑定,程序如下:

    点击(此处)折叠或打开

    1. static void driver_bound(struct device *dev)
    2. {
    3.     if (klist_node_attached(&dev->p->knode_driver)) {
    4.         printk(KERN_WARNING "%s: device %s already bound ",
    5.             __func__, kobject_name(&dev->kobj));
    6.         return;
    7.     }
    8.     pr_debug("driver: '%s': %s: bound to device '%s' ", dev_name(dev),
    9.          __func__, dev->driver->name);
    10.     klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
    11.     if (dev->bus)
    12.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
    13.                      BUS_NOTIFY_BOUND_DRIVER, dev);
    14. }

            说明:

            1) 使用klist_add_tail()将设备与驱动链接在一起。

    四、总结

            在device和device_drive结构中,device中存在一个struct device_driver *driver,而在device_drive中并没有同样的包含device结构。对于一个设备来说,只能绑定一个驱动;而对于一个驱动来说,可以对应多个设备。 也就是说这里device中的driver指针将会指向其绑定的驱动。回到probe探测函数,对一个设备驱动进行注册的过程中,会在其相应的总线(也就是其挂接的总线)上发出一个探测,这个探测会搜寻所有挂接在这个总线上的尚未被绑定的设备(也就是driver指针为NULL),然后将driver指针指向这个驱动的结构,同时将这个设备的device结构挂接在device_driver结构中的klist链表中。 当一个设备被注册时,它也会去寻找挂接在同一条总线上的驱动,并将自己与这个驱动联系起来。

    五、spi传输函数

            spi核心提供了数据传输函数,如下:

    点击(此处)折叠或打开

    1. static inline void spi_message_init(struct spi_message *m)
    2. {
    3.     memset(m, 0, sizeof *m);
    4.     INIT_LIST_HEAD(&m->transfers);
    5. }
    6. static inline void
    7. spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
    8. {
    9.     list_add_tail(&t->transfer_list, &m->transfers);
    10. }
    11. static inline int
    12. spi_write(struct spi_device *spi, const void *buf, size_t len)
    13. {
    14.     struct spi_transfer    t = {
    15.             .tx_buf        = buf,
    16.             .len        = len,
    17.         };
    18.     struct spi_message    m;
    19.     spi_message_init(&m);
    20.     spi_message_add_tail(&t, &m);
    21.     return spi_sync(spi, &m);
    22. }
    23. static inline int
    24. spi_read(struct spi_device *spi, void *buf, size_t len)
    25. {
    26.     struct spi_transfer    t = {
    27.             .rx_buf        = buf,
    28.             .len        = len,
    29.         };
    30.     struct spi_message    m;
    31.     spi_message_init(&m);
    32.     spi_message_add_tail(&t, &m);
    33.     return spi_sync(spi, &m);
    34. }
    35. static inline ssize_t spi_w8r8(struct spi_device *spi, u8 cmd)
    36. {
    37.     ssize_t            status;
    38.     u8            result;
    39.     status = spi_write_then_read(spi, &cmd, 1, &result, 1);
    40.     /* return negative errno or unsigned value */
    41.     return (status < 0) ? status : result;
    42. }
    43. static inline ssize_t spi_w8r16(struct spi_device *spi, u8 cmd)
    44. {
    45.     ssize_t            status;
    46.     u16            result;
    47.     status = spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);
    48.     /* return negative errno or unsigned value */
    49.     return (status < 0) ? status : result;
    50. }

            说明:

            1) 传输开始时,首先初始化spi_message,然后将传输的spi_transfer链入spi_message中。
            2) spi_message中,有一个transfers队列,spi_transfer结构体通过这个队列挂到spi_message中。一个spi_message代表一次传输会话,spi_transfer代表一次单独的IO操作。比如,有些spi设备需要先读后写,那么这个读写过程就是一次spi会话,里面包括两个transfer,一个定义写操作的参数,另一个定义读操作的参数。

            3) 最后都是调用spi_sync()函数实现传输的,如下:

    点击(此处)折叠或打开

    1. int spi_sync(struct spi_device *spi, struct spi_message *message)
    2. {
    3.     return __spi_sync(spi, message, 0);
    4. }
    5. static int __spi_sync(struct spi_device *spi, struct spi_message *message,
    6.          int bus_locked)
    7. {
    8.     DECLARE_COMPLETION_ONSTACK(done);
    9.     int status;
    10.     struct spi_master *master = spi->master;
    11.     message->complete = spi_complete;
    12.     message->context = &done;
    13.     if (!bus_locked)
    14.         mutex_lock(&master->bus_lock_mutex);
    15.     status = spi_async_locked(spi, message);
    16.     if (!bus_locked)
    17.         mutex_unlock(&master->bus_lock_mutex);
    18.     if (status == 0) {
    19.         wait_for_completion(&done);
    20.         status = message->status;
    21.     }
    22.     message->context = NULL;
    23.     return status;
    24. }
    25. int spi_async_locked(struct spi_device *spi, struct spi_message *message)
    26. {
    27.     struct spi_master *master = spi->master;
    28.     int ret;
    29.     unsigned long flags;
    30.     spin_lock_irqsave(&master->bus_lock_spinlock, flags);
    31.     ret = __spi_async(spi, message);
    32.     spin_unlock_irqrestore(&master->bus_lock_spinlock, flags);
    33.     return ret;
    34. }
    35. static int __spi_async(struct spi_device *spi, struct spi_message *message)
    36. {
    37.     struct spi_master *master = spi->master;
    38.     /* Half-duplex links include original MicroWire, and ones with
    39.      * only one data pin like SPI_3WIRE (switches direction) or where
    40.      * either MOSI or MISO is missing. They can also be caused by
    41.      * software limitations.
    42.      */
    43.     if ((master->flags & SPI_MASTER_HALF_DUPLEX)
    44.             || (spi->mode & SPI_3WIRE)) {
    45.         struct spi_transfer *xfer;
    46.         unsigned flags = master->flags;
    47.         list_for_each_entry(xfer, &message->transfers, transfer_list) {
    48.             if (xfer->rx_buf && xfer->tx_buf)
    49.                 return -EINVAL;
    50.             if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf)
    51.                 return -EINVAL;
    52.             if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf)
    53.                 return -EINVAL;
    54.         }
    55.     }
    56.     message->spi = spi;
    57.     message->status = -EINPROGRESS;
    58.     return master->transfer(spi, message);
    59. }

            说明:

            1) 由上面的函数调用轨迹看,最后就是调用master的transfer函数实现传输的。

  • 相关阅读:
    MongoDB安装
    前端构建工具gulp入门教程
    限制input输入类型(多种方法实现)
    【E20200105-1】Centos 7.x 下vsftpd配置文件常用配置详解
    【E20200102-1】centos 7 下vsftp的安装和配置
    【E20200101-1】Centos 7.x 关闭防火墙(firewall)和SELinux
    Linux下如何修改用户默认目录
    linux给普通用户增加ssh权限
    在IIS7中应用Application Request Routing配置反向代理
    vmware相关服务默认禁用 修改服务弹出服务拒绝访问解决办法
  • 原文地址:https://www.cnblogs.com/muhuacat/p/7061908.html
Copyright © 2011-2022 走看看