從DTS到驅動加載的過程分析

一、驅動中的probe函數如何被調用?


    首先,我們知道驅動執行的起始函數是init函數。以I2C驅動爲例。

(cm36283.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int __init cm36283_init(void)  
  2. {  
  3.     int err = 0;  
  4.     err = i2c_add_driver(&cm36283_driver);
  5.     return err;  
  6. }  
  7.   
  8. module_init(cm36283_init);  

(i2c.h)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define i2c_add_driver(driver) \  
  2.     i2c_register_driver(THIS_MODULE, driver)  

(i2c-core.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  
  2. {  
  3.     int res;  
  4.   
  5.     /* Can't register until after driver model init */  
  6.     if (unlikely(WARN_ON(!i2c_bus_type.p)))  
  7.         return -EAGAIN;  
  8.   
  9.     /* add the driver to the list of i2c drivers in the driver core */  
  10.     driver->driver.owner = owner;  
  11.     driver->driver.bus = &i2c_bus_type;  
  12.   
  13.     /* When registration returns, the driver core 
  14.      * will have called probe() for all matching-but-unbound devices. 
  15.      */  
  16.     res = driver_register(&driver->driver);</span>  
  17.     if (res)  
  18.         return res;  
  19.   
  20.     /* Drivers should switch to dev_pm_ops instead. */  
  21.     if (driver->suspend)  
  22.         pr_warn("i2c-core: driver [%s] using legacy suspend method\n",  
  23.             driver->driver.name);  
  24.     if (driver->resume)  
  25.         pr_warn("i2c-core: driver [%s] using legacy resume method\n",  
  26.             driver->driver.name);  
  27.   
  28.     pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);  
  29.   
  30.     INIT_LIST_HEAD(&driver->clients);  
  31.     /* Walk the adapters that are already present */  
  32.     i2c_for_each_dev(driver, __process_new_driver);  
  33.   
  34.     return 0;  
  35. }  
  36. EXPORT_SYMBOL(i2c_register_driver);  

(driver.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int driver_register(struct device_driver *drv)  
  2. {  
  3.     int ret;  
  4.     struct device_driver *other;  
  5.   
  6.     BUG_ON(!drv->bus->p);  
  7.   
  8.     if ((drv->bus->probe && drv->probe) ||  
  9.         (drv->bus->remove && drv->remove) ||  
  10.         (drv->bus->shutdown && drv->shutdown))  
  11.         printk(KERN_WARNING "Driver '%s' needs updating - please use "  
  12.             "bus_type methods\n", drv->name);  
  13.   
  14.     other = driver_find(drv->name, drv->bus);  
  15.     if (other) {  
  16.         printk(KERN_ERR "Error: Driver '%s' is already registered, "  
  17.             "aborting...\n", drv->name);  
  18.         return -EBUSY;  
  19.     }  
  20.   
  21.     ret = bus_add_driver(drv);</span>  
  22.     if (ret)  
  23.         return ret;  
  24.     ret = driver_add_groups(drv, drv->groups);  
  25.     if (ret)  
  26.         bus_remove_driver(drv);  
  27.     return ret;  
  28. }  
(bus.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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.   
  7.     bus = bus_get(drv->bus);  
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);  
  12.   
  13.     priv = kzalloc(sizeof(*priv), GFP_KERNEL);  
  14.     if (!priv) {  
  15.         error = -ENOMEM;  
  16.         goto out_put_bus;  
  17.     }  
  18.     klist_init(&priv->klist_devices, NULL, NULL);  
  19.     priv->driver = drv;  
  20.     drv->p = priv;  
  21.     priv->kobj.kset = bus->p->drivers_kset;  
  22.     error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,  
  23.                      "%s", drv->name);  
  24.     if (error)  
  25.         goto out_unregister;  
  26.   
  27.     klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);  
  28.     if (drv->bus->p->drivers_autoprobe) {  
  29.         <span style="color:#FF6666;">error = driver_attach(drv);</span>  
  30.         if (error)  
  31.             goto out_unregister;  
  32.     }  
  33.     module_add_driver(drv->owner, drv);  
  34.   
  35.     error = driver_create_file(drv, &driver_attr_uevent);  
  36.     if (error) {  
  37.         printk(KERN_ERR "%s: uevent attr (%s) failed\n",  
  38.             __func__, drv->name);  
  39.     }  
  40.     error = driver_add_attrs(bus, drv);  
  41.     if (error) {  
  42.         /* How the hell do we get out of this pickle? Give up */  
  43.         printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  
  44.             __func__, drv->name);  
  45.     }  
  46.   
  47.     if (!drv->suppress_bind_attrs) {  
  48.         error = add_bind_files(drv);  
  49.         if (error) {  
  50.             /* Ditto */  
  51.             printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  
  52.                 __func__, drv->name);  
  53.         }  
  54.     }  
  55.   
  56.     kobject_uevent(&priv->kobj, KOBJ_ADD);  
  57.     return 0;  
  58.   
  59. out_unregister:  
  60.     kobject_put(&priv->kobj);  
  61.     kfree(drv->p);  
  62.     drv->p = NULL;  
  63. out_put_bus:  
  64.     bus_put(bus);  
  65.     return error;  
  66. }  
    driver註冊到bus上時,同時會建立uevent屬性文件及bus->attr數組中的屬性文件(如果 bus->attr 有的話)。


(dd.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);  
  4. }  
  5. EXPORT_SYMBOL_GPL(driver_attach);  

(bus.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  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.   
  8.     if (!bus)  
  9.         return -EINVAL;  
  10.   
  11.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  12.                  (start ? &start->p->knode_bus : NULL));  
  13.     while ((dev = next_device(&i)) && !error)  
  14.         error = <span style="color:#FF6666;">fn(dev, data);</span>  
  15.     klist_iter_exit(&i);  
  16.     return error;  
  17. }  
  18. EXPORT_SYMBOL_GPL(bus_for_each_dev);  

