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

本文介绍I2C总线适配器的结构和注册过程,包括适配器关键字段的作用、静态或动态创建适配器的方法,以及通过i2c_register_adapter函数完成适配器注册的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
 

对于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; }

 

 

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值