如果我们已经在使用 struct of_device_id,那么 struct i2c_device_id 有什么用?
What is use of struct i2c_device_id if we are already using struct of_device_id?
我试图了解 Linux 内核 4.4 上的编解码器驱动程序代码。编解码器使用 i2c 总线连接到声卡,编解码器驱动程序代码编写为 I2C 客户端。客户端的 struct i2c_driver 包含 i2c_device_id 信息和 of_device_id 信息。
现在根据我的理解,当 compatible string of struct of_device_id 匹配 compatible 设备节点信息字符串。那么struct i2c_device_id有什么用呢?
注意:编解码器驱动程序正在使用设备树。
您的 i2c_device_id
结构被 i2c_driver
结构引用; I²C 框架使用它来查找要附加到特定 I²C 设备的驱动程序。这类似于 of_device_id
信息用于查找设备树中描述的特定设备的驱动程序的方式。
作为驱动程序编写者,您并不真正了解编解码器稍后将如何实际枚举(I²C 或 OF),因此您应该提供这两种信息。
当您使用 MODULE_DEVICE_TABLE()
时,i2c_device_id
结构中的值用于查找要加载的模块。 (这在既没有热插拔也没有模块的嵌入式系统中不太可能发生,但如果编解码器曾用于模块化系统(例如,用于测试),自动加载可能无法工作。)
此外,MODULE_DEVICE_TABLE()
提供的信息可用于确定某些特定硬件需要哪些内核配置选项。
假设您有以下 i2c 驱动程序结构:
static const struct i2c_device_id lm75_ids[] = {
{ "adt75", adt75, },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm75_ids);
static const struct of_device_id lm75_of_match[] = {
{ .compatible = "adi,adt75" },
{ },
};
MODULE_DEVICE_TABLE(of, lm75_of_match);
static struct i2c_driver lm75_driver = {
.driver = {
.name = "lm75",
.of_match_table = of_match_ptr(lm75_of_match),
},
.probe = lm75_probe,
.id_table = lm75_ids,
};
module_i2c_driver(lm75_driver);
当 I2C 设备通过用户空间实例化时:
echo adt75 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
i2c-core 将名称 "adt75" 与结构 i2c_device_id 数组中的名称匹配,并将该元素传递给 lm75_probe。
当 I2C 设备通过 OF 设备树实例化时,它的兼容 属性 被匹配(格式:"manufacturer,model")并且 "model" 组件与结构 [=25] 匹配=] 数组 - 也将该元素传递给 lm75_probe。非常整洁!
struct of_device_id 也有一个 .data 属性,您可以通过不同的机制访问它。
我试图了解 Linux 内核 4.4 上的编解码器驱动程序代码。编解码器使用 i2c 总线连接到声卡,编解码器驱动程序代码编写为 I2C 客户端。客户端的 struct i2c_driver 包含 i2c_device_id 信息和 of_device_id 信息。
现在根据我的理解,当 compatible string of struct of_device_id 匹配 compatible 设备节点信息字符串。那么struct i2c_device_id有什么用呢?
注意:编解码器驱动程序正在使用设备树。
您的 i2c_device_id
结构被 i2c_driver
结构引用; I²C 框架使用它来查找要附加到特定 I²C 设备的驱动程序。这类似于 of_device_id
信息用于查找设备树中描述的特定设备的驱动程序的方式。
作为驱动程序编写者,您并不真正了解编解码器稍后将如何实际枚举(I²C 或 OF),因此您应该提供这两种信息。
当您使用 MODULE_DEVICE_TABLE()
时,i2c_device_id
结构中的值用于查找要加载的模块。 (这在既没有热插拔也没有模块的嵌入式系统中不太可能发生,但如果编解码器曾用于模块化系统(例如,用于测试),自动加载可能无法工作。)
此外,MODULE_DEVICE_TABLE()
提供的信息可用于确定某些特定硬件需要哪些内核配置选项。
假设您有以下 i2c 驱动程序结构:
static const struct i2c_device_id lm75_ids[] = {
{ "adt75", adt75, },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm75_ids);
static const struct of_device_id lm75_of_match[] = {
{ .compatible = "adi,adt75" },
{ },
};
MODULE_DEVICE_TABLE(of, lm75_of_match);
static struct i2c_driver lm75_driver = {
.driver = {
.name = "lm75",
.of_match_table = of_match_ptr(lm75_of_match),
},
.probe = lm75_probe,
.id_table = lm75_ids,
};
module_i2c_driver(lm75_driver);
当 I2C 设备通过用户空间实例化时:
echo adt75 0x50 > /sys/bus/i2c/devices/i2c-3/new_device
i2c-core 将名称 "adt75" 与结构 i2c_device_id 数组中的名称匹配,并将该元素传递给 lm75_probe。
当 I2C 设备通过 OF 设备树实例化时,它的兼容 属性 被匹配(格式:"manufacturer,model")并且 "model" 组件与结构 [=25] 匹配=] 数组 - 也将该元素传递给 lm75_probe。非常整洁!
struct of_device_id 也有一个 .data 属性,您可以通过不同的机制访问它。