(dd.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int __driver_attach(struct device *dev, void *data)  
  2. {  
  3.     struct device_driver *drv = data;  
  4.   
  5.     /* 
  6.      * Lock device and try to bind to it. We drop the error 
  7.      * here and always return 0, because we need to keep trying 
  8.      * to bind to devices and some drivers will return an error 
  9.      * simply if it didn't support the device. 
  10.      * 
  11.      * driver_probe_device() will spit a warning if there 
  12.      * is an error. 
  13.      */  
  14.   
  15.     if (!driver_match_device(drv, dev))</strong>  
  16.         return 0;  
  17.   
  18.     if (dev->parent) /* Needed for USB */  
  19.         device_lock(dev->parent);  
  20.     device_lock(dev);  
  21.     if (!dev->driver)  
  22.         <strong><span style="color:#FF6666;">driver_probe_device(drv, dev);</span></strong>  
  23.     device_unlock(dev);  
  24.     if (dev->parent)  
  25.         device_unlock(dev->parent);  
  26.   
  27.     return 0;  
  28. }  

      driver_match_device调用bus上的match函数进行匹配。具体可以参照各种总线match匹配函数

    匹配成功后,会调用driver的probe函数。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int driver_probe_device(struct device_driver *drv, struct device *dev)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     if (!device_is_registered(dev))  
  6.         return -ENODEV;  
  7.   
  8.     pr_debug("bus: '%s': %s: matched device %s with driver %s\n",  
  9.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  10.   
  11.     pm_runtime_get_noresume(dev);  
  12.     pm_runtime_barrier(dev);  
  13.     <span style="color:#FF6666;">ret = really_probe(dev, drv);</span>  
  14.     pm_runtime_put_sync(dev);  
  15.   
  16.     return ret;  
  17. }  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int really_probe(struct device *dev, struct device_driver *drv)  
  2. {  
  3.     int ret = 0;  
  4.   
  5.     atomic_inc(&probe_count);  
  6.     pr_debug("bus: '%s': %s: probing driver %s with device %s\n",  
  7.          drv->bus->name, __func__, drv->name, dev_name(dev));  
  8.     WARN_ON(!list_empty(&dev->devres_head));  
  9.   
  10.     dev->driver = drv;  
  11.   
  12.     /* If using pinctrl, bind pins now before probing */  
  13.     ret = pinctrl_bind_pins(dev);  
  14.     if (ret)  
  15.         goto probe_failed;  
  16.   
  17.     if (driver_sysfs_add(dev)) {  
  18.         printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",  
  19.             __func__, dev_name(dev));  
  20.         goto probe_failed;  
  21.     }  
  22.   
  23.     if (dev->bus->probe) {  
  24.         ret = dev->bus->probe(dev);  
  25.         if (ret)  
  26.             goto probe_failed;  
  27.     } else if (drv->probe) {  
  28.         <span style="color:#FF6666;">ret = drv->probe(dev);</span>  
  29.         if (ret)  
  30.             goto probe_failed;  
  31.     }
  32.   
  33.     driver_bound(dev);  
  34.     ret = 1;  
  35.     pr_debug("bus: '%s': %s: bound device %s to driver %s\n",  
  36.          drv->bus->name, __func__, dev_name(dev), drv->name);  
  37.     goto done;  
  38.   
  39. probe_failed:  
  40.     devres_release_all(dev);  
  41.     driver_sysfs_remove(dev);  
  42.     dev->driver = NULL;  
  43.   
  44.     if (ret == -EPROBE_DEFER) {  
  45.         /* Driver requested deferred probing */  
  46.         dev_info(dev, "Driver %s requests probe deferral\n", drv->name);  
  47.         driver_deferred_probe_add(dev);  
  48.     } else if (ret != -ENODEV && ret != -ENXIO) {  
  49.         /* driver matched but the probe failed */  
  50.         printk(KERN_WARNING  
  51.                "%s: probe of %s failed with error %d\n",  
  52.                drv->name, dev_name(dev), ret);  
  53.     } else {  
  54.         pr_debug("%s: probe of %s rejects match %d\n",  
  55.                drv->name, dev_name(dev), ret);  
  56.     }  
  57.     /* 
  58.      * Ignore errors returned by ->probe so that the next driver can try 
  59.      * its luck. 
  60.      */  
  61.     ret = 0;  
  62. done:  
  63.     atomic_dec(&probe_count);  
  64.     wake_up(&probe_waitqueue);  
  65.     return ret;  
  66. }  
     如果bus->probe爲空,就執行drv->probe

二、驅動中的probe函數參數如何產生的?


根據函數參數傳遞可以跟蹤到,是從bus_for_each_dev中獲得參數的。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int driver_attach(struct device_driver *drv)  
  2. {  
  3.     return bus_for_each_dev(<span style="color:#FF0000;"><strong>drv->bus, NULL, drv, __driver_attach</strong></span>);  
  4. }  
  5. EXPORT_SYMBOL_GPL(driver_attach);  
  6.   
  7. int bus_for_each_dev(struct bus_type *bus, struct device *start,  
  8.              void *data, int (*fn)(struct device *, void *))  
  9. {  
  10.     struct klist_iter i;  
  11.     struct device *dev;  
  12.     int error = 0;  
  13.   
  14.     if (!bus)  
  15.         return -EINVAL;  
  16.   
  17.     klist_iter_init_node(&bus->p->klist_devices, &i,  
  18.                  (start ? &start->p->knode_bus : NULL));  
  19.     while ((<strong><span style="color:#FF0000;">dev = next_device(&i)</span></strong>) && !error)  
  20.         error = fn(dev, data);  
  21.     klist_iter_exit(&i);  
  22.     return error;  
  23. }  

    這樣可以看到klist_iter_init_node實際調用klist_iter_init_node(&bus->p->klist_devices, &i,NULL),所以,跟蹤klist_iter_init_node函數,發現並沒做什麼相關重要的東西。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void klist_iter_init_node(struct klist *k, struct klist_iter *i,  
  2.               struct klist_node *n)  
  3. {  
  4.     i->i_klist = k;  
  5.     i->i_cur = n;  
  6.     if (n)  
  7.         kref_get(&n->n_ref);  
  8. }  
  9. EXPORT_SYMBOL_GPL(klist_iter_init_node);  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static struct device *next_device(struct klist_iter *i)  
  2. {  
  3.     struct klist_node *n = klist_next(i);  
  4.     struct device *dev = NULL;  
  5.     struct device_private *dev_prv;  
  6.   
  7.     if (n) {  
  8.         dev_prv =<span style="color:#FF0000;"> to_device_private_bus(n);</span>  
  9.         <span style="color:#FF0000;">dev = dev_prv->device;</span>  
  10.     }  
  11.     return dev;  
  12. }  
    可以看出,只要得到dev_prv就可以得到dev。下面的問題就是dev_prv中的dev如何被添加進去的呢?
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define to_device_private_bus(obj)  \  
  2.     container_of(obj, struct device_private, knode_bus)  

這裏引用其他一些文章解釋:

先上几个struct:

struct klist_iter {

         struct  klist                 *i_klist;

         struct  klist_node      *i_cur;

};

 

struct klist {

         spinlock_t                  k_lock;

         struct  list_head        k_list;

         void                    (*get)(struct klist_node *);

         void                    (*put)(struct klist_node *);

} __attribute__ ((aligned (sizeof(void*))));

 

struct klist_node {

         void                    *n_klist;   /* never access directly */

         struct    list_head        n_node;

         struct    kref                  n_ref;

};

 

struct kref {

         atomic_t    refcount;

};

 

         其中的klist_iter_init_node(&bus->p->klist_devices, &i,(start ?&start->p->knode_bus :NULL))作用是定义个klist_iter指向此klist,以便以后直接使用,如图:

 

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static struct device *next_device(struct klist_iter *i)  
  2. {  
  3.     struct klist_node *n =<span style="color:#FF0000;"> <strong>klist_next(i);</strong></span>  
  4.     struct device *dev = NULL;  
  5.     struct device_private *dev_prv;  
  6.   
  7.     if (n) {  
  8.         dev_prv = to_device_private_bus(n);  
  9.         dev = dev_prv->device;  
  10.     }  
  11.     return dev;  
  12. }  

(klist.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct klist_node *klist_next(struct klist_iter *i)  
  2. {  
  3.     void (*put)(struct klist_node *) = i->i_klist->put;  
  4.     struct klist_node *last = i->i_cur;  <span style="color:#FFCCCC;"> <span style="color:#009900;">// NULL</span></span>  
  5.     struct klist_node *next;  
  6.   
  7.     spin_lock(&i->i_klist->k_lock);  
  8.   
  9.     if (last) {  
  10.         next = to_klist_node(last->n_node.next);  
  11.         if (!klist_dec_and_del(last))  
  12.             put = NULL;  
  13.     } else  
  14.         <span style="color:#FF0000;">next = to_klist_node(i->i_klist->k_list.next);</span>  
  15.   
  16.     i->i_cur = NULL;  
  17.     while (next != to_klist_node(&i->i_klist->k_list)) {  
  18.         if (likely(!knode_dead(next))) {  
  19.             kref_get(&next->n_ref);  
  20.             i->i_cur = next;  
  21.             break;  
  22.         }  
  23.         next = to_klist_node(next->n_node.next);  
  24.     }  
  25.   
  26.     spin_unlock(&i->i_klist->k_lock);  
  27.   
  28.     if (put && last)  
  29.         put(last);  
  30.     return i->i_cur;  
  31. }  
  32. EXPORT_SYMBOL_GPL(klist_next);  

這裏可以知道i->i_cur=NULL,i->i_klist=&bus->p->klist_devices。 to_klist_node 從klist中取得下一個node賦值給next,然後執行一次while循環裏的內容,將next賦值給i->i_cur。這樣就得到了klist_node.  to_device_private_bus通過container_of 得到struct device_private。下圖說明其中的關係。


     

    由此,可以知道DTS解析後的設備都是通過klist和klist_node掛載到bus上的。


三、 DTS的解析掛載

dts文件編譯時通過dtc被編譯成了dtb文件。然後在內核啓動時該文件被解析。DTS节点信息保存到allnodes鏈表中。

start_kernel() --> setup_arch() --> unflatten_device_tree()


随后,当系统启动到board文件时,会调用.init_machine,高通8974平台对应的是msm8974_init()。接着调用of_platform_populate(....)接口,加载平台总线和平台设备。


(kernel/arch/arm/mach-msm/board-8226.c)


[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void __init msm8226_init(void)  
  2. {  
  3.     board_dt_populate(adata);</span>  
  4.     msm8226_add_drivers();  
  5. }  

(kernel/arch/arm/mach-msm/board-dt.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void __init board_dt_populate(struct of_dev_auxdata *adata)  
  2. {  
  3.     of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
  4.   
  5.     /* Explicitly parent the /soc devices to the root node to preserve 
  6.      * the kernel ABI (sysfs structure, etc) until userspace is updated 
  7.      */  
  8.     of_platform_populate(of_find_node_by_path("/soc"),  
  9.                  of_default_bus_match_table, adata, NULL);
  10. }  

       上面兩句話,一個是以“/”爲根進行遍歷;一個是遍歷allnodes鏈找到“/soc”,並以這一節點爲根節點進行遍歷。

(kernel/driver/of/platform.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int of_platform_populate(struct device_node *root,  
  2.             const struct of_device_id *matches,  
  3.             const struct of_dev_auxdata *lookup,  
  4.             struct device *parent)  
  5. {  
  6.     struct device_node *child;  
  7.     int rc = 0;  
  8.   
  9.     root = root ? of_node_get(root) : of_find_node_by_path("/");  
  10.     if (!root)  
  11.         return -EINVAL;  
  12.   
  13.     for_each_child_of_node(root, child) {  
  14.         rc = of_platform_bus_create(child, matches, lookup, parent, true);  
  15.         if (rc)  
  16.             break;  
  17.     }  
  18.   
  19.     of_node_put(root);  
  20.     return rc;  
  21. }  
  22. #endif /* CONFIG_OF_ADDRESS */  

      of_platform_populate遍歷根節點下的所有節點,分配建立platform device。for_each_child_of_node實現遍歷父節點下的所有兄弟節點及孩子節點。
    

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define for_each_child_of_node(parent, child) \  
  2.     for (child = of_get_next_child(parent, NULL); child != NULL; \  
  3.          child = of_get_next_child(parent, child))  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct device_node *of_get_next_child(const struct device_node *node,  
  2.     struct device_node *prev)  
  3. {  
  4.     struct device_node *next;  
  5.   
  6.     read_lock(&devtree_lock);  
  7.     next = prev ? prev->sibling : node->child;  
  8.     for (; next; next = next->sibling)  
  9.         if (of_node_get(next))  
  10.             break;  
  11.     of_node_put(prev);  
  12.     read_unlock(&devtree_lock);  
  13.     return next;  
  14. }  
  15. EXPORT_SYMBOL(of_get_next_child);  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. (kernel/driver/of/platform.c)  
  2.   
  3. static int of_platform_bus_create(struct device_node *bus,  
  4.                   const struct of_device_id *matches,  
  5.                   const struct of_dev_auxdata *lookup,  
  6.                   struct device *parent, bool strict)  
  7. {  
  8.     const struct of_dev_auxdata *auxdata;  
  9.     struct device_node *child;  
  10.     struct platform_device *dev;  
  11.     const char *bus_id = NULL;  
  12.     void *platform_data = NULL;  
  13.     int rc = 0;  
  14.   
  15.     /* Make sure it has a compatible property */  
  16.     if (strict && (!of_get_property(bus, "compatible", NULL))) {  
  17.         pr_debug("%s() - skipping %s, no compatible prop\n",  
  18.              __func__, bus->full_name);  
  19.         return 0;  
  20.     }  
  21.   
  22.     auxdata = of_dev_lookup(lookup, bus);  
  23.     if (auxdata) {  
  24.         bus_id = auxdata->name;  
  25.         platform_data = auxdata->platform_data;  
  26.     }  
  27.   
  28.     if (of_device_is_compatible(bus, "arm,primecell")) {  
  29.         of_amba_device_create(bus, bus_id, platform_data, parent);  
  30.         return 0;  
  31.     }  
  32.   
  33.     dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
  34.     if (!dev || !of_match_node(matches, bus))  
  35.         return 0;  
  36.   
  37.      for_each_child_of_node(bus, child) {  
  38.         pr_debug("   create child: %s\n", child->full_name);  
  39.          rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);  
  40.         if (rc) {  
  41.             of_node_put(child);  
  42.             break;  
  43.         }  
  44.     }  
  45.     return rc;  
  46. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct platform_device *of_platform_device_create_pdata(  
  2.                     struct device_node *np,  
  3.                     const char *bus_id,  
  4.                     void *platform_data,  
  5.                     struct device *parent)  
  6. {  
  7.     struct platform_device *dev;  
  8.   
  9.     if (!of_device_is_available(np))  
  10.         return NULL;  
  11.   
  12.     dev = of_device_alloc(np, bus_id, parent);
  13.     if (!dev)  
  14.         return NULL;  
  15.   
  16. #if defined(CONFIG_MICROBLAZE)  
  17.     dev->archdata.dma_mask = 0xffffffffUL;  
  18. #endif  
  19.     dev->dev.coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);  
  20.     dev->dev.bus = &platform_bus_type;  
  21.     dev->dev.platform_data = platform_data;  
  22.   
  23.     /* We do not fill the DMA ops for platform devices by default. 
  24.      * This is currently the responsibility of the platform code 
  25.      * to do such, possibly using a device notifier 
  26.      */  
  27.   
  28.     if (of_device_add(dev) != 0) {  
  29.         platform_device_put(dev);  
  30.         return NULL;  
  31.     }  
  32.   
  33.     return dev;  
  34. }  

      of_device_alloc根據allnodes的device node分配platform device空間。然後設置platform device的bus總線。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct platform_device *of_device_alloc(struct device_node *np,  
  2.                   const char *bus_id,  
  3.                   struct device *parent)  
  4. {  
  5.     struct platform_device *dev;  
  6.     int rc, i, num_reg = 0, num_irq;  
  7.     struct resource *res, temp_res;  
  8.   
  9.     dev = platform_device_alloc("", -1);  
  10.     if (!dev)  
  11.         return NULL;  
  12.   
  13.     /* count the io and irq resources */  
  14.     if (of_can_translate_address(np))  
  15.         while (of_address_to_resource(np, num_reg, &temp_res) == 0)  
  16.             num_reg++;  
  17.     num_irq = of_irq_count(np);  
  18.   
  19.     /* Populate the resource table */  
  20.     if (num_irq || num_reg) {  
  21.         res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);  
  22.         if (!res) {  
  23.             platform_device_put(dev);  
  24.             return NULL;  
  25.         }  
  26.   
  27.         dev->num_resources = num_reg + num_irq;  
  28.         dev->resource = res;  
  29.         for (i = 0; i < num_reg; i++, res++) {  
  30.             rc = of_address_to_resource(np, i, res);  
  31.             WARN_ON(rc);  
  32.         }  
  33.         WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);  
  34.     }  
  35.   
  36.     dev->dev.of_node = of_node_get(np);
  37. #if defined(CONFIG_MICROBLAZE)  
  38.     dev->dev.dma_mask = &dev->archdata.dma_mask;  
  39. #endif  
  40.     dev->dev.parent = parent;  
  41.   
  42.     if (bus_id)  
  43.         dev_set_name(&dev->dev, "%s", bus_id);  
  44.     else  
  45.         of_device_make_bus_id(&dev->dev);  
  46.   
  47.     return dev;  
  48. }  
  49. EXPORT_SYMBOL(of_device_alloc);  
         分配platform device空間後,注意將device node賦值給dev->dev.of_node,這也就是爲什麼經常在probe函數中見到通過pdev->dev.of_node得到dts 設備節點,並從該節點中讀取相關信息。

I2C platform device驅動加載在i2c-qup.c文件中。下面是i2c-qup platform device驅動加載及i2c-client的驅動加載。

(i2c-qup.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static int __devinit  
  2. qup_i2c_probe(struct platform_device *pdev)  
  3. {  
  4.     struct qup_i2c_dev  *dev;  
  5.     struct resource         *qup_mem, *gsbi_mem, *qup_io, *gsbi_io, *res;  
  6.     struct resource     *in_irq, *out_irq, *err_irq;  
  7.     struct clk         *clk, *pclk;  
  8.     int  ret = 0;  
  9.     int  i;  
  10.     int  dt_gpios[I2C_GPIOS_DT_CNT];  
  11.     bool use_device_tree = pdev->dev.of_node;  
  12.     struct msm_i2c_platform_data *pdata;  
  13.   
  14.     gsbi_mem = NULL;  
  15.     dev_dbg(&pdev->dev, "qup_i2c_probe\n");  
  16.   
  17.     if (use_device_tree) {  
  18.         pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);  
  19.         if (!pdata)  
  20.             return -ENOMEM;  
  21.   
  22.         ret = msm_i2c_rsrcs_dt_to_pdata_map(pdev, pdata, dt_gpios);  
  23.         if (ret)  
  24.             goto get_res_failed;  
  25.     } else  
  26.         pdata = pdev->dev.platform_data;  
  27.   
  28.     if (!pdata) {  
  29.         dev_err(&pdev->dev, "platform data not initialized\n");  
  30.         return -ENOSYS;  
  31.     }  
  32.     qup_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,  
  33.                         "qup_phys_addr");  
  34.     if (!qup_mem) {  
  35.         dev_err(&pdev->dev,  
  36.             "platform_get_resource_byname(qup_phys_addr) failed\n");  
  37.         ret = -ENODEV;  
  38.         goto get_res_failed;  
  39.     }  
  40.   
  41.     /* 
  42.      * We only have 1 interrupt for new hardware targets and in_irq, 
  43.      * out_irq will be NULL for those platforms 
  44.      */  
  45.     in_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,  
  46.                         "qup_in_intr");  
  47.   
  48.     out_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,  
  49.                         "qup_out_intr");  
  50.   
  51.     err_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ,  
  52.                         "qup_err_intr");  
  53.     if (!err_irq) {  
  54.         dev_err(&pdev->dev, "no error irq resource?\n");  
  55.         ret = -ENODEV;  
  56.         goto get_res_failed;  
  57.     }  
  58.   
  59.     qup_io = request_mem_region(qup_mem->start, resource_size(qup_mem),  
  60.                     pdev->name);  
  61.     if (!qup_io) {  
  62.         dev_err(&pdev->dev, "QUP region already claimed\n");  
  63.         ret = -EBUSY;  
  64.         goto get_res_failed;  
  65.     }  
  66.     if (!pdata->use_gsbi_shared_mode) {  
  67.         gsbi_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,  
  68.                             "gsbi_qup_i2c_addr");  
  69.         if (!gsbi_mem) {  
  70.             dev_dbg(&pdev->dev, "Assume BLSP\n");  
  71.             /* 
  72.              * BLSP core does not need protocol programming so this 
  73.              * resource is not expected 
  74.              */  
  75.             goto blsp_core_init;  
  76.         }  
  77.         gsbi_io = request_mem_region(gsbi_mem->start,  
  78.                         resource_size(gsbi_mem),  
  79.                         pdev->name);  
  80.         if (!gsbi_io) {  
  81.             dev_err(&pdev->dev, "GSBI region already claimed\n");  
  82.             ret = -EBUSY;  
  83.             goto err_res_failed;  
  84.         }  
  85.     }  
  86.   
  87. blsp_core_init:  
  88.     clk = clk_get(&pdev->dev, "core_clk");  
  89.     if (IS_ERR(clk)) {  
  90.         dev_err(&pdev->dev, "Could not get core_clk\n");  
  91.         ret = PTR_ERR(clk);  
  92.         goto err_clk_get_failed;  
  93.     }  
  94.   
  95.     pclk = clk_get(&pdev->dev, "iface_clk");  
  96.     if (IS_ERR(pclk)) {  
  97.         dev_err(&pdev->dev, "Could not get iface_clk\n");  
  98.         ret = PTR_ERR(pclk);  
  99.         clk_put(clk);  
  100.         goto err_clk_get_failed;  
  101.     }  
  102.   
  103.     /* We support frequencies upto FAST Mode(400KHz) */  
  104.     if (pdata->clk_freq <= 0 ||  
  105.             pdata->clk_freq > 400000) {  
  106.         dev_err(&pdev->dev, "clock frequency not supported\n");  
  107.         ret = -EIO;  
  108.         goto err_config_failed;  
  109.     }  
  110.   
  111.     dev = kzalloc(sizeof(struct qup_i2c_dev), GFP_KERNEL);  
  112.     if (!dev) {  
  113.         ret = -ENOMEM;  
  114.         goto err_alloc_dev_failed;  
  115.     }  
  116.   
  117.     dev->dev = &pdev->dev;  
  118.     if (in_irq)  
  119.         dev->in_irq = in_irq->start;  
  120.     if (out_irq)  
  121.         dev->out_irq = out_irq->start;  
  122.     dev->err_irq = err_irq->start;  
  123.     if (in_irq && out_irq)  
  124.         dev->num_irqs = 3;  
  125.     else  
  126.         dev->num_irqs = 1;  
  127.     dev->clk = clk;  
  128.     dev->pclk = pclk;  
  129.     dev->base = ioremap(qup_mem->start, resource_size(qup_mem));  
  130.     if (!dev->base) {  
  131.         ret = -ENOMEM;  
  132.         goto err_ioremap_failed;  
  133.     }  
  134.   
  135.     /* Configure GSBI block to use I2C functionality */  
  136.     if (gsbi_mem) {  
  137.         dev->gsbi = ioremap(gsbi_mem->start, resource_size(gsbi_mem));  
  138.         if (!dev->gsbi) {  
  139.             ret = -ENOMEM;  
  140.             goto err_gsbi_failed;  
  141.         }  
  142.     }  
  143.   
  144.     for (i = 0; i < ARRAY_SIZE(i2c_rsrcs); ++i) {  
  145.         if (use_device_tree && i < I2C_GPIOS_DT_CNT) {  
  146.             dev->i2c_gpios[i] = dt_gpios[i];  
  147.         } else {  
  148.             res = platform_get_resource_byname(pdev, IORESOURCE_IO,  
  149.                                i2c_rsrcs[i]);  
  150.             dev->i2c_gpios[i] = res ? res->start : -1;  
  151.         }  
  152.     }  
  153.   
  154.     platform_set_drvdata(pdev, dev);  
  155.   
  156.     dev->one_bit_t = (USEC_PER_SEC/pdata->clk_freq) + 1;  
  157.     dev->pdata = pdata;  
  158.     dev->clk_ctl = 0;  
  159.     dev->pos = 0;  
  160.   
  161.     ret = i2c_qup_clk_path_init(pdev, dev);  
  162.     if (ret) {  
  163.         dev_err(&pdev->dev,  
  164.         "Failed to init clock path-voting data structs. err:%d", ret);  
  165.         /* disable i2c_qup_clk_path_xxx() functionality */  
  166.         dev->pdata->master_id = 0;  
  167.     }  
  168.   
  169.     if (dev->pdata->src_clk_rate <= 0) {  
  170.         dev_info(&pdev->dev,  
  171.             "No src_clk_rate specified in platfrom data\n");  
  172.         dev_info(&pdev->dev, "Using default clock rate %dHz\n",  
  173.                             DEFAULT_CLK_RATE);  
  174.         dev->pdata->src_clk_rate = DEFAULT_CLK_RATE;  
  175.     }  
  176.   
  177.     ret = clk_set_rate(dev->clk, dev->pdata->src_clk_rate);  
  178.     if (ret)  
  179.         dev_info(&pdev->dev, "clk_set_rate(core_clk, %dHz):%d\n",  
  180.                     dev->pdata->src_clk_rate, ret);  
  181.   
  182.     clk_prepare_enable(dev->clk);  
  183.     clk_prepare_enable(dev->pclk);  
  184.     /* 
  185.      * If bootloaders leave a pending interrupt on certain GSBI's, 
  186.      * then we reset the core before registering for interrupts. 
  187.      */  
  188.     writel_relaxed(1, dev->base + QUP_SW_RESET);  
  189.     if (qup_i2c_poll_state(dev, 0, true) != 0)  
  190.         goto err_reset_failed;  
  191.     clk_disable_unprepare(dev->clk);  
  192.     clk_disable_unprepare(dev->pclk);  
  193.   
  194.     /* 
  195.      * We use num_irqs to also indicate if we got 3 interrupts or just 1. 
  196.      * If we have just 1, we use err_irq as the general purpose irq 
  197.      * and handle the changes in ISR accordingly 
  198.      * Per Hardware guidelines, if we have 3 interrupts, they are always 
  199.      * edge triggering, and if we have 1, it's always level-triggering 
  200.      */  
  201.     if (dev->num_irqs == 3) {  
  202.         ret = request_irq(dev->in_irq, qup_i2c_interrupt,  
  203.                 IRQF_TRIGGER_RISING, "qup_in_intr", dev);  
  204.         if (ret) {  
  205.             dev_err(&pdev->dev, "request_in_irq failed\n");  
  206.             goto err_request_irq_failed;  
  207.         }  
  208.         /* 
  209.          * We assume out_irq exists if in_irq does since platform 
  210.          * configuration either has 3 interrupts assigned to QUP or 1 
  211.          */  
  212.         ret = request_irq(dev->out_irq, qup_i2c_interrupt,  
  213.                 IRQF_TRIGGER_RISING, "qup_out_intr", dev);  
  214.         if (ret) {  
  215.             dev_err(&pdev->dev, "request_out_irq failed\n");  
  216.             free_irq(dev->in_irq, dev);  
  217.             goto err_request_irq_failed;  
  218.         }  
  219.         ret = request_irq(dev->err_irq, qup_i2c_interrupt,  
  220.                 IRQF_TRIGGER_RISING, "qup_err_intr", dev);  
  221.         if (ret) {  
  222.             dev_err(&pdev->dev, "request_err_irq failed\n");  
  223.             free_irq(dev->out_irq, dev);  
  224.             free_irq(dev->in_irq, dev);  
  225.             goto err_request_irq_failed;  
  226.         }  
  227.     } else {  
  228.         ret = request_irq(dev->err_irq, qup_i2c_interrupt,  
  229.                 IRQF_TRIGGER_HIGH, "qup_err_intr", dev);  
  230.         if (ret) {  
  231.             dev_err(&pdev->dev, "request_err_irq failed\n");  
  232.             goto err_request_irq_failed;  
  233.         }  
  234.     }  
  235.     disable_irq(dev->err_irq);  
  236.     if (dev->num_irqs == 3) {  
  237.         disable_irq(dev->in_irq);  
  238.         disable_irq(dev->out_irq);  
  239.     }  
  240.     i2c_set_adapdata(&dev->adapter, dev);  
  241.     dev->adapter.algo = &qup_i2c_algo;  
  242.     strlcpy(dev->adapter.name,  
  243.         "QUP I2C adapter",  
  244.         sizeof(dev->adapter.name));  
  245.     dev->adapter.nr = pdev->id;  
  246.     dev->adapter.dev.parent = &pdev->dev;  
  247.     if (pdata->msm_i2c_config_gpio)  
  248.         pdata->msm_i2c_config_gpio(dev->adapter.nr, 1);  
  249.   
  250.     mutex_init(&dev->mlock);  
  251.     dev->pwr_state = MSM_I2C_PM_SUSPENDED;  
  252.     /* If the same AHB clock is used on Modem side 
  253.      * switch it on here itself and don't switch it 
  254.      * on and off during suspend and resume. 
  255.      */  
  256.     if (dev->pdata->keep_ahb_clk_on)  
  257.         clk_prepare_enable(dev->pclk);  
  258.   
  259.     ret = i2c_add_numbered_adapter(&dev->adapter);  
  260.     if (ret) {  
  261.         dev_err(&pdev->dev, "i2c_add_adapter failed\n");  
  262.         if (dev->num_irqs == 3) {  
  263.             free_irq(dev->out_irq, dev);  
  264.             free_irq(dev->in_irq, dev);  
  265.         }  
  266.         free_irq(dev->err_irq, dev);  
  267.     } else {  
  268.         if (dev->dev->of_node) {  
  269.             dev->adapter.dev.of_node = pdev->dev.of_node;  
  270.             of_i2c_register_devices(&dev->adapter);
  271.         }  
  272.   
  273.         pm_runtime_set_autosuspend_delay(&pdev->dev, MSEC_PER_SEC);  
  274.         pm_runtime_use_autosuspend(&pdev->dev);  
  275.         pm_runtime_enable(&pdev->dev);  
  276.         return 0;  
  277.     }  
  278.   
  279.   
  280. err_request_irq_failed:  
  281.     if (dev->gsbi)  
  282.         iounmap(dev->gsbi);  
  283. err_reset_failed:  
  284.     clk_disable_unprepare(dev->clk);  
  285.     clk_disable_unprepare(dev->pclk);  
  286.     i2c_qup_clk_path_teardown(dev);  
  287. err_gsbi_failed:  
  288.     iounmap(dev->base);  
  289. err_ioremap_failed:  
  290.     kfree(dev);  
  291. err_alloc_dev_failed:  
  292. err_config_failed:  
  293.     clk_put(clk);  
  294.     clk_put(pclk);  
  295. err_clk_get_failed:  
  296.     if (gsbi_mem)  
  297.         release_mem_region(gsbi_mem->start, resource_size(gsbi_mem));  
  298. err_res_failed:  
  299.     release_mem_region(qup_mem->start, resource_size(qup_mem));  
  300. get_res_failed:  
  301.     if (pdev->dev.of_node)  
  302.         kfree(pdata);  
  303.     return ret;  
  304. }  
