当前位置: 首页 > news >正文

linux kernel struct regmap_config结构详解

在 Linux 内核中,struct regmap_config 是 ​Regmap 子系统的核心配置结构体,用于定义如何与底层硬件寄存器进行交互。Regmap(Register Map)子系统通过抽象不同总线(如 I2C、SPI、MMIO 等)的寄存器访问细节,为驱动开发者提供统一的寄存器读写接口,显著简化了设备驱动的开发。

以下是对 struct regmap_config 结构体的详细解析,涵盖其核心成员、功能及典型配置场景:

一、结构体定义概览(以 Linux 5.10+ 内核为例)

struct regmap_config {/* 基础标识与总线类型 */const char *name;               // Regmap 实例名称(调试用)enum regmap_bus_type bus_type;  // 总线类型(如 REGMAP_BUS_I2C、REGMAP_BUS_SPI、REGMAP_BUS_MMIO 等)/* 寄存器与值的位宽配置 */int reg_bits;                   // 寄存器地址的位宽(如 8/16/32 位)int val_bits;                   // 寄存器值的位宽(如 8/16/32 位)int pad_bits;                   // 地址/值与实际总线传输间的填充位(通常为 0)/* 字节序与对齐方式 */enum regmap_endian reg_format_endian;  // 寄存器地址的字节序(大端/小端/不转换)enum regmap_endian val_format_endian;  // 寄存器值的字节序(同上)bool reg_stride;                // 地址自动递增步长(默认 1,若硬件地址不连续需手动设置)/* 访问约束与超时 */unsigned int max_register;      // 设备支持的最大寄存器地址(0 表示无限制)unsigned int fast_io;           // 是否启用快速 IO(1 启用,依赖硬件特性)unsigned long read_flag_mask;   // 读操作的标志掩码(如 I2C 的 RD 位)unsigned long write_flag_mask;  // 写操作的标志掩码(如 I2C 的 WR 位)/* 缓存策略 */enum regmap_cache_type cache_type;  // 缓存类型(无缓存/读缓存/写缓存/读写缓存)unsigned int cache_size;            // 缓存大小(字节数,0 表示自动计算)bool use_single_read;               // 强制单次读(即使支持批量读)bool use_single_write;              // 强制单次写(即使支持批量写)/* 中断与事件处理 */int irq;                          // 设备关联的中断号(若需要)unsigned long irq_flags;          // 中断触发标志(如 IRQF_SHARED)/* 自定义回调函数 */int (*reg_read)(struct regmap *map, unsigned int reg, unsigned int *val);  // 自定义读回调int (*reg_write)(struct regmap *map, unsigned int reg, unsigned int val); // 自定义写回调void (*lock)(struct regmap *map);                                         // 自定义锁函数void (*unlock)(struct regmap *map);                                       // 自定义解锁函数/* 调试与日志 */bool verbose;                     // 是否启用详细日志(调试用)struct dentry *debugfs;           // DebugFS 挂载点(用于调试)
};

二、核心成员详解

1. 基础标识与总线类型
  • ​**name**​:Regmap 实例的名称(如 "my_spi_device_regmap"),主要用于调试日志和 DebugFS 展示。
  • ​**bus_type**​:指定底层总线类型,决定 Regmap 如何与总线驱动交互。常见值包括:
    • REGMAP_BUS_I2C:I2C 总线(需配合 struct i2c_client 使用)。
    • REGMAP_BUS_SPI:SPI 总线(需配合 struct spi_device 使用)。
    • REGMAP_BUS_MMIO:内存映射 IO(MMIO,直接访问物理内存地址)。
    • REGMAP_BUS_HOST:主机侧总线(如用于连接外部芯片的专用总线)。
2. 寄存器与值的位宽配置
  • ​**reg_bits**​:寄存器地址的二进制位数(如 8 位地址对应 reg_bits=8)。
    示例:若设备寄存器地址范围是 0x00 ~ 0xFF,则 reg_bits=8
  • ​**val_bits**​:寄存器值的二进制位数(如 16 位值对应 val_bits=16)。
    示例:若寄存器是 8 位宽(每次读写 1 字节),则 val_bits=8;若是 16 位宽(大端存储),则 val_bits=16
  • ​**pad_bits**​:地址或值与实际总线传输字节的填充位数(通常为 0)。
    示例:某些 SPI 设备需要在地址后填充 4 位校验位,则 pad_bits=4
