i2c子系统之adapter device和client device注册——i2c_add_number_adapter()

如前文所述,在probe函数会调用函数i2c_add_number_adapter(),通过此函数来实现adapter device和client device的注册

i2c_add_number_adapter()函数如下:

int i2c_add_numbered_adapter(struct i2c_adapter *adap)
{
	int	id;
	int	status;

	if (adap->nr & ~MAX_ID_MASK)
		return -EINVAL;

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;
	 * we need the "equal to" result to force the result
	 */
	status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id);
	if (status == 0 && id != adap->nr) {
		status = -EBUSY;
		idr_remove(&i2c_adapter_idr, id);
	}
	mutex_unlock(&core_lock);
	if (status == -EAGAIN)
		goto retry;

	if (status == 0)
		status = i2c_register_adapter(adap);
	return status;
}
函数前面部分应该是用来提高搜索效率相关,此处省略分析。直接分析

i2c_register_adapter()函数,如下:

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

	。。。 。。。
	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);
        。。。 。。。

	/* create pre-declared device nodes */
	if (adap->nr < __i2c_first_dynamic_bus_num)
		i2c_scan_static_board_info(adap);

	/* Notify drivers */
	printk("bus_search\n");
	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;
}

函数首先通过:

        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);
 

语句,将名为i2c-0的adapter设备注册到i2c_bus_type型的i2c总线上上,其中通过

adap->dev.type = &i2c_adapter_type;

指定了本次注册的设备类型为i2c_adapter_type(因为还有client设备同时需要注册到这条i2c总线上)

最后同构device_register()将adapter注册到i2c总线上。

接着然后判断if条件是否成立(此处成立),__i2c_first_dynamic_bus_num的判断分析见另一篇博文,

条件成立则执行函数i2c_scan_static_board_info(adap),如下:

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(&adapter->dev,
				"Can't create device at 0x%02x\n",
				devinfo->board_info.addr);
	}
	up_read(&__i2c_board_lock);
}
在此函数中完成一个重要的工作。首先从__i2c_board_list链表上获取一个devinfo信息结构体,此结

构体由前面的i2c_register_board_info()添加到i2c设备链表上的。结构体中包含板上的i2c at24c02设

备相关信息。然后在此函数中调用i2c_new_device()以从链表上获取的devinfo作为参数,

i2c_new_device函数根据devinfo中的设备相关信息来创建client,内核中使用client来代表at24c02设备。

struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
{
	。。。 。。。

        client->dev.parent = &client->adapter->dev;
	client->dev.bus = &i2c_bus_type;
	client->dev.type = &i2c_client_type;
       
        。。。 。。。
        status = device_register(&client->dev);

}

可见client和adapter同样都被注册到i2c_bus_type总线上了,并且还通过

client->dev.type = &i2c_client_type;

指定了设备类型i2c_client_type。最后通过device_register()函数将此client注册到i2c总线上。

所以此i2c总线同时包含了adapter和client,即i2c主机(s3c2440的i2c控制器)、i2c从设备at24c02。

到这一步内核实现了adapter device和client device的注册,接着要通过函数bus_for_each_drv()

来扫描i2c总线,检测刚注册到i2c总线的adapter是否有对应的驱动。

	bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter);

不过目前肯定失败,因为到目前为止还未注册adapter driver。

所以系统接着执行后续步骤。

总结

至此,执行完i2c_add_numbered_adapter函数后,内核的i2c总线上已有adapter device和client device,

但是i2c总线此时还未有adapter driver和client driver。

i2c子系统将继续执行初始化函数,下步就是将i2c设备作为字符设备注册到系统,并且注册adapter的驱动,

以及在/dev目录下生成i2c设备文件等操作。实现这一步的函数是i2c_dev_init()。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值