i2c、spi等都是platform bus,在msm8974_init()時调用of_platform_populate(....)接口註冊到系統中。這樣在i2c bus驅動中就可以調用of_i2c_register_devices,將i2c設備註冊到i2c bus上。

(of_i2c.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. void of_i2c_register_devices(struct i2c_adapter *adap)  
  2. {  
  3.     void *result;  
  4.     struct device_node *node;  
  5.   
  6.     /* Only register child devices if the adapter has a node pointer set */  
  7.     if (!adap->dev.of_node)  
  8.         return;  
  9.   
  10.     dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");  
  11.   
  12.     for_each_child_of_node(adap->dev.of_node, node) {  
  13.         struct i2c_board_info info = {};  
  14.         struct dev_archdata dev_ad = {};  
  15.         const __be32 *addr;  
  16.         int len;  
  17.   
  18.         dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name);  
  19.   
  20.         if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {  
  21.             dev_err(&adap->dev, "of_i2c: modalias failure on %s\n",  
  22.                 node->full_name);  
  23.             continue;  
  24.         }  
  25.   
  26.         addr = of_get_property(node, "reg", &len);  
  27.         if (!addr || (len < sizeof(int))) {  
  28.             dev_err(&adap->dev, "of_i2c: invalid reg on %s\n",  
  29.                 node->full_name);  
  30.             continue;  
  31.         }  
  32.   
  33.         info.addr = be32_to_cpup(addr);  
  34.         if (info.addr > (1 << 10) - 1) {  
  35.             dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n",  
  36.                 info.addr, node->full_name);  
  37.             continue;  
  38.         }  
  39.   
  40.         info.irq = irq_of_parse_and_map(node, 0);  
  41.         info.of_node = of_node_get(node);  
  42.         info.archdata = &dev_ad;  
  43.   
  44.         request_module("%s%s", I2C_MODULE_PREFIX, info.type);  
  45.   
  46.         <span style="color:#FF0000;">result = i2c_new_device(adap, &info);</span>  
  47.         if (result == NULL) {  
  48.             dev_err(&adap->dev, "of_i2c: Failure registering %s\n",  
  49.                     node->full_name);  
  50.             of_node_put(node);  
  51.             irq_dispose_mapping(info.irq);  
  52.             continue;  
  53.         }  
  54.     }  
  55. }  
  56. EXPORT_SYMBOL(of_i2c_register_devices);  

