单I2C总线中同地址双I2C设备的DTS配置及适配问题求助
解决同I2C地址不同设备的绑定与检测问题
核心问题分析
同一I2C总线上无法同时注册两个相同地址的设备,这是Linux I2C子系统的固有限制。你当前的DTS同时声明device1@30和device2@30,会直接导致总线初始化时设备绑定冲突,其中一个设备必然无法完成绑定,后续的寄存器读取自然会失败。
解决方案
1. 针对不同电路板拆分DTS配置
如果两块电路板使用独立固件,最直接的方式是通过条件编译或设备树覆盖(overlay),仅在对应板子的固件中声明当前存在的设备:
条件编译示例(DTS)
#ifdef CONFIG_BOARD_DEVICE1 device1@30 { compatible = "device1"; reg = <0x30>; clock-mode = /bits/ 8 <1>; // 其他设备属性 }; #endif #ifdef CONFIG_BOARD_DEVICE2 device2@30 { compatible = "device2"; reg = <0x30>; clock-mode = /bits/ 8 <1>; // 其他设备属性 }; #endif
编译固件时,针对不同板子开启对应的CONFIG_BOARD_DEVICE1或CONFIG_BOARD_DEVICE2宏即可。
2. 单固件自动识别设备(通用驱动方案)
如果需要用同一份固件适配两块板子,不要在DTS中同时声明两个设备,而是声明一个通用占位节点,再在驱动中动态检测设备类型:
通用DTS节点
generic_i2c_device@30 { compatible = "generic-i2c-device"; reg = <0x30>; clock-mode = /bits/ 8 <1>; };
通用驱动实现(核心逻辑)
#include <linux/i2c.h> #include <linux/module.h> #define DEVICE_ID_REG_ADDR 0x00 // 根据实际设备的ID寄存器地址调整 #define DEVICE1_ID 0xAB // device1的ID值 #define DEVICE2_ID 0xCD // device2的ID值 static int generic_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { int ret; u8 device_id; // 读取设备ID寄存器 ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG_ADDR); if (ret < 0) { dev_err(&client->dev, "Failed to read device ID\n"); return ret; } device_id = ret; // 根据ID绑定对应设备逻辑 if (device_id == DEVICE1_ID) { dev_info(&client->dev, "Detected device1, initializing..."); // 执行device1的初始化、注册字符设备等操作 } else if (device_id == DEVICE2_ID) { dev_info(&client->dev, "Detected device2, initializing..."); // 执行device2的初始化、注册字符设备等操作 } else { dev_err(&client->dev, "Unknown device with ID 0x%x", device_id); return -ENODEV; } return 0; } static const struct of_device_id generic_i2c_of_match[] = { { .compatible = "generic-i2c-device" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, generic_i2c_of_match); static struct i2c_driver generic_i2c_driver = { .driver = { .name = "generic-i2c-device", .of_match_table = generic_i2c_of_match, }, .probe = generic_i2c_probe, }; module_i2c_driver(generic_i2c_driver); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Generic I2C driver for device1/device2");
3. 排查检测失败的额外注意事项
你之前的驱动检测失败,本质是DTS地址冲突导致其中一个驱动的probe函数根本无法执行。修正DTS后,需单独验证每个设备的ID读取逻辑:
- 确认ID寄存器地址、读取方式(SMBus字节读/I2C块读)与设备手册一致
- 检查I2C总线的电气连接(上拉电阻、电平匹配)是否正常
内容的提问来源于stack exchange,提问作者Adil Saidi
相关产品推荐
相关产品推荐

