linux i2c子系统代码分析3 ---操作函数i2c_add_adapter i2c_add_numbered_adapter介绍

二.i2c子系统操作函数,i2c-core.c

1.

kernel/driver/linux/i2c/i2c-core.c

/**
 * i2c_add_adapter - declare i2c adapter, use dynamic bus number
 * @adapter: the adapter to add
 * Context: can sleep
 *
 * This routine is used to declare an I2C adapter when its bus number
 * doesn't matter.  Examples: for I2C adapters dynamically added by
 * USB links or PCI plugin cards.
 *
 * When this returns zero, a new bus number was allocated and stored
 * in adap->nr, and the specified adapter became available for clients.
 * Otherwise, a negative errno value is returned.
 */
int i2c_add_adapter(struct i2c_adapter *adapter)
{
int id, res = 0;


retry:
if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0)
return -ENOMEM;


mutex_lock(&core_lock);
/* "above" here means "above or equal to", sigh */
res = idr_get_new_above(&i2c_adapter_idr, adapter,
__i2c_first_dynamic_bus_num, &id);
mutex_unlock(&core_lock);


if (res < 0) {
if (res == -EAGAIN)
goto retry;
return res;
}


adapter->nr = id;
return i2c_register_adapter(adapter);
}

 i2c_add_adapter  注册i2c适配器到系统,主要功能是首先通过ird机制给i2c适配器分配指针,然后注册该i2c适配器

idr_pre_get           预分配i2c适配器指针

idr_get_new_above  给i2c适配器分配指针并和id关联

i2c_register_adapter  i2c注册适配器


kernel/driver/linux/i2c/i2c-core.c

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


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


/* Sanity checks */
if (unlikely(adap->name[0] == '\0')) {
pr_err("i2c-core: Attempt to register an adapter with "
      "no name!\n");
return -EINVAL;
}
if (unlikely(!adap->algo)) {
pr_err("i2c-core: Attempt to register adapter '%s' with "
      "no algo!\n", adap->name);
return -EINVAL;
}


rt_mutex_init(&adap->bus_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)
goto out_list;


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


#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


/* create pre-declared device nodes */
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);


return 0;


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


 i2c_register_adapter  注册适配器  
unlikely(WARN_ON(!i2c_bus_type.p   检查总线是否初始化完成

unlikely(adap->name[0] == '\0')             检查适配器名称是否为空

unlikely(!adap->algo)                             检查适配器算法是否为空

rt_mutex_init(&adap->bus_lock);                         初始化实时互斥锁
mutex_init(&adap->userspace_clients_lock);       初始化用户设备锁
INIT_LIST_HEAD(&adap->userspace_clients);    初始化i2c设备链表

dev_set_name(&adap->dev, "i2c-%d", adap->nr);  设置适配器设备驱动模型设备名称

adap->dev.bus = &i2c_bus_type;                            初始化适配器设备驱动模型设备的总线类型
adap->dev.type = &i2c_adapter_type;                    初始化适配器设备驱动模型设备类型

device_register(&adap->dev);                                注册适配器设备到设备驱动模型


i2c_scan_static_board_info(adap);                        扫描静态声明的i2c设备信息,该方法也对应i2c设备静态声明注册

kernel/driver/linux/i2c/i2c-core.c

static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
{
struct i2c_devinfo*devinfo;


down_read(&__i2c_board_lock);
list_for_each_entry(devinfo, &__i2c_board_list, list) {
if (devinfo->busnum == adapter->nr
&& !i2c_new_device(adapter,
&devinfo->board_info))
dev_err(&

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
I2C 是一种串行通信总线,常用于连接微控制器、传感器、存储器等设备。在 Linux 内核中,I2C 子系统i2c-core 和 i2c-algo-* 组成,其中 i2c-core 提供了 I2C 总线驱动的核心功能,而 i2c-algo-* 提供了 I2C 总线驱动的具体实现。 下面是 Linux 内核 4.19 版本中 I2C 总线的初始化流程: 1. 启动内核后,i2c-core 驱动被注册到系统中,并创建 i2c_bus_type 总线类型对象。 2. i2c-algo-* 驱动被注册到系统中,这些驱动封装了不同的 I2C 总线控制器,如 i2c-algo-bit、i2c-algo-pca 等。 3. 在设备树中,定义了 I2C 总线控制器所使用的硬件资源,如 GPIO、时钟等。 4. 当系统探测到 I2C 总线控制器时,会调用 i2c_add_numbered_adapter() 函数创建 i2c_adapter 对象,并将其挂载到 i2c_bus_type 总线类型对象上。 5. 然后,内核会扫描设备树,找到已经定义的 I2C 设备节点,如 i2c-device1、i2c-device2 等。 6. 对于每个 I2C 设备节点,内核会解析其中的属性,如设备地址、总线编号等信息,并调用 i2c_new_device() 函数创建 i2c_client 对象,并将其挂载到 i2c_adapter 对象上。 7. I2C 客户端驱动可以通过 i2c_new_device() 函数获取 i2c_client 对象,然后通过 i2c_transfer() 函数进行 I2C 数据传输。 总之,I2C 设备的挂载与设备树息息相关。内核通过解析设备树中的节点信息,创建 i2c_client 对象,并将其挂载到 i2c_adapter 对象上,从而实现 I2C 总线的初始化和设备的挂载。 需要注意的是,不同的 I2C 设备可能需要使用不同的 I2C 总线控制器,因此在设备树中需要明确指定所使用的控制器类型和硬件资源。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值