of_i2c_register_devices從解析後的allnodes鏈表信息取出節點,解析具體信息後,放到stuct i2c_board_info中,用於建立i2c-client。


(I2c-core.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. struct i2c_client *  
  2. i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)  
  3. {  
  4.     struct i2c_client   *client;  
  5.     int         status;  
  6.   
  7.     client = kzalloc(sizeof *client, GFP_KERNEL);  
  8.     if (!client)  
  9.         return NULL;  
  10.   
  11.     client->adapter = adap;  
  12.   
  13.     client->dev.platform_data = info->platform_data;  
  14.   
  15.     if (info->archdata)  
  16.         client->dev.archdata = *info->archdata;  
  17.   
  18.     client->flags = info->flags;  
  19.     client->addr = info->addr;  
  20.     client->irq = info->irq;  
  21.   
  22.     strlcpy(client->name, info->type, sizeof(client->name));  
  23.   
  24.     /* Check for address validity */  
  25.     status = i2c_check_client_addr_validity(client);  
  26.     if (status) {  
  27.         dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n",  
  28.             client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr);  
  29.         goto out_err_silent;  
  30.     }  
  31.   
  32.     /* Check for address business */  
  33.     status = i2c_check_addr_busy(adap, client->addr);  
  34.     if (status)  
  35.         goto out_err;  
  36.   
  37.     client->dev.parent = &client->adapter->dev;  
  38.     client->dev.bus = &i2c_bus_type;  
  39.     client->dev.type = &i2c_client_type;  
  40.     client->dev.of_node = info->of_node;  
  41.   
  42.     /* For 10-bit clients, add an arbitrary offset to avoid collisions */  
  43.     dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),  
  44.              client->addr | ((client->flags & I2C_CLIENT_TEN)  
  45.                      ? 0xa000 : 0));  
  46.     status = device_register(&client->dev);
  47.     if (status)  
  48.         goto out_err;  
  49.   
  50.     dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",  
  51.         client->name, dev_name(&client->dev));  
  52.   
  53.     return client;  
  54.   
  55. out_err:  
  56.     dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x "  
  57.         "(%d)\n", client->name, client->addr, status);  
  58. out_err_silent:  
  59.     kfree(client);  
  60.     return NULL;  
  61. }  
  62. EXPORT_SYMBOL_GPL(i2c_new_device);  