3. 字节序与对齐方式
  • ​**reg_format_endian**​:寄存器地址的字节序(仅当 reg_bits > 8 时有效)。
    可选值:REGMAP_ENDIAN_BIG(大端)、REGMAP_ENDIAN_LITTLE(小端)、REGMAP_ENDIAN_NATIVE(与 CPU 一致)。
  • ​**val_format_endian**​:寄存器值的字节序(仅当 val_bits > 8 时有效)。
    示例:SPI 设备寄存器值为 16 位大端格式,则 val_format_endian=REGMAP_ENDIAN_BIG
  • ​**reg_stride**​:地址自动递增的步长(默认 1)。
    场景:若硬件寄存器地址不连续(如跳过保留地址),可手动设置步长(如 reg_stride=2 表示每次地址+2)。
4. 访问约束与超时
  • ​**max_register**​:设备支持的最大寄存器地址(0 表示无限制)。
    作用:Regmap 会检查读写操作的地址是否超过此值,避免越界访问。
  • ​**fast_io**​:启用快速 IO 优化(默认 0)。
    条件:仅当底层总线支持原子读写(如 MMIO 或高速 SPI)时设置为 1,可减少函数调用开销。
  • ​**read_flag_mask/write_flag_mask**​:总线操作的标志位掩码。
    示例:I2C 设备写操作需要在地址后置位 0(写标志),则 write_flag_mask=0x00;读操作置位 1(读标志),则 read_flag_mask=0x01(具体取决于总线协议)。
5. 缓存策略

Regmap 支持缓存寄存器值以减少总线访问次数(尤其适用于频繁读写的只读/半静态寄存器)。

  • ​**cache_type**​:缓存类型,可选值:
    • REGMAP_CACHE_NONE:无缓存(每次读写直接访问硬件)。
    • REGMAP_CACHE_R:只读缓存(仅缓存读操作结果,写操作后失效)。
    • REGMAP_CACHE_W:写缓存(写操作先更新缓存,读操作从缓存读取,需配合 regmap_write 自动同步)。
    • REGMAP_CACHE_RW:读写缓存(读写均通过缓存,需手动调用 regmap_sync() 同步到硬件)。
  • ​**cache_size**​:缓存大小(字节数)。若为 0,Regmap 会根据 max_registerval_bits 自动计算。
  • ​**use_single_read/use_single_write**​:强制单次读写(即使总线支持批量操作)。
    场景:某些老旧设备不支持批量传输,需强制每次读写一个寄存器。
6. 中断与事件处理
  • ​**irq**​:设备关联的中断号(若需要 Regmap 处理中断)。
    配合:需结合 regmap_irq_chip 定义中断映射,实现中断的统一管理。
  • ​**irq_flags**​:中断触发标志(如 IRQF_SHARED 共享中断、IRQF_ONESHOT 单次触发)。
7. 自定义回调函数

Regmap 允许通过自定义回调覆盖默认的读写逻辑(如硬件有特殊时序要求)。

  • ​**reg_read/reg_write**​:自定义读写函数,原型为:
    int (*reg_read)(struct regmap *map, unsigned int reg, unsigned int *val);
    int (*reg_write)(struct regmap *map, unsigned int reg, unsigned int val);
    示例:实现非标准的 SPI 事务(如先发命令再读数据)。
  • ​**lock/unlock**​:自定义锁函数(默认使用自旋锁或互斥锁)。
    场景:多线程/中断上下文共享 Regmap 时,需自定义锁机制保证线程安全。
8. 调试与日志
  • ​**verbose**​:启用详细日志(默认 0)。设置为 1 时,Regmap 会在读写操作时打印调试信息(如地址、值)。
  • ​**debugfs**​:DebugFS 挂载点路径(如 "/sys/kernel/debug/regmap/my_regmap"),可通过 regmap-dump 工具查看寄存器状态。

三、典型配置示例

示例 1:SPI 设备(16 位地址,8 位值,大端)

假设一个 SPI 设备的寄存器地址为 16 位(范围 0x0000 ~ 0xFFFF),每个寄存器值是 8 位,且地址采用大端格式:

