如前文所述,在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()。