Linux PowerPC I2C驱动之 I2C设备层的注册过程


Linux PowerPC I2C驱动之 I2C设备层的注册过程
2011年10月26日
  Linux下i2c驱动的加载过程,分为i2c设备层、i2c adapter层与i2c核心层
  i2c设备驱动层也就是我们为特定i2c设备编写的驱动,下面是我自己理解的i2c驱动的注册过程
  在我们写的i2c设备驱动中,我们会调用i2c_add_driver()开始i2c设备驱动的注册,该函数调用i2c_register_driver完成所有注册操作
  static inline int i2c_add_driver(struct i2c_driver *driver)
  {
  return i2c_register_driver(THIS_MODULE, driver);
  }
  i2c_register_driver会调用driver_register() 来将设备驱动添加到总线的设备驱动链表中:
  int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
  {
  int res;
  /* Can't register until after driver model init */
  if (unlikely(WARN_ON(!i2c_bus_type.p)))
  return -EAGAIN;
  driver->driver.owner = owner;
  driver->driver.bus = &i2c_bus_type;
  /* When registration returns, the driver core
  * will have called probe() for all matching-but-unbound devices.
  */
  res = driver_register(&driver->driver);
  if (res)
  return res;
  pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
  INIT_LIST_HEAD(&driver->clients);
  /* Walk the adapters that are already present */
  mutex_lock(&core_lock);
  bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
  mutex_unlock(&core_lock);
  return 0;
  }
  在driver_register中,通过driver_find来判断驱动是否已经注册,然后会调用
  bus_add_drive
  将设备驱动添加到总线上
  int driver_register(struct device_driver *drv)
  {
  int ret;
  struct device_driver *other;
  BUG_ON(!drv->bus->p);
  if ((drv->bus->probe && drv->probe) ||
  (drv->bus->remove && drv->remove) ||
  (drv->bus->shutdown && drv->shutdown))
  printk(KERN_WARNING "Driver '%s' needs updating - please use "
  "bus_type methods\n", drv->name);
  other = driver_find(drv->name, drv->bus);
  if (other) {
  put_driver(other);
  printk(KERN_ERR "Error: Driver '%s' is already registered, "
  "aborting...\n", drv->name);
  return -EBUSY;
  }
  ret = bus_add_driver(drv);
  if (ret)
  return ret;
  ret = driver_add_groups(drv, drv->groups);
  if (ret)
  bus_remove_driver(drv);
  return ret;
  }
  在bus_add_driver中初始化priv->klist_devices的值,并将priv赋值给drv->p
  通过调用klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers)将驱动信息保存到总线结构中,在此之前将调用driver_attach()
  int bus_add_driver(struct device_driver *drv) { struct bus_type *bus; struct driver_private *priv; int error = 0; bus = bus_get(drv->bus); if (!bus) return -EINVAL; pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name); priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { error = -ENOMEM; goto out_put_bus; } klist_init(&priv->klist_devices, NULL, NULL); priv->driver = drv; drv->p = priv; priv->kobj.kset = bus->p->drivers_kset; error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,      "%s", drv->name); if (error) goto out_unregister; if (drv->bus->p->drivers_autoprobe) { error = driver_attach(drv); if (error) goto out_unregister; } klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers); module_add_driver(drv->owner, drv); error = driver_create_file(drv, &driver_attr_uevent); if (error) { printk(KERN_ERR "%s: uevent attr (%s) failed\n", __func__, drv->name); } error = driver_add_attrs(bus, drv); if (error) { /* How the hell do we get out of this pickle? Give up */ printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n", __func__, drv->name); } if (!drv->suppress_bind_attrs) { error = add_bind_files(drv); if (error) { /* Ditto */ printk(KERN_ERR "%s: add_bind_files(%s) failed\n", __func__, drv->name); } } kobject_uevent(&priv->kobj, KOBJ_ADD); return 0; out_unregister: kfree(drv->p); drv->p = NULL; kobject_put(&priv->kobj); out_put_bus: bus_put(bus); return error; } 在driver_attach中,通过调用bus_for_each_dev,遍历在总线上挂载的所有设备,并对每个设备(dev)调用__driver_attach()
  int driver_attach(struct device_driver *drv)
  {
  return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
  }
  在__driver_attach里会调用driver_match_device()来判断dev与driv的id是否相同,在i2c驱动里就会调用i2c_bus_type->match程序进行判断,
  当id相同时,将会调用driver_probe_device()
  static int __driver_attach(struct device *dev, void *data)
  {
  struct device_driver *drv = data;
  /*
  * Lock device and try to bind to it. We drop the error
  * here and always return 0, because we need to keep trying
  * to bind to devices and some drivers will return an error
  * simply if it didn't support the device.
  *
  * driver_probe_device() will spit a warning if there
  * is an error.
  */
  if (!driver_match_device(drv, dev))
  return 0;
  if (dev->parent) /* Needed for USB */
  down(&dev->parent->sem);
  down(&dev->sem);
  if (!dev->driver)
  driver_probe_device(drv, dev);
  up(&dev->sem);
  if (dev->parent)
  up(&dev->parent->sem);
  return 0;
  }
  在driver_probe_device(),首先会调用device_is_registered()判断dev是否注册,若没注册则返回;若已经注册,则调用really_probe
  int driver_probe_device(struct device_driver *drv, struct device *dev)
  {
  int ret = 0;
  if (!device_is_registered(dev))
  return -ENODEV;
  pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
  drv->bus->name, __func__, dev_name(dev), drv->name);
  pm_runtime_get_noresume(dev);
  pm_runtime_barrier(dev);
  ret = really_probe(dev, drv);
  pm_runtime_put_sync(dev);
  return ret;
  }
  在really_probe()里,首先将drv赋值给dev->driver,然后会调用总线的probe函数,在i2c驱动里,
  此时将会调用i2c总线的probe函数:i2c_device_probe
  static int really_probe(struct device *dev, struct device_driver *drv)
  {
  int ret = 0;
  atomic_inc(&probe_count);
  pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
  drv->bus->name, __func__, drv->name, dev_name(dev));
  WARN_ON(!list_empty(&dev->devres_head));
  dev->driver = drv;
  if (driver_sysfs_add(dev)) {
  printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
  __func__, dev_name(dev));
  goto probe_failed;
  } if (dev->bus->probe) {//此处调用i2c总线的probe函数
  ret = dev->bus->probe(dev);
  if (ret)
  goto probe_failed;
  } else if (drv->probe) {
  ret = drv->probe(dev);
  if (ret)
  goto probe_failed;
  }
  driver_bound(dev);
  ret = 1;
  pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
  drv->bus->name, __func__, dev_name(dev), drv->name);
  goto done;
  probe_failed:
  devres_release_all(dev);
  driver_sysfs_remove(dev);
  dev->driver = NULL;
  if (ret != -ENODEV && ret != -ENXIO) {
  /* driver matched but the probe failed */
  printk(KERN_WARNING
  "%s: probe of %s failed with error %d\n",
  drv->name, dev_name(dev), ret);
  }
  /*
  * Ignore errors returned by ->probe so that the next driver can try
  * its luck.
  */
  ret = 0;
  done:
  atomic_dec(&probe_count);
  wake_up(&probe_waitqueue);
  return ret;
  }
  在i2c_device_probe()里,会根据to_i2c_driver(dev->driver)获取i2c驱动,也就是我们编写的具体的i2c设备驱动的结构体i2c_driver,即
  static struct i2c_driver XXX_driver = {
  .driver = {
  .name = "XXXX_name",
  .owner = THIS_MODULE,
  },
  .probe = XXX_probe,
  .remove = XXX_remove,
  .id_table = XXX_id,
  };
  这样就调用了我们驱动的probe()了,这就是我们在驱动里调用i2c_add_driver(),通过driver_register()的一系列调用,最后执行我们所写的probe()
  static int i2c_device_probe(struct device *dev)
  {
  struct i2c_client *client = i2c_verify_client(dev);
  struct i2c_driver *driver;
  int status;
  if (!client)
  return 0;
  driver = to_i2c_driver(dev->driver);
  if (!driver->probe || !driver->id_table)
  return -ENODEV;
  client->driver = driver;
  if (!device_can_wakeup(&client->dev))
  device_init_wakeup(&client->dev,
  client->flags & I2C_CLIENT_WAKE);
  dev_dbg(dev, "probe\n"); status = driver->probe(client, i2c_match_id(driver->id_table, client));//执行我们写的probe函数
  if (status)
  client->driver = NULL;
  return status;
  }
  本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/41104p3.htm
  本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/41104p2.htm
  本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2011-08/41104.htm

猜你喜欢

转载自sit379vt.iteye.com/blog/1359514