二.i2c子系统操作函数,i2c-core.c
上面介绍了i2c子系统重要的数据结构,下面介绍i2c子系统的适配器、算法、设备、设备驱动注册、注销以及重要的数据处理函数
在kernel/driver/linux/i2c/i2c-core.c文件中
static int __init i2c_init(void)
{
int retval;
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
#ifdef CONFIG_I2C_COMPAT
i2c_adapter_compat_class = class_compat_register("i2c-adapter");
if (!i2c_adapter_compat_class) {
retval = -ENOMEM;
goto bus_err;
}
#endif
retval = i2c_add_driver(&dummy_driver);
if (retval)
goto class_err;
return 0;
class_err:
#ifdef CONFIG_I2C_COMPAT
class_compat_unregister(i2c_adapter_compat_class);
bus_err:
#endif
bus_unregister(&i2c_bus_type);
return retval;
}
i2c_init 是i2c子系统的初始化函数,i2c总线注册,以及虚拟驱动的添加。
步骤:
1.bus_register(&i2c_bus_type); i2c总线注册,这样在/sys/bus/下就会增加i2c的节点
2.i2c_add_driver(&dummy_driver); 虚拟驱动的注册,用来创建注册i2c适配器
详细步骤:
1.1
bus_register(&i2c_bus_type);
kernel/driver/linux/i2c/i2c-core.c
struct bus_type i2c_bus_type = {
.name = "i2c",
.match = i2c_device_match,
.probe = i2c_device_probe,
.remove = i2c_device_remove,
.shutdown = i2c_device_shutdown,
.pm = &i2c_device_pm_ops,
};
上面是i2c总线的实例化
.match= i2c_device_match, i2c总线驱动和设备匹配函数
.probe= i2c_device_probe, i2c总线设备探测函数,最终会调用驱动中的probe函数
1.1.1
kernel/driver/linux/i2c/i2c-core.c
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client*client = i2c_verify_client(dev);
struct i2c_driver*driver;
if (!client)
return 0;
/* Attempt an OF style match */
if (of_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* match on an id table if there is one */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}
i2c_device_match 设备和驱动匹配函数。
struct i2c_client*client = i2c_verify_client(dev); 首先判断该设备是否是i2c设备
kernel/driver/linux/i2c/i2c-core.c
struct i2c_client *i2c_verify_client(struct device *dev)
{
return (dev->type == &i2c_client_type)
? to_i2c_client(dev)
: NULL;
}
kernel/driver/linux/i2c/i2c-core.c
static struct device_type i2c_client_type = {
.groups = i2c_dev_attr_groups,
.uevent = i2c_device_uevent,
.release = i2c_client_dev_release,
};
of_driver_match_device(dev, drv) 再看设备驱动模型中设备和驱动是否匹配
kernel/include/linux/of_device.h
/**
* of_driver_match_device - Tell if a driver's of_match_table matches a device.
* @drv: the device_driver structure to test
* @dev: the device structure to match against
*/
static inline int of_driver_match_device(struct device *dev,
const struct device_driver *drv)
{
return of_match_device(drv->of_match_table, dev) != NULL;
}
kernel/driver/of/device.c
/**
* of_match_device - Tell if a struct device matches an of_device_id list
* @ids: array of of device match structures to search in
* @dev: the of device structure to match against
*
* Used by a driver to check whether an platform_device present in the
* system is in its list of supported devices.
*/
const struct of_device_id *of_match_device(const struct of_device_id *matches,
const struct device *dev)
{
if ((!matches) || (!dev->of_node))
return NULL;
return of_match_node(matches, dev->of_node);
}
kernel/driver/of/base.c
/**
* of_match_node - Tell if an device_node has a matching of_match structure
*