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

来源:互联网 发布:理财软件排行 编辑:程序博客网 时间:2024/04/29 21:19

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

i2c_add_number_adapter()函数如下:

int i2c_add_numbered_adapter(struct i2c_adapter *adap){intid;intstatus;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()。

原创粉丝点击