linux powerpc i2c驱动 之 i2c设备…

Linuxi2c驱动的加载过程,分为i2c设备层、i2c adapter层与i2c核心层

i2c设备驱动层也就是我们为特定i2c设备编写的驱动,下面是我自己理解的i2c驱动的注册过程

在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver完成所有注册操作

 

 

[plain] view plaincopyprint?

  1. static inline int i2c_add_driver(struct i2c_driver *driver)  

  2.  

  3. return i2c_register_driver(THIS_MODULE, driver);  

  4.  

i2c_register_driver会调用driver_register() 来将设备驱动添加到总线的设备驱动链表中

[plain] view plaincopyprint?

  1. int i2c_register_driver(struct module *owner, struct i2c_driver *driver)  

  2.  

  3. int res;  

  4.   

  5. if (unlikely(WARN_ON(!i2c_bus_type.p)))  

  6. return -EAGAIN;  

  7. driver->driver.owner owner;  

  8. driver->driver.bus &i2c_bus_type;  

  9.   

  10. res <strong>driver_register</strong>(&driver->driver);  

  11. if (res)  

  12. return res;  

  13. pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);  

  14. INIT_LIST_HEAD(&driver->clients);  

  15.   

  16. mutex_lock(&core_lock);  

  17. bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);  

  18. mutex_unlock(&core_lock);  

  19. return 0;  

  20.  



driver_register,通过driver_find来判断驱动是否已经注册,然后会调用

bus_add_drive

将设备驱动添加到总线上

[plain] view plaincopyprint?

  1. int driver_register(struct device_driver *drv)  

  2.  

  3. int ret;  

  4. struct device_driver *other;  

  5. BUG_ON(!drv->bus->p);  

  6. if ((drv->bus->probe && drv->probe) ||  

  7.     (drv->bus->remove && drv->remove) ||  

  8.     (drv->bus->shutdown && drv->shutdown))  

  9. printk(KERN_WARNING "Driver '%s' needs updating please use  

  10. "bus_type methods\n", drv->name);  

  11. other driver_find(drv->name, drv->bus);  

  12. if (other)  

  13. put_driver(other);  

  14. printk(KERN_ERR "Error: Driver '%s' is already registered,  

  15. "aborting...\n", drv->name);  

  16. return -EBUSY;  

  17.  

  18. ret <strong>bus_add_driver</strong>(drv);  

  19. if (ret)  

  20. return ret;  

  21. ret driver_add_groups(drv, drv->groups);  

  22. if (ret)  

  23. bus_remove_driver(drv);  

  24. return ret;  

  25.  



bus_add_driver中初始化priv->klist_devices的值,并将priv赋值给drv->p

通过调用klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers)将驱动信息保存到总线结构中,在此之前将调用driver_attach()

[plain] view plaincopyprint?

  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\n", bus->name, drv->name);  

  10. priv kzalloc(sizeof(*priv), GFP_KERNEL);  

  11. if (!priv)  

  12. error -ENOMEM;  

  13. goto out_put_bus;  

  14.  

  15. <strong>klist_init</strong>(&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 <strong>driver_attach</strong>(drv);  

  25. if (error)  

  26. goto out_unregister;  

  27.  

  28. <strong>klist_add_tail</strong>(&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\n",  

  33. __func__, drv->name);  

  34.  

  35. error driver_add_attrs(bus, drv);  

  36. if (error)  

  37.   

  38. printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",  

  39. __func__, drv->name);  

  40.  

  41. if (!drv->suppress_bind_attrs)  

  42. error add_bind_files(drv);  

  43. if (error)  

  44.   

  45. printk(KERN_ERR "%s: add_bind_files(%s) failed\n",  

  46. __func__, drv->name);  

  47.  

  48.  

  49. kobject_uevent(&priv->kobj, KOBJ_ADD);  

  50. return 0;  

  51. out_unregister:  

  52. kfree(drv->p);  

  53. drv->p NULL;  

  54. kobject_put(&priv->kobj);  

  55. out_put_bus:  

  56. bus_put(bus);  

  57. return error;  

  58.  



driver_attach中,通过调用bus_for_each_dev,遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()

