内核4.19中内置I2C驱动未注册/初始化问题排查求助
I2C音频驱动未被内核编入/注册的排查问题
仅通过Linux速成课程接触Linux,正在4.19版本内核中添加一款I2C控制的音频设备驱动,驱动位于sound/soc/codecs/目录下。以下是已完成的配置与当前遇到的问题:
已完成的配置
驱动代码片段
static const struct i2c_device_id foo_i2c_id[] = { { "foo", 0 }, {} }; MODULE_DEVICE_TABLE(i2c, foo_i2c_id); static const struct of_device_id foo_i2c_match[] = { { .compatible = "bar,foo" }, {} }; MODULE_DEVICE_TABLE(of, foo_i2c_match); static struct i2c_driver foo_i2c_driver = { .driver = { .name = foo, .owner = THIS_MODULE, .of_match_table = of_match_ptr(foo_i2c_match), }, .probe = foo_i2c_probe, .remove = foo_i2c_remove, .id_table = foo_i2c_id, }; static int __init foo_ctl_init(void) { int ret = 0; ret = i2c_add_driver(&foo_i2c_driver); if (ret != 0) { printk("%s: i2c driver register failed.\n", __func__); } else { printk("%s: i2c driver register SUCCESS.\n", __func__); } return ret; } device_initcall(foo_ctl_init); MODULE_DESCRIPTION("foo driver"); MODULE_LICENSE("GPL v2");
Makefile配置(sound/soc/codecs/目录下)
obj-$(CONFIG_SND_SOC_FOO) += foo_driver.o
Kconfig配置
config SND_SOC_FOO tristate "Foo driver" depends on I2C
defconfig配置(arch/arm64/configs/vendor/bengal_defconfig)
CONFIG_SND_SOC_FOO=y
设备树配置
&qupv3_se1_i2c { foo@5d { status = "okay"; compatible = "bar,foo"; reg = <0x5d>; } }
当前现象
- 设备树配置生效,通过以下命令可看到foo设备节点:
ls -al /sys/bus/i2c/devices/ # 输出包含 0-005d -> ../../../devices/platform/soc/4a84000.i2c/i2c-0/0-005d ls /proc/device-tree/soc/i2c@4a84000: # 输出包含 foo@5d - dmesg中无任何与foo驱动相关的日志
- 逻辑分析仪可捕获同I2C总线上其他设备的探测信号,但未捕获到地址0x5d的操作
- 执行
objdump -x vmlinux | grep foo无任何输出,推测驱动未被编入内核
排查方向
1. 确认驱动是否被正确编译进内核
- 检查内核编译日志,查找是否有
CC sound/soc/codecs/foo_driver.o或LD sound/soc/codecs/foo_driver.o相关记录,若没有则说明驱动未被编译 - 查看编译生成的
.config文件,确认CONFIG_SND_SOC_FOO=y是否存在(defconfig导入后可能被其他依赖配置覆盖) - 确认上层音频子系统配置是否开启:检查
.config中CONFIG_SND_SOC是否设为y或m,否则音频codecs目录下的驱动不会被编译 - 检查sound/soc/codecs/目录的Makefile是否被上层Makefile正确包含,比如确认
sound/soc/Makefile中是否有obj-$(CONFIG_SND_SOC_CODECS) += codecs/之类的配置
2. 修复驱动代码中的语法错误
- 驱动代码中
.driver.name = foo存在明显错误:foo未加引号,应改为.name = "foo",否则编译会报错,导致驱动无法生成 - 确认
foo_i2c_probe和foo_i2c_remove函数已正确定义,若未定义,编译会出现未引用符号的错误,阻止驱动编译 - 建议使用
module_i2c_driver宏替代手动注册逻辑,简化代码并避免注册错误:
替换原有的module_i2c_driver(foo_i2c_driver);foo_ctl_init函数和device_initcall
3. 后续匹配验证(驱动编译成功后)
- 若驱动已编译进内核,可通过
cat /sys/bus/i2c/drivers/foo查看是否存在该驱动,确认驱动是否注册成功 - 检查设备树节点的
compatible字符串与驱动中of_device_id的.compatible是否完全一致(大小写、逗号分隔均需匹配)
内容的提问来源于stack exchange,提问作者ShityCoder
相关产品推荐
相关产品推荐

