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 | config I2C_STUB |
文档保存路径: 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 | 被测 i2c_driver (如 hwmon、PMIC 测试) |
特点:
- 仅实现
smbus_xfer,无master_xfer→ 用户态I2C_RDWR(i2c-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 |
I2C_FUNC_SMBUS_BLOCK_DATA默认关闭;需modprobe时设置functionality显式开启;stub_func()返回STUB_FUNC_ALL & functionality。
4.2 加载示例
1 | modprobe i2c-stub chip_addr=0x48,0x49 |
可用 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 | static struct i2c_adapter stub_adapter = { |
8. 典型使用流程
modprobe i2c-stub chip_addr=0x48i2cset预加载寄存器modprobe被测客户端驱动- 观察 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. 相关文档
Documentation/i2c/i2c-stub.rst- rk3588-kernel-6.1-i2c-core-smbus.c功能详细分析_zh.md
- rk3588-kernel-6.1-i2c-dev.c功能详细分析_zh.md
- rk3588-kernel-6.1-drivers-i2c目录功能详细分析_zh.md
文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/i2c-stub.c 分析。
正在加载留言…