Linux Kernel 设备驱动之I2C之host描述

    xiaoxiao2021-03-25  108

    对于I2C传输来说,其由三部分组成,一个是I2C控制端,二是控制端对外提供的总线,三是总线上的设备。

    所以,存在三个方面的抽象,控制端一般叫host或者adapter等,其结构如下: /*  * i2c_adapter is the structure used to identify a physical i2c bus along  * with the access algorithms necessary to access it.  */ struct i2c_adapter {  struct module *owner;  unsigned int class;    /* classes to allow probing for */  const struct i2c_algorithm *algo; /* the algorithm to access the bus */  void *algo_data;这两个是I2C传输数据的关键。

     /* data fields that are valid for all devices */  const struct i2c_lock_operations *lock_ops;  struct rt_mutex bus_lock;  struct rt_mutex mux_lock;

     int timeout;   /* in jiffies */  int retries;  struct device dev;  /* the adapter device */

     int nr;  char name[48];  struct completion dev_released;

     struct mutex userspace_clients_lock;  struct list_head userspace_clients;

     struct i2c_bus_recovery_info *bus_recovery_info;  const struct i2c_adapter_quirks *quirks; };

    对于adapter来说,要么静态定义,要么动态分配,在简单初始化后,调用函数

    i2c_add_adapter()或者函数i2c_add_numbered_adapter()把adapter添加到

    i2c驱动的框架层。

    这两个函数都是调用i2c_register_adapter()完成adapter的注册。

     

    static int i2c_register_adapter(struct i2c_adapter *adap) {  int res = -EINVAL;

     /* Can't register until after driver model init */  if (WARN_ON(!is_registered)) {   res = -EAGAIN;   goto out_list;  }

     /* Sanity checks */  if (WARN(!adap->name[0], "i2c adapter has no name"))   goto out_list;

     if (!adap->algo) {   pr_err("adapter '%s': no algo supplied!\n", adap->name);   goto out_list;  }

     if (!adap->lock_ops)   adap->lock_ops = &i2c_adapter_lock_ops;

     rt_mutex_init(&adap->bus_lock);  rt_mutex_init(&adap->mux_lock);  mutex_init(&adap->userspace_clients_lock);  INIT_LIST_HEAD(&adap->userspace_clients);

     /* Set default timeout to 1 second if not already set */  if (adap->timeout == 0)   adap->timeout = HZ;

     dev_set_name(&adap->dev, "i2c-%d", adap->nr);  adap->dev.bus = &i2c_bus_type;设备模型中,设备总线类型  adap->dev.type = &i2c_adapter_type;设备类型  res = device_register(&adap->dev);设备模型中设备注册  if (res) {   pr_err("adapter '%s': can't register device (%d)\n", adap->name, res);   goto out_list;  }

     dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);

    //PM支持回调

     pm_runtime_no_callbacks(&adap->dev);  pm_suspend_ignore_children(&adap->dev, true);  pm_runtime_enable(&adap->dev);

    #ifdef CONFIG_I2C_COMPAT  res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev,            adap->dev.parent);  if (res)   dev_warn(&adap->dev,     "Failed to create compatibility class link\n"); #endif

     i2c_init_recovery(adap);

     /* create pre-declared device nodes */  of_i2c_register_devices(adap);  i2c_acpi_register_devices(adap);  i2c_acpi_install_space_handler(adap);

     if (adap->nr < __i2c_first_dynamic_bus_num)   i2c_scan_static_board_info(adap);

     /* Notify drivers */  mutex_lock(&core_lock);  bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);  mutex_unlock(&core_lock);这一步是对总线上设备探测,这里的回调函数是__process_new_adapter

     return 0;

    out_list:  mutex_lock(&core_lock);  idr_remove(&i2c_adapter_idr, adap->nr);  mutex_unlock(&core_lock);  return res; }

    在添加总线时,我们看看是否有设备在总线上,如果有则调用设备的驱动,对设备初始化。这里并不一定对设备初始化,

    也可以提前做些事情。 static int __process_new_adapter(struct device_driver *d, void *data) {  return i2c_do_add_adapter(to_i2c_driver(d), data); }

    static int i2c_do_add_adapter(struct i2c_driver *driver,设备驱动          struct i2c_adapter *adap)host对象 {  /* Detect supported devices on that bus, and instantiate them */  i2c_detect(adap, driver);

     /* Let legacy drivers scan this bus for matching devices */  if (driver->attach_adapter) {   dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",     driver->driver.name);   dev_warn(&adap->dev,     "Please use another way to instantiate your i2c_client\n");   /* We ignore the return code; if it fails, too bad */   driver->attach_adapter(adap);  }  return 0; }

     

     

     

     
    转载请注明原文地址: https://ju.6miu.com/read-10974.html

    最新回复(0)