static const struct regmap_config my_spi_regmap_config = {.name = "my_spi_device",.bus_type = REGMAP_BUS_SPI,.reg_bits = 16,       // 16 位寄存器地址.val_bits = 8,        // 8 位寄存器值.reg_format_endian = REGMAP_ENDIAN_BIG,  // 地址大端格式.max_register = 0xFFFF, // 最大地址.fast_io = 1,         // 启用快速 IO.cache_type = REGMAP_CACHE_RW, // 读写缓存
};
示例 2:I2C 设备(8 位地址,16 位值,小端)

假设一个 I2C 设备的寄存器地址为 8 位(范围 0x00 ~ 0x7F),每个寄存器值是 16 位小端格式:

static const struct regmap_config my_i2c_regmap_config = {.name = "my_i2c_device",.bus_type = REGMAP_BUS_I2C,.reg_bits = 8,        // 8 位寄存器地址.val_bits = 16,       // 16 位寄存器值.val_format_endian = REGMAP_ENDIAN_LITTLE, // 值小端格式.max_register = 0x7F, // 最大地址.read_flag_mask = 0x01, // I2C 读操作标志位(假设设备要求地址后第 0 位为 1).cache_type = REGMAP_CACHE_NONE, // 无缓存(实时性要求高)
};

四、关键注意事项

  1. 总线适配器依赖​:bus_type 需与实际使用的总线驱动匹配(如 SPI 需先注册 spi_device,I2C 需先注册 i2c_client)。
  2. 位宽对齐​:reg_bitsval_bits 需与硬件寄存器的实际位宽严格一致,否则会导致读写错误。
  3. 缓存一致性​:启用缓存(cache_type != REGMAP_CACHE_NONE)时,需在寄存器值变更后调用 regmap_write()regmap_update_bits() 触发缓存同步;若硬件状态可能被外部修改(如其他主设备),需手动调用 regmap_sync() 刷新缓存。
  4. 字节序处理​:reg_format_endianval_format_endian 需根据硬件的寄存器定义设置(如网络设备常用大端,传感器常用小端)。
  5. 中断处理​:若设备需要中断支持,需额外定义 struct regmap_irq_chip 并关联到 Regmap 实例(通过 regmap_add_irq_chip())。

五、总结

struct regmap_config 是 Linux Regmap 子系统的核心配置结构体,通过灵活设置其成员,开发者可以适配各种总线和寄存器特性的硬件设备。关键是根据硬件的实际需求(总线类型、位宽、字节序、缓存需求等)配置相应字段,并合理利用 Regmap 提供的统一接口简化寄存器操作。

http://www.dtcms.com/a/274613.html

相关文章:

  • 力扣242.有效的字母异位词
  • MySQL5.7版本出现同步或插入中文出现乱码或???显示问题处理
  • vector之动态二维数组的底层
  • django queryset 去重
  • JavaSE -- StreamAPI 详细介绍(上篇)
  • Java开发新宠!飞算JavaAI深度体验评测
  • 获取华为开源3D引擎 (OpenHarmony),把引擎嵌入VUE中
  • string模拟实现
  • 信号肽预测工具PrediSi本地化
  • 《打破预设的编码逻辑:Ruby元编程的动态方法艺术》
  • 内存踩踏全解析:原理 + 实战案例 + 项目排查技巧
  • 2025十大免费销售管理软件推荐
  • 基于物联网的智能体重秤设计与实现
  • 测试第一定律
  • 如何通过公网IP访问部署在kubernetes中的服务?
  • AVL平衡二叉树
  • 为什么必须掌握Java异常处理机制?——从代码健壮性到面试必考题全解析
  • 阿里云服务器,CentOS7.9上安装YApi 接口管理平台
  • Linux修炼:权限
  • vue2往vue3升级需要注意的点(个人建议非必要别直接升级)
  • 基于规则匹配的文档标题召回
  • Leaflet面试题及答案(21-40)
  • PHT-CAD 笔记
  • 【每日算法】专题八_分治_归并排序
  • k8s新增jupyter服务
  • 7.11 dp 图
  • 企业IT管理——医院数据备份与存储制度模板
  • spring-ai RAG(Retrieval-Augmented Generation)
  • 【网络】Linux 内核优化实战 - net.netfilter.nf_conntrack_max
  • 【网络】Linux 内核优化实战 - net.netfilter.nf_conntrack_buckets