RK3588 kernel-6.1/drivers/i2c/i2c-stub.c 功能详细分析

RK3588 kernel-6.1/drivers/i2c/i2c-stub.c 功能详细分析

1. 文档范围与说明

路径说明: 用户表述为「i2c-stub.c 目录」,实际为 单个源文件

  • rk3588/kernel-6.1/drivers/i2c/i2c-stub.c(约 414 行)

编译关系:

1
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
1
2
3
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on m # 仅能编译为模块,不能 built-in

文档保存路径: linuxDoc/drivers/i2c/

定位: 纯软件 I2C/SMBus 芯片模拟器(Test Stub)。注册一条 虚拟 i2c_adapter,在模块参数指定的 最多 10 个 7 位地址 上响应 SMBus 命令,数据保存在 内核内存数组 中,不连接任何硬件。用于 客户端驱动开发、回归测试、无实物传感器时的行为验证

与 RK3588 的关系:

项目 说明
产品内核 rockchip_linux_defconfig 通常不包含 CONFIG_I2C_STUB
硬件 ;与 i2c-rk3x 等真实总线 独立
用途 开发机/CI 上 modprobe i2c-stub + 加载被测驱动;非量产路径

2. 功能总览

功能 实现 说明
虚拟总线 全局 stub_adapter 单条 adapter,i2c_add_adapter() 注册
SMBus 仿真 stub_xfer() 实现 algo->smbus_xfer,无 master_xfer
多芯片地址 chip_addr[] 模块参数 最多 10 个地址 (0x03–0x77)
寄存器模型 stub_chip.words[256] 每地址 256 个 16 位“寄存器”
指针自增 chip->pointer Byte/Byte Data 类操作模拟 EEPROM 连续读
存储体切换 bank_* 模块参数 可选 bank 寄存器与扩展地址空间
SMBus Block smbus_block_data 链表 functionality 开启 I2C_FUNC_SMBUS_BLOCK_DATA
能力掩码 functionality 模块参数 可裁剪支持的 SMBus 命令类型

3. 架构示意

1
2
3
4
5
6
7
8
9
10
被测 i2c_driver (如 hwmon、PMIC 测试)
│ i2c_smbus_read_byte_data() 等

i2c-core-smbus.c → i2c_smbus_xfer()

stub_adapter (虚拟)
│ algo.smbus_xfer = stub_xfer

内存: stub_chips[i].words[] / bank_words[] / smbus_blocks
(无 SDA/SCL,无 rk3x)

特点:

  • 仅实现 smbus_xfer master_xfer → 用户态 I2C_RDWRi2c-dev不可用
  • class = I2C_CLASS_HWMON | I2C_CLASS_SPD,便于遗留 class 探测匹配;
  • 每次操作 dev_dbg 打日志(文档称可能刷屏)。

4. 模块参数

参数 类型 默认值 含义
chip_addr ushort[] 必须至少 1 个 模拟芯片的 7 位地址,最多 10 个
functionality ulong STUB_FUNC_DEFAULT 覆盖 stub_func() 返回值位掩码
bank_reg u8[] 0 选 bank 的寄存器号
bank_mask u8[] 0 bank 字段掩码(连续位假设)
bank_start u8[] bank 区内寄存器起始
bank_end u8[] bank 区内寄存器结束

4.1 默认 functionality

1
2
3
4
5
6
#define STUB_FUNC_DEFAULT \
(I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK)

#define STUB_FUNC_ALL (STUB_FUNC_DEFAULT | I2C_FUNC_SMBUS_BLOCK_DATA)
  • I2C_FUNC_SMBUS_BLOCK_DATA 默认关闭;需 modprobe 时设置 functionality 显式开启;
  • stub_func() 返回 STUB_FUNC_ALL & functionality

4.2 加载示例

1
2
3
modprobe i2c-stub chip_addr=0x48,0x49
i2cset -y <stub_bus_num> 0x48 0x00 0x1a
modprobe <被测驱动>

可用 i2c-tools 脚本 i2c-stub-from-dump 从芯片 dump 批量加载寄存器初值。


5. 核心数据结构

5.1 struct stub_chip(每地址一个)

  • pointer:SMBus 当前地址,支持自增读;
  • words[256]:主寄存器文件,字节操作用 低 8 位(符合 SMBus 规范);
  • smbus_blocks:按 command 索引的 SMBus block 数据链表;
  • 可选 bank_words:多 bank 扩展寄存器。

5.2 SMBus block 语义

  • 写可部分更新;读返回历史上最大写长度 的数据;
  • 无先写直接读-EOPNOTSUPP

6. stub_xfer() — SMBus 命令处理

根据 addr 匹配 chip_addr[];未找到返回 -ENODEV

size 行为摘要
QUICK 直接 ACK
BYTE 写设 pointer;读从 pointer++ 取 LSB
BYTE_DATA 读/写 words[command];可切换 bank;pointer=command+1
WORD_DATA 读/写 16 位
I2C_BLOCK 连续访问 words[](忽略 bank)
BLOCK_DATA 链表存 block;须先写后读
其它 -EOPNOTSUPP

6.1 Bank 机制

bank_mask[i] 非 0 时分配 bank_words:写 bank_reg 切换 bank_sel[bank_start,bank_end] 范围内访问 bank 区。


7. 初始化与退出

init: 校验 chip_addr[0]、地址范围、分配 stub_chips、可选 bank、i2c_add_adapter(&stub_adapter)

exit: i2c_del_adapter + 释放内存。

1
2
3
4
5
static struct i2c_adapter stub_adapter = {
.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
.algo = &smbus_algorithm,
.name = "SMBus stub driver",
};

8. 典型使用流程

  1. modprobe i2c-stub chip_addr=0x48
  2. i2cset 预加载寄存器
  3. modprobe 被测客户端驱动
  4. 观察 dmesg

注意: 驱动若轮询等待寄存器变化可能死锁,需 i2cset 解锁;高频日志可能丢失。


9. 与真实 I2C 对比(RK3588)

维度 i2c-stub i2c-rk3x + 真实设备
硬件 SoC I2C
API 仅 smbus_xfer master_xfer + SMBus 模拟
配置 CONFIG_I2C_STUB=m CONFIG_I2C_RK3X=y

10. RK3588 结论

  • 产品镜像 默认不包含;可选模块用于 驱动开发/CI
  • slave-eeprom/testunit(从机模拟)不同:stub 是 主机侧虚拟总线 + 内存寄存器
  • 不能替代硬件联调。

11. 相关文档


文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/i2c-stub.c 分析。

文章互动

阅读 --

留言

0 条留言

正在加载留言…