您的位置:首页 > 运维架构 > Linux

Linux kernel I2C设备总结

2013-12-19 20:49 183 查看
在系统开机时,首先装载的是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设备至此清晰了~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: