RK3588 kernel-6.1/drivers/i2c/i2c-slave-testunit.c 功能详细分析
1. 文档范围与说明
路径说明: 用户表述为「i2c-slave-testunit.c 目录」,实际为 单个源文件:
rk3588/kernel-6.1/drivers/i2c/i2c-slave-testunit.c(约 193 行)
编译关系:
1 | obj-$(CONFIG_I2C_SLAVE_TESTUNIT) += i2c-slave-testunit.o |
依赖:
1 | CONFIG_I2C_SLAVE_TESTUNIT → 依赖 CONFIG_I2C_SLAVE |
文档保存路径: linuxDoc/drivers/i2c/
定位: I2C 从机模式测试单元(testunit)后端,供 I2C 主机控制器驱动开发与回归测试 使用。外部测试主机通过 写 4 字节寄存器 触发用例;从机在 workqueue 中可再作为 Master 发起 i2c_transfer(多主、Host Notify 等场景)。非生产用途,ABI 不保证稳定。
与 RK3588 的关系:
| 项目 | RK3588 典型情况 |
|---|---|
CONFIG_I2C_SLAVE / TESTUNIT |
defconfig 通常未启用 |
i2c-rk3x |
无从机 + 无 master/slave 切换 → 本驱动 无法在 rk3x 上正常工作 |
| 用途 | 主要在 其它支持 I2C Slave 的控制器 上验证主机驱动;RK3588 文档供架构对照 |
2. 功能总览
| 模块 | 符号 | 作用 |
|---|---|---|
| 寄存器协议 | enum testunit_regs |
CMD / DATAL / DATAH / DELAY |
| 测试命令 | enum testunit_cmds |
READ_BYTES、HOST_NOTIFY、SMBUS_BLOCK_PROC_CALL |
| 从机回调 | i2c_slave_testunit_slave_cb() |
解析主机写入、处理读版本号 / Block Proc Call |
| 延迟执行 | i2c_slave_testunit_work() |
STOP 后按 DELAY 在 workqueue 执行测试 |
| 注册 | i2c_slave_register() |
挂接从机事件 |
| 实例化 | slave-testunit |
经 sysfs new_device |
3. 设计目的与使用场景
内核文档 Documentation/i2c/slave-testunit-backend.rst 说明:
- 为 难以获得的远程从设备能力 提供可编程替身(多主机仲裁、SMBus Host Notify、Block Process Call 等);
- 部分测试要求从机控制器能在 Slave ↔ Master 间切换(本驱动在 work 里调用
i2c_transfer); - 禁止用于量产镜像;带版本号
TU_CUR_VERSION = 0x01,读操作返回该版本。
4. 架构与数据流
1 | 测试用 I2C Master (PC/另一 SoC/自测脚本) |
与 i2c-slave-eeprom.c 对比:
| 维度 | slave-eeprom | slave-testunit |
|---|---|---|
| 目的 | 模拟 EEPROM 存储 | 触发主机驱动测试用例 |
| 用户接口 | sysfs slave-eeprom |
仅 I2C 寄存器协议 |
| Master 行为 | 无 | work 中可 i2c_transfer |
| 读默认 | EEPROM 数据 | 版本号 0x01 |
5. 寄存器与命令协议
5.1 四个写寄存器(须完整写入 4 字节触发,Block Proc Call 除外)
| 偏移 | 名称 | 含义 |
|---|---|---|
TU_REG_CMD (0) |
CMD | 测试命令编号 |
TU_REG_DATAL (1) |
DATAL | 参数低字节 |
TU_REG_DATAH (2) |
DATAH | 参数高字节 |
TU_REG_DELAY (3) |
DELAY | 延迟 = DELAY × 10ms 后执行 |
实例化示例:
1 | echo slave-testunit 0x1030 > /sys/bus/i2c/devices/i2c-0/new_device |
(0x1030 = 0x1000 + 7 位地址 0x30,与从机 new_device 约定一致。)
i2c-tools 通用写法:
1 | i2cset -y <bus> <addr> <CMD> <DATAL> <DATAH> <DELAY> i |
5.2 命令列表
| CMD | 名称 | 需要 Master 模式 | DATAL / DATAH | 行为 |
|---|---|---|---|---|
0x01 |
TU_CMD_READ_BYTES |
是 | DATAL=从地址(7bit),DATAH=读长度 | work 中对 adapter 发起 读传输,测多主机 |
0x02 |
TU_CMD_HOST_NOTIFY |
是 | 状态字低/高字节(Linux 侧可忽略) | 向地址 0x08 写 3 字节 SMBus Host Notify |
0x03 |
TU_CMD_SMBUS_BLOCK_PROC_CALL |
否(从机读侧模拟) | DATAL=1,DATAH=返回字节数 | 从机在后续 读事务 中模拟 Block Process Call 响应 |
TU_CMD >= TU_NUM_CMDS 时从机回调返回 -EINVAL(主机应 NACK)。
保留: CMD 0x00 为 NOOP(未实现)。
6. i2c_slave_testunit_slave_cb() 详解
6.1 I2C_SLAVE_WRITE_REQUESTED
- 若
TU_FLAG_IN_PROCESS已置位 →-EBUSY(上一命令未结束); - 清零
regs[],reg_idx = 0。
6.2 I2C_SLAVE_WRITE_RECEIVED
- 忙时返回
-EBUSY; - 按序写入
regs[reg_idx],reg_idx++; - 写满 4 寄存器后校验
regs[TU_REG_CMD] < TU_NUM_CMDS,否则-EINVAL; - 超出 4 字节 →
-EMSGSIZE。
6.3 I2C_SLAVE_STOP
- 若
reg_idx == TU_NUM_REGS(4):- 置
TU_FLAG_IN_PROCESS; queue_delayed_work(system_long_wq, delay = 10ms * regs[TU_REG_DELAY]);
- 置
reg_idx = 0(避免后续读事务重复排队;不清 regs,work 仍需要)。
6.4 读路径
| 场景 | *val |
|---|---|
| 普通读 | TU_CUR_VERSION (0x01) |
Block Proc Call 模拟 (reg_idx==3 且 CMD=0x03 且 DATAL=1) |
递减序列:先返回 DATAH,每次 READ_PROCESSED 后 DATAH-- |
Block Proc Call 时主机随后发起读;从机按 SMBus 语义在首字节放 长度,后续字节为 length-1 … 0(由 DATAH 递减实现,见内核文档 i2ctransfer 示例)。
7. i2c_slave_testunit_work() — 测试执行
在延迟结束后运行,根据 TU_REG_CMD 构造 i2c_msg 并 i2c_transfer(tu->client->adapter, &msg, 1)。
7.1 TU_CMD_READ_BYTES
1 | msg.addr = tu->regs[TU_REG_DATAL]; /* 7 位从地址 */ |
用于验证:被测主机驱动 与 testunit 发起的读 同时访问总线时的仲裁/忙处理。
示例(文档):
1 | i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i # 50ms 后从 0x50 读 128 字节 |
7.2 TU_CMD_HOST_NOTIFY
1 | msg.addr = 0x08; |
向 SMBus Host Notify 地址 发送通知,测试主机侧 Host Notify 处理路径(与 i2c-core-base.c / i2c-smbus.c 中 Host Notify 相关)。
7.3 完成与错误
i2c_transfer返回 0 条消息时转为-EIO;- 失败
dev_err打印 CMD 与 errno; clear_bit(TU_FLAG_IN_PROCESS),允许下一条命令。
8. Probe / Remove
8.1 i2c_slave_testunit_probe()
1 | devm_kzalloc(testunit_data) |
使用 probe_new(无 id 参数,匹配靠 id_table 在绑定前完成)。
8.2 i2c_slave_testunit_remove()
1 | cancel_delayed_work_sync(&tu->worker) |
8.3 模块
- 单一型号:
{ "slave-testunit", 0 }; - 无
of_match_table— 典型通过new_device创建,非 DTcompatible。
9. 与 I2C 子系统的关系
| 组件 | 关系 |
|---|---|
i2c-core-slave.c |
i2c_slave_register / i2c_slave_event |
i2c-core-base.c |
work 中 i2c_transfer、Host Notify 消费端 |
i2c-core-smbus.c |
Block Proc Call 常经 SMBus 模拟;需 I2C_M_RECV_LEN |
| 主机驱动 | 必须 reg_slave;READ_BYTES/HOST_NOTIFY 还需 同一 adapter 可作 Master |
10. RK3588 平台说明
10.1 默认不可用原因
CONFIG_I2C_SLAVE_TESTUNIT未开 → 驱动不编译;i2c-rk3x仅实现 Master(master_xfer),无reg_slave;- 即使强行加载,
i2c_slave_register()返回-EOPNOTSUPP; - 测试用例依赖的 Slave 期间再 Master 发送 在 rk3x 上 无硬件/驱动支持。
10.2 若用于验证 RK3588 主机驱动
需在 支持 I2C Slave(及 preferably 主从切换) 的平台上运行 testunit,或使用 USB-I2C 适配器 + 另一套 slave 控制器 作为对端;不能 把 testunit 挂在 rk3x 控制器上作为完整方案。
10.3 与 slave-eeprom 选型
| 需求 | 选用 |
|---|---|
| 模拟 EEPROM、用户空间读写镜像 | i2c-slave-eeprom.c |
| 主机驱动回归、多主/Notify/Block Proc Call | i2c-slave-testunit.c(本文) |
11. 测试示例摘要(来自内核文档)
多主读字节:
1 | i2cset -y 0 0x30 0x01 0x50 0x80 0x05 i |
Host Notify:
1 | i2cset -y 0 0x30 0x02 0x42 0x64 0x01 i |
Block Process Call(i2ctransfer ≥ 4.2):
1 | i2ctransfer -y 0 w3@0x30 0x03 0x01 0x10 r? |
12. 并发与状态标志
| 标志 | 含义 |
|---|---|
TU_FLAG_IN_PROCESS |
命令已排队或 work 执行中;新写/新写请求返回 -EBUSY |
DELAY 期间 主机写入会被拒绝,需等待 work 完成。
13. 源码结构速查(约 193 行)
1 | L17-44 版本、命令/寄存器/标志、testunit_data |
14. 结论
i2c-slave-testunit.c 是 I2C 从机框架的测试专用后端:
- 通过 4 字节寄存器协议 远程触发 READ_BYTES / HOST_NOTIFY / SMBUS_BLOCK_PROC_CALL;
- 在 workqueue 中可切换为 Master 发送,用于 多主机与 SMBus 特性 验证;
- 从机读路径提供 版本号 与 Block Proc Call 响应模拟;
- 依赖
CONFIG_I2C_SLAVE与主机reg_slave,不保证稳定 ABI; - RK3588 rk3x 默认栈不支持,属开发与它平台主机驱动测试工具。
与 rk3588-kernel-6.1-i2c-slave-eeprom.c功能详细分析_zh.md 同属从机后端,但面向 总线主机驱动 QA 而非存储仿真。
15. 推荐阅读顺序
Documentation/i2c/slave-testunit-backend.rst— 命令与示例i2c-slave-testunit.c—slave_cb、workDocumentation/i2c/slave-interface.rst— 从机事件语义i2c-core-slave.c— 注册与事件投递i2c-core-smbus.c— Block 读与I2C_M_RECV_LEN
16. 相关文档
rk3588-kernel-6.1-i2c-slave-eeprom.c功能详细分析_zh.mdrk3588-kernel-6.1-i2c-core-slave.c功能详细分析_zh.mdrk3588-kernel-6.1-i2c-core-smbus.c功能详细分析_zh.mdrk3588-kernel-6.1-i2c-dev.c功能详细分析_zh.md
文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/i2c-slave-testunit.c 分析。
正在加载留言…