参考:
Linux驱动框架之i2c驱动框架解析
i2c_client
结构体,将这个文件编译出来的.ko文件称之为"设备驱动"i2c_driver
结构体,将这个文件编译出来的.ko文件称之为"主机驱动"我的实现的I2C设备驱动:
【RV1126】IIC驱动–EEPROM
【RV1126】IIC驱动–MAX30102
文件地址:kernel/drivers/i2c/i2c-core-base.c
在线Linux源码位置查看:https://elixir.bootlin.com/linux/latest/source/drivers/i2c/i2c-core-base.c#L117
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
/* Attempt an OF style match */
if (i2c_of_match_device(drv->of_match_table, client))
return 1;
/* Then ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* Finally an I2C match */
if (i2c_match_id(driver->id_table, client))
return 1;
return 0;
}
这是所有的设备驱动匹配都适用的一种匹配方式,不仅限于I2C设备匹配,利用设备树(.dts,.dtsi)节点的字段进行配备。一般使用compatible
字段来进行匹配。
定义位置:kernel/include/linux/mod_devicetable.h
/*
* Struct used for matching a device
*/
struct of_device_id {
char name[32];
char type[32];
char compatible[128];
const void *data;
};
算法中,只要name或type,或compatible任一个匹配,就算匹配.
使用实例:
设备树中的:
&i2c4 {
status = "okay";
maxim@57 {
status = "okay";
compatible = "maxim,max30102";
reg = <0x57>;
};
};
驱动代码中的:
static const struct of_device_id max30102_of_match[] = {
{ .compatible = "maxim,max30102" },
{}
};
static struct i2c_driver driver =
{
.probe = rv1126_probe,
.remove = rv1126_remove,
.driver =
{
.name = "max30102",
.of_match_table = of_match_ptr(max30102_of_match),
},
};
由上可知,设备树中的compatible字段和结构体对象中的compatible成员是一致的,所以可以完成匹配。
对于ACPI主要是用于电源管理的,需要有acpi对应的id。
定义位置:kernel/include/linux/mod_devicetable.h
struct acpi_device_id {
__u8 id[ACPI_ID_LEN];
kernel_ulong_t driver_data;
__u32 cls;
__u32 cls_msk;
};
这个平时用得少,略过。
相比于OF style的设备匹配,I2C id表匹配是i2c专有的匹配方式: id_table方式:
定义位置:kernel/include/linux/mod_devicetable.h
struct i2c_device_id {
char name[I2C_NAME_SIZE];
kernel_ulong_t driver_data; /* Data private to the driver */
};
这种方式是比较常用的,有设备树后就用的少了。
使用实例:
&i2c4 {
status = "okay";
eeprom@50 {
status = "okay";
compatible = "atmel,at24c256B";
reg = <0x50>;
};
};
static struct i2c_device_id id_table[]=
{
{"eeprom", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, id_table);
static struct i2c_driver drv=
{
.probe=rv1126_probe,
.remove=rv1126_remove,
.driver=
{
.name="at24c256B",
},
.id_table=id_table
};