of_device_id与i2c_device_id作用及I2C驱动匹配问题咨询
of_device_id无法触发probe的问题分析 我来帮你拆解这个问题——你遇到的情况其实是Linux内核I2C子系统匹配逻辑和设备树配置细节共同作用的结果,下面一步步分析:
一、为什么仅用of_device_id时probe不触发?
虽然内核文档说明设备树匹配(of_match_device)优先级高于传统id匹配(i2c_match_id),但你的场景里of匹配没生效,大概率是以下某一个原因:
1. 设备树节点的compatible属性与驱动不匹配
驱动里的of_match_table定义的匹配字符串是:
static const struct of_device_id adxl34x_of_id[] = { { .compatible = "adi,adxl345", }, { .compatible = "adi,adxl34x", }, { } };
你需要检查设备树里的ADXL34x节点是否严格匹配其中一个compatible值,比如:
&i2c1 { adxl345@53 { compatible = "adi,adxl345"; // 必须和驱动里的字符串完全一致,前缀、大小写都不能错 reg = <0x53>; status = "okay"; }; };
如果你的设备树里写的是compatible = "adxl345"(缺了adi,前缀),或者存在拼写错误,of_match_device就会返回NULL,匹配失败。
2. 内核CONFIG_OF配置或版本问题
- 确认你的内核确实开启了
CONFIG_OF(驱动里的#ifdef CONFIG_OF已经做了判断,但要确保编译时这个宏是生效的); - 如果你用的是比较老的内核(比如3.x版本),早期I2C子系统对纯设备树驱动的支持有缺陷,可能要求驱动必须提供
id_table才能被正确注册,即使你用的是设备树。
3. 设备树节点的其他配置错误
比如I2C节点的reg(设备地址)设置错误,或者status没有设为"okay",都会导致设备无法被枚举,自然不会触发probe。
二、为什么添加i2c_device_id后probe能正常触发?
当你启用i2c_device_id后,内核会走传统的i2c_match_id匹配逻辑:
static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, const struct i2c_client *client) { while (id->name[0]) { if (strcmp(client->name, id->name) == 0) return id; id++; } return NULL; }
这里的client->name在设备树场景下,大概率是内核从设备树节点的compatible或name属性自动生成的。比如如果你的设备树节点compatible是"adi,adxl345",内核可能会提取出adxl345作为client->name,刚好和你i2c_device_id里的"adxl345"匹配,所以触发了probe。
三、I2C驱动是否必须同时使用of_device_id和i2c_device_id?
答案是否定的。现代Linux内核(4.0+)的I2C子系统完全支持纯设备树驱动,不需要依赖i2c_device_id。你只需要确保:
- 设备树节点的
compatible与驱动的of_match_table严格匹配; - 内核开启
CONFIG_OF; - 设备树节点的地址、状态等配置正确。
很多主线Linux内核里的I2C驱动(比如其他ADI传感器驱动)都只保留了of_match_table,去掉了i2c_device_id,所以你的场景肯定可以做到纯设备树匹配。
解决步骤建议
- 仔细核对设备树节点的
compatible字符串,确保和驱动里的完全一致; - 检查设备树节点的
reg(I2C地址)和status是否正确; - 确认内核
CONFIG_OF已开启,且内核版本足够新(建议用4.14+版本); - 如果以上都没问题,可以在内核的
i2c_device_match函数里加打印,调试一下of匹配的过程,看是哪一步返回了NULL。
内容的提问来源于stack exchange,提问作者mrigendra