[plain] view plaincopyprint?

  1. int driver_attach(struct device_driver *drv)  

  2.  

  3. return bus_for_each_dev(drv->bus, NULL, drv, <strong>__driver_attach</strong>);  

  4.  


__driver_attach里会调用driver_match_device()来判断devdrivid是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,

id相同时,将会调用driver_probe_device()

[plain] view plaincopyprint?

  1. static int __driver_attach(struct device *dev, void *data)  

  2.  

  3. struct device_driver *drv data;  

  4.   

  5. if (!<strong>driver_match_device</strong>(drv, dev))  

  6. return 0;  

  7. if (dev->parent)   

  8. down(&dev->parent->sem);  

  9. down(&dev->sem);  

  10. if (!dev->driver)  

  11. <strong>driver_probe_device</strong>(drv, dev);  

  12. up(&dev->sem);  

  13. if (dev->parent)  

  14. up(&dev->parent->sem);  

  15. return 0;  

  16.  



在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,若没注册则返回;若已经注册,则调用really_probe

[plain] view plaincopyprint?

  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\n",  

  7.  drv->bus->name, __func__, dev_name(dev), drv->name);  

  8. pm_runtime_get_noresume(dev);  

  9. pm_runtime_barrier(dev);  

  10. ret <strong>really_probe</strong>(dev, drv);  

  11. pm_runtime_put_sync(dev);  

  12. return ret;  

  13.  



在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,

此时将会调用i2c总线的probe函数:i2c_device_probe

[plain] view plaincopyprint?

  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\n",  

  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\n",  

  11. __func__, dev_name(dev));  

  12. goto probe_failed;  

  13.  

  14. if (dev->bus->probe)   

  15.  

  16. //此处调用i2c总线的probe函数  

  17. ret dev->bus->probe(dev);  

  18. if (ret)  

  19. goto probe_failed;  

  20.   

  21. else if (drv->probe)   

  22.  

  23. ret drv->probe(dev);  

  24. if (ret)  

  25. goto probe_failed;  

  26.  

  27. driver_bound(dev);  

  28. ret 1;  

  29. pr_debug("bus: '%s': %s: bound device %s to driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name);  

  30. goto done;  

  31. probe_failed:  

  32. devres_release_all(dev);  

  33. driver_sysfs_remove(dev);  

  34. dev->driver NULL;  

  35. if (ret != -ENODEV && ret != -ENXIO)   

  36.  

  37.   

  38. printk(KERN_WARNING       "%s: probe of %s failed with error %d\n",       drv->name, dev_name(dev), ret);  

  39.  

  40.   

  41. ret 0;  

  42. done:  

  43. atomic_dec(&probe_count);  

  44. wake_up(&probe_waitqueue);  

  45. return ret;  

  46.  



i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体i2c_driver,即

[plain] view plaincopyprint?

  1. static struct i2c_driver XXX_driver  

  2. .driver  

  3. .name "XXXX_name",  

  4. .owner THIS_MODULE,  

  5. },  

  6. .probe XXX_probe,  

  7. .remove XXX_remove,  

  8. .id_table XXX_id,  

  9. };  



这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe()

[plain] view plaincopyprint?

  1. static int i2c_device_probe(struct device *dev)  

  2.  

  3. struct i2c_client *client i2c_verify_client(dev);  

  4. struct i2c_driver *driver;  

  5. int status;  

  6. if (!client)  

  7. return 0;  

  8. driver to_i2c_driver(dev->driver);  

  9. if (!driver->probe || !driver->id_table)  

  10. return -ENODEV;  

  11. client->driver driver;  

  12. if (!device_can_wakeup(&client->dev))  

  13. device_init_wakeup(&client->dev,  

  14. client->flags I2C_CLIENT_WAKE);  

  15. dev_dbg(dev, "probe\n");  

  16. status <strong>driver->probe</strong>(client, i2c_match_id(driver->id_table, client));//执行我们写的probe函数  

  17. if (status)  

  18. client->driver NULL;  

  19. return status;  

  20.  


<script type="text/javascript" id="wumiiRelatedItems"> </script>
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值