如何定义Linux内核驱动中适配TPS92518-Q1系列的SPI帧格式
1 Regmap 请求/响应预处理方案
除了完整实现reg_read/reg_write回调外,还有两种更轻量的实现方式,不需要重写regmap已有的寄存器校验、缓存管理逻辑:
- 优先选择
pre_write和post_read回调:Linux 5.1及以上版本的regmap支持在struct regmap_config中配置这两个回调,pre_write会在寄存器写请求下发到SPI总线前触发,你可以在这个回调里组装完1位命令位、5位地址、9位数据后,按XNOR规则计算校验位,写入到1位pad位的位置。post_read回调会在SPI读响应返回后触发,你可以在这里解析读/写响应帧中的错误位(SPI错误、欠压错误、过热警告等),返回对应的内核错误码即可。 - 如果需要兼容更低内核版本,可以自定义
struct regmap_bus的write/read回调,只修改SPI帧的组装和解析逻辑,其余逻辑依然复用regmap的通用实现。
校验位计算参考代码:
// 返回值为1位奇偶校验位,输入为1位命令位、5位地址、9位数据 static u8 tps92518_calc_parity(u8 cmd, u8 addr, u16 data) { u16 val = (cmd << 14) | ((addr & GENMASK(4, 0)) << 9) | (data & GENMASK(8, 0)); // __builtin_parity返回所有位异或结果,取反得到XNOR return !__builtin_parity(val); }
2 SPI协议格式指定位置
SPI协议的配置分为两部分:
- 物理层参数(CPOL、CPHA、位序、最大时钟频率):直接在SPI设备的
struct spi_device结构体的mode和max_speed_hz成员中配置,也可以通过设备树的spi-cpol、spi-cpha、spi-lsb-first属性定义,SPI核心会自动将配置同步到控制器。 - 器件自定义的帧结构(本次的16位位域定义):属于驱动层面的协议逻辑,不需要向SPI核心注册,你在上述regmap的预处理回调中自行完成位域的组装、解析即可。
你当前定义的regmap配置是合理的,.reg_bits = 6刚好对应1位命令位+5位地址,.pad_bits = 1对应奇偶校验位,.val_bits = 9对应数据位,刚好匹配16位SPI帧长度,不需要额外做字节对齐处理。
内容的提问来源于stack exchange,提问作者fireblade
相关产品推荐
相关产品推荐

