在系统开机时,首先装载的是I2C总线驱动。一个总线驱动用于支持一条特定的I2C总线的读写。这部分主要定义i2c_adapter和i2c_algorithm数据结构,前者用来描述具体的 i2c 总线适配器,后者则描述i2c 总线的通信方法.
设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。
Client很有可能是一个cdev在probe中实现
init->i2c_add_driver->i2c_register_driver
在i2c_register_driver中
driver->driver.owner = owner;
driver->driver.bus = &i2c_bus_type;
res = driver_register(&driver->driver);
i2c_for_each_dev(driver, __process_new_driver);//对每一个adapter执行__process_new_driver函数,以前一直以为实在这里将driver和algorithm联系起来
后来发现是在driver_register中,最后调用到i2c-core.c中的i2c_device_probe中client回传联系起来的,这里回传的client即是adapter
并在这里创建相应的kobject,并触发相应的kevent
仔细分析一下driver_register函数
在注册的时候注册了一个i2c_driver的结构体
例如adv7170.c
static struct i2c_driver adv7170_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "adv7170",
},
.probe = adv7170_probe,
.remove = adv7170_remove,
.id_table = adv7170_id,
};
static __init int init_adv7170(void)
{
return i2c_add_driver(&adv7170_driver);
}
在driver_register中首先调用other = driver_find(drv->name, drv->bus);
看dirver是否已经在bus中,没有则调用bus_add_driver
中调用了error = driver_attach(drv);因为i2c_bus中的driver_autoprobe不为0
int driver_attach(struct device_driver *drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}
中对每一个bus上的device去匹配driver,并调用__driver_attach函数
这里可以看出adataper在bus中充当的是device角色,master在bus中充当的是driver角色
等一下看看adapter的注册就可以得到证实
if (!dev->driver)
driver_probe_device(drv, dev);//此时的adapter即device的driver还为空
__driver_attach->driver_probe_device->really_probe->ret = dev->bus->probe(dev);
这里调用到了i2c-core里边bus的probe
static int i2c_device_probe(struct device *dev)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
int status;
if (!client)
return 0;
driver = to_i2c_driver(dev->driver);
if (!driver->probe || !driver->id_table)
return -ENODEV;
client->driver = driver;
if (!device_can_wakeup(&client->dev))
device_init_wakeup(&client->dev,
client->flags & I2C_CLIENT_WAKE);
dev_dbg(dev, "probe\n");
status = driver->probe(client, i2c_match_id(driver->id_table, client));//这里回调给driver并把adapter作为client回传
if (status) {
client->driver = NULL;
i2c_set_clientdata(client, NULL);
}
return status;
}
其中i2c_register_adapter中调用了
int device_register(struct device *dev)
{
device_initialize(dev);
return device_add(dev);
}
创建了sys文件并把device放到bus private的device链表的结尾部分
一般是在arch目录设置i2c的设备信息,包括相应的地址和中断
是一个平台设备
然后在i2c/buss/中添加相应的adapter,中是相应的驱动
中用软件设置了相应的传输操作,初始化操作
然后driver中则通过core对apdataer的传输操作进行调用
其中adapter中重要的实现了algorithm结构体,定义了
static const struct i2c_algorithm omap_i2c_algo = {
.master_xfer = omap_i2c_xfer,
.functionality = omap_i2c_func,
};
I2C设备至此清晰了~~
阅读(410) | 评论(0) | 转发(0) |