(bus.c)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int device_register(struct device *dev)  
  2. {  
  3.     device_initialize(dev);  
  4.     return device_add(dev);
  5. }  

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int device_add(struct device *dev)  
  2. {  
  3.     struct device *parent = NULL;  
  4.     struct kobject *kobj;  
  5.     struct class_interface *class_intf;  
  6.     int error = -EINVAL;  
  7.   
  8.     dev = get_device(dev);  
  9.     if (!dev)  
  10.         goto done;  
  11.   
  12.     if (!dev->p) {  
  13.         error = device_private_init(dev);  
  14.         if (error)  
  15.             goto done;  
  16.     }  
  17.   
  18.     /* 
  19.      * for statically allocated devices, which should all be converted 
  20.      * some day, we need to initialize the name. We prevent reading back 
  21.      * the name, and force the use of dev_name() 
  22.      */  
  23.     if (dev->init_name) {  
  24.         dev_set_name(dev, "%s", dev->init_name);  
  25.         dev->init_name = NULL;  
  26.     }  
  27.   
  28.     /* subsystems can specify simple device enumeration */  
  29.     if (!dev_name(dev) && dev->bus && dev->bus->dev_name)  
  30.         dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id);  
  31.   
  32.     if (!dev_name(dev)) {  
  33.         error = -EINVAL;  
  34.         goto name_error;  
  35.     }  
  36.   
  37.     pr_debug("device: '%s': %s\n", dev_name(dev), __func__);  
  38.   
  39.     parent = get_device(dev->parent);  
  40.     kobj = get_device_parent(dev, parent);  
  41.     if (kobj)  
  42.         dev->kobj.parent = kobj;  
  43.   
  44.     /* use parent numa_node */  
  45.     if (parent)  
  46.         set_dev_node(dev, dev_to_node(parent));  
  47.   
  48.     /* first, register with generic layer. */  
  49.     /* we require the name to be set before, and pass NULL */  
  50.     error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);  
  51.     if (error)  
  52.         goto Error;  
  53.   
  54.     /* notify platform of device entry */  
  55.     if (platform_notify)  
  56.         platform_notify(dev);  
  57.   
  58.     error = device_create_file(dev, &uevent_attr);  
  59.     if (error)  
  60.         goto attrError;  
  61.   
  62.     if (MAJOR(dev->devt)) {  
  63.         error = device_create_file(dev, &devt_attr);  
  64.         if (error)  
  65.             goto ueventattrError;  
  66.   
  67.         error = device_create_sys_dev_entry(dev);  
  68.         if (error)  
  69.             goto devtattrError;  
  70.   
  71.         devtmpfs_create_node(dev);  
  72.     }  
  73.   
  74.     error = device_add_class_symlinks(dev);  
  75.     if (error)  
  76.         goto SymlinkError;  
  77.     error = device_add_attrs(dev);  
  78.     if (error)  
  79.         goto AttrsError;  
  80.    error = bus_add_device(dev);
  81.     if (error)  
  82.         goto BusError;  
  83.     error = dpm_sysfs_add(dev);  
  84.     if (error)  
  85.         goto DPMError;  
  86.     device_pm_add(dev);  
  87.   
  88.     /* Notify clients of device addition.  This call must come 
  89.      * after dpm_sysfs_add() and before kobject_uevent(). 
  90.      */  
  91.     if (dev->bus)  
  92.         blocking_notifier_call_chain(&dev->bus->p->bus_notifier,  
  93.                          BUS_NOTIFY_ADD_DEVICE, dev);  
  94.   
  95.     kobject_uevent(&dev->kobj, KOBJ_ADD);  
  96.     bus_probe_device(dev);  
  97.     if (parent)  
  98.         klist_add_tail(&dev->p->knode_parent,  
  99.                    &parent->p->klist_children);  
  100.   
  101.     if (dev->class) {  
  102.         mutex_lock(&dev->class->p->mutex);  
  103.         /* tie the class to the device */  
  104.         klist_add_tail(&dev->knode_class,  
  105.                    &dev->class->p->klist_devices);  
  106.   
  107.         /* notify any interfaces that the device is here */  
  108.         list_for_each_entry(class_intf,  
  109.                     &dev->class->p->interfaces, node)  
  110.             if (class_intf->add_dev)  
  111.                 class_intf->add_dev(dev, class_intf);  
  112.         mutex_unlock(&dev->class->p->mutex);  
  113.     }  
  114. done:  
  115.     put_device(dev);  
  116.     return error;  
  117.  DPMError:  
  118.     bus_remove_device(dev);  
  119.  BusError:  
  120.     device_remove_attrs(dev);  
  121.  AttrsError:  
  122.     device_remove_class_symlinks(dev);  
  123.  SymlinkError:  
  124.     if (MAJOR(dev->devt))  
  125.         devtmpfs_delete_node(dev);  
  126.     if (MAJOR(dev->devt))  
  127.         device_remove_sys_dev_entry(dev);  
  128.  devtattrError:  
  129.     if (MAJOR(dev->devt))  
  130.         device_remove_file(dev, &devt_attr);  
  131.  ueventattrError:  
  132.     device_remove_file(dev, &uevent_attr);  
  133.  attrError:  
  134.     kobject_uevent(&dev->kobj, KOBJ_REMOVE);  
  135.     kobject_del(&dev->kobj);  
  136.  Error:  
  137.     cleanup_device_parent(dev);  
  138.     if (parent)  
  139.         put_device(parent);  
  140. name_error:  
  141.     kfree(dev->p);  
  142.     dev->p = NULL;  
  143.     goto done;  
  144. }  
  145.   
  146. <pre name="code" class="cpp">int bus_add_device(struct device *dev)  
  147. {  
  148.     struct bus_type *bus = bus_get(dev->bus);  
  149.     int error = 0;  
  150.   
  151.     if (bus) {  
  152.         pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));  
  153.         error = device_add_attrs(bus, dev);  
  154.         if (error)  
  155.             goto out_put;  
  156.         error = sysfs_create_link(&bus->p->devices_kset->kobj,  
  157.                         &dev->kobj, dev_name(dev));  
  158.         if (error)  
  159.             goto out_id;  
  160.         error = sysfs_create_link(&dev->kobj,  
  161.                 &dev->bus->p->subsys.kobj, "subsystem");  
  162.         if (error)  
  163.             goto out_subsys;  
  164.         klist_add_tail(&dev->p->knode_bus, &bus->p->klist_devices);
  165.     }  
  166.     return 0;  
  167.   
  168. out_subsys:  
  169.     sysfs_remove_link(&bus->p->devices_kset->kobj, dev_name(dev));  
  170. out_id:  
  171.     device_remove_attrs(bus, dev);  
  172. out_put:  
  173.     bus_put(dev->bus);  
  174.     return error;  
  175. }  

 
 
 
 

        這樣,i2c-client device掛載到了i2c bus上。當i2c 設備驅動添加到系統時,就出現了在前幾部分的東西了。從bus上取下i2c-client與i2c-driver進行匹配。

            雖然i2-client怎麼掛載到i2c-bus上知道了(由qup_i2c_probe調用of_i2c_register_device掛載)。新的問題又來了:qup_i2c_probe參數是platform_device,i2c-bus又是如何建立platform_device的。

