Linux内核关机时ST LSM6DSM驱动致I2C总线堵塞无法正常掉电问题咨询
问题分析
1. ST官方lsm6dsm驱动是否存在缺陷
大概率是驱动电源管理逻辑存在遗漏。4.19版本分支的ST官方LSM6DSM驱动未实现shutdown回调函数,内核触发关机流程时,不会主动终止驱动正在进行的I2C寄存器访问操作,也不会重置IMU的通信状态。如果I2C传输进行到一半时驱动被内核强制停止,就会出现从设备持续拉低SCL引脚的堵塞问题。
2. Linux内核I2C处理逻辑是否有问题
内核原生I2C核心逻辑不会主动引发总线堵塞。该场景属于典型的未完成I2C传输异常:当I2C主机发起传输后,从设备处于时钟延展状态拉低SCL的过程中,主机侧驱动突然终止,没有发送停止位或者重置I2C控制器,从设备就会一直保持SCL拉低的状态等待后续传输,这是外设驱动逻辑缺失导致的,和内核I2C核心逻辑无关。
3. 关机场景下I2C总线堵塞是否合理、pm_power_off调用regmap_write()是否合规
I2C总线在关机场景下堵塞不属于合理情况。pm_power_off钩子中调用regmap_write()访问PMU本身完全符合内核开发规范,大量嵌入式设备的掉电逻辑都采用该实现方式。写入失败问题是因为执行PMU写入操作前,I2C总线已经被未完成的传输堵死,后续所有I2C操作自然会超时失败。
修复方向
- 为LSM6DSM驱动添加
shutdown回调函数,回调执行时先取消所有正在调度的寄存器访问任务,再向IMU发送软复位指令,最后重置对应I2C控制器的状态,确保关机前总线回到空闲状态。 - 可在
pm_power_off执行PMU写入操作前,先调用内核I2C核心提供的i2c_recover_bus()接口触发总线恢复逻辑,主动把被拉死的总线重置为可用状态,避免前面的异常影响最终掉电操作。
内容的提问来源于stack exchange,提问作者fadedbee
相关产品推荐
相关产品推荐