(kernel/include/linux/init.h)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define arch_initcall(fn)       <span style="color:#FF0000;">__define_initcall("3",fn,3)</span>  
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define __define_initcall(level,fn,id) \  
  2.     static initcall_t __initcall_##fn##id __used \  
  3.     __attribute__((__section__(".initcall" level ".init"))) = fn  

        將i2c-bus的driver init函數放到.initcall3.init 代碼段中。

        之所以,i2c-bus的driver和i2c 設備的驅動init函數使用的不同的函數放到.initcall代碼段,主要原因是後面調用.initcall中的函數執行順序是按.initcall段的函數順序進行的(按照initcall的level從0到7依次存放的)。

(kernel/include/linux/vmlinux.lds.h)

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #define INIT_CALLS_LEVEL(level)                        \  
  2.         VMLINUX_SYMBOL(__initcall##level##_start) = .;        \  
  3.         *(.initcall##level##.init)                \  
  4.         *(.initcall##level##s.init)      
  5.   
  6. #define INIT_CALLS                          \  
  7.         VMLINUX_SYMBOL(__initcall_start) = .;           \  
  8.         *(.initcallearly.init)                  \  
  9.         INIT_CALLS_LEVEL(0)                 \  
  10.         INIT_CALLS_LEVEL(1)                 \  
  11.         INIT_CALLS_LEVEL(2)                 \  
  12.         INIT_CALLS_LEVEL(3)                 \  
  13.         INIT_CALLS_LEVEL(4)                 \  
  14.         INIT_CALLS_LEVEL(5)                 \  
  15.         INIT_CALLS_LEVEL(rootfs)                \  
  16.         INIT_CALLS_LEVEL(6)                 \  
  17.         INIT_CALLS_LEVEL(7)                 \  
  18.         VMLINUX_SYMBOL(__initcall_end) = .;  

       那麼現在根據前面部分內容,知道driver_register將platform bus上的platform device取下來,與driver進行匹配。到此終於理順了從dts節點信息到驅動註冊的完整過程。


四、module_init()中的驅動初始化後函數何時被調用

(kernel/include/linux/init.h)

#define module_init(x)        __initcall(x);

#define __initcall(fn)                               device_initcall(fn)
#define device_initcall(fn)                __define_initcall("6",fn,6)
#define __define_initcall(level,fn,id) /
        static initcall_t __initcall_##fn##id __used /
        __attribute__((__section__(".initcall" level ".init"))) = fn

initcall_t(typedef int (*initcall_t)(void))


這樣就將module_init傳遞的fn函數放到了制定的.initcall6.init 代碼段中。

在linux  /init/main.c 中,
static void __init do_initcalls(void)
{
  initcall_t *call;

  call = &__initcall_start;
  do {
   (*call)();
   call++;
  } while (call < &__initcall_end);

  /* Make sure there is no pending stuff from the initcall sequence */
  flush_scheduled_tasks();
}

通過do_initcalls就可以吧__initcall section段的函數調用起來。


參考文章:  http://blog.csdn.net/MarsWG/archive/2004/11/05/168552.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值