RK3588 kernel-6.1/drivers/i2c/i2c-core-slave.c 功能详细分析
1. 文档范围与说明
路径说明: 用户表述为「i2c-core-slave.c 目录」,实际为 单个源文件:
rk3588/kernel-6.1/drivers/i2c/i2c-core-slave.c(约 128 行)
编译关系: 仅在启用 CONFIG_I2C_SLAVE 时编入 i2c-core.ko:
1 | i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o |
文档保存路径: linuxDoc/drivers/i2c/
定位: I2C 子系统的 从机(Slave)模式核心薄层:在已有 i2c_client 与 i2c_adapter 框架上,提供 注册/注销从机回调、向从机后端投递总线事件、以及 从 DT 检测控制器是否应工作在从机模式 的通用 API。具体从机行为由 后端驱动(如 i2c-slave-eeprom.c)和 主机控制器驱动的 reg_slave/unreg_slave 实现。
与 RK3588 的关系:
| 项目 | RK3588 典型情况 |
|---|---|
CONFIG_I2C_SLAVE |
Rockchip arm64 defconfig 通常未启用 → 本文件 默认不链接 |
i2c-rk3x.c |
未实现 algo->reg_slave / unreg_slave |
| 产品角色 | SoC I2C 控制器作 主设备(Master) 访问传感器/PMIC 等 |
若需让 RK3588 Linux 作为 I2C 从设备 被外部主机访问,除打开 CONFIG_I2C_SLAVE 外,还须 硬件与 i2c-rk3x 驱动支持从机模式(当前树中未提供)。本文仍完整说明本文件机制及与 DT、其它驱动的衔接。
2. 功能总览
| 符号 | 导出 | 作用 |
|---|---|---|
i2c_slave_register() |
GPL | 绑定 slave_cb,调用 adapter reg_slave |
i2c_slave_unregister() |
GPL | 调用 adapter unreg_slave,清除回调 |
i2c_slave_event() |
GPL | 主机驱动收到总线活动时调用,转发至 slave_cb |
i2c_detect_slave_mode() |
GPL | 扫描 DT 子节点 reg 是否含 I2C_OWN_SLAVE_ADDRESS |
Tracepoint: trace/events/i2c_slave.h(trace_i2c_slave),在 i2c_slave_event() 中可选记录。
3. I2C 从机模式架构
1 | 外部 I2C Master Linux SoC |
内核文档:Documentation/i2c/slave-interface.rst。
要点: i2c-core-slave.c 不处理硬件寄存器;仅协调 adapter 算法 与 从机后端回调。
4. 数据结构与事件类型(include/linux/i2c.h)
4.1 回调类型
1 | typedef int (*i2c_slave_cb_t)(struct i2c_client *client, |
struct i2c_client 含成员 i2c_slave_cb_t slave_cb(CONFIG_I2C_SLAVE 时有效)。
4.2 事件枚举
| 事件 | 含义(简述) |
|---|---|
I2C_SLAVE_WRITE_REQUESTED |
主机发起写:地址+写位已匹配,尚未收数据 |
I2C_SLAVE_WRITE_RECEIVED |
收到一字节写数据(val 为数据) |
I2C_SLAVE_READ_REQUESTED |
主机发起读:应填充首字节到 *val |
I2C_SLAVE_READ_PROCESSED |
上一读字节已发出,准备下一字节 |
I2C_SLAVE_STOP |
检测到 STOP(或等效结束) |
后端在 READ_REQUESTED / READ_PROCESSED 中通过 *val 提供读出数据;WRITE_RECEIVED 从 *val 取写入数据。详见 slave-interface.rst 中 mandatory/optional 说明。
5. i2c_slave_register() — 注册从机
1 | int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb); |
5.1 流程
1 | 参数检查 (client, slave_cb) |
5.2 注意事项
| 检查 | 行为 |
|---|---|
未设置 I2C_CLIENT_SLAVE |
仅警告,仍继续注册(可能与其它 master 地址冲突) |
无 reg_slave |
-EOPNOTSUPP |
| 10 位地址 | 跳过 strict 7 位检查 |
谁调用: 从机后端在 probe 中调用,例如 i2c-slave-eeprom.c、i2c-slave-testunit.c;i2c-smbus.c 中 Host Notify 从机路径(CONFIG_I2C_SLAVE)。
6. i2c_slave_unregister() — 注销从机
1 | int i2c_slave_unregister(struct i2c_client *client); |
对称调用 adap->algo->unreg_slave(client),成功则 client->slave_cb = NULL。无 unreg_slave 时返回 -EOPNOTSUPP。
调用时机: 后端驱动 remove、或 Host Notify 客户端拆除时。
7. i2c_slave_event() — 事件投递
1 | int i2c_slave_event(struct i2c_client *client, |
- 调用
client->slave_cb(client, event, val); - 若启用 trace,记录
trace_i2c_slave(client, event, val, ret); - 返回值供 总线驱动 决定 ACK/NACK 等(依控制器实现)。
调用者: 仅 实现了从机模式的 I2C 主机驱动(如 i2c-stm32f7.c、i2c-imx.c、i2c-rcar.c 等在 ISR/状态机中调用)。
示例(STM32):
1 | i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value); |
8. i2c_detect_slave_mode() — DT 从机模式检测
1 | bool i2c_detect_slave_mode(struct device *dev); |
8.1 逻辑
若 dev->of_node 存在,遍历其 直接子节点,读取 reg:
1 | if (reg & I2C_OWN_SLAVE_ADDRESS) |
I2C_OWN_SLAVE_ADDRESS 定义于 include/dt-bindings/i2c/i2c.h:(1 << 30)。
8.2 与 i2c-core-of.c 的配合
of_i2c_get_board_info() 解析子设备时:
1 | if (addr & I2C_OWN_SLAVE_ADDRESS) { |
- 子设备 带
I2C_OWN_SLAVE_ADDRESS→ 创建的 client 带I2C_CLIENT_SLAVE; i2c_detect_slave_mode(dev)在 控制器设备dev上扫描子节点,判断整路 I2C 是否配置为从机控制器模式(任一子节点声明 own-slave 地址即返回 true)。
8.3 使用方
| 驱动 | 用途 |
|---|---|
i2c-designware-core |
i2c_dw_configure() 选择 master/slave 硬件配置 |
i2c-at91-core |
dev->slave_detected 标志 |
RK3588 i2c-rk3x: 源码中 未调用 i2c_detect_slave_mode()。
8.4 ACPI
1 | } else if (IS_BUILTIN(CONFIG_ACPI) && ACPI_HANDLE(dev)) { |
ACPI 从机检测 尚未实现,恒返回 false。
9. Kconfig 与相关模块
9.1 CONFIG_I2C_SLAVE
1 | config I2C_SLAVE |
依赖链:
1 | CONFIG_I2C_SLAVE=y |
9.2 从机后端驱动(同目录,非本文)
| 文件 | 作用 |
|---|---|
i2c-slave-eeprom.c |
模拟 I2C EEPROM,用户空间经 sysfs 读写“存储” |
i2c-slave-testunit.c |
测试用从机,配合总线 master 测试多主机、Host Notify 等 |
9.3 i2c-smbus.c 中的从机用法
启用 CONFIG_I2C_SLAVE 时,SMBus Host Notify 可注册从机回调 i2c_slave_host_notify_cb,在收到主机写通知时置位 status->host_notify 并 wake_up。
10. 主机驱动支持情况(本树)
algo->reg_slave / unreg_slave 在部分 busses/ 驱动中实现,例如:
i2c-stm32f7.ci2c-imx.ci2c-rcar.ci2c-pxa.ci2c-npcm7xx.ci2c-mlxbf.ci2c-emev2.c- DesignWare 系列(配合
i2c_detect_slave_mode配置 master/slave)
未实现(RK3588 相关):
i2c-rk3x.c— 无reg_slave/unreg_slave
因此即使打开 CONFIG_I2C_SLAVE,在 RK3588 上对 rk3x 控制器 调用 i2c_slave_register() 仍会得到 -EOPNOTSUPP。
11. Device Tree 与实例化
11.1 从机后端设备节点
从机后端仍是标准 I2C client,在 DT 中挂在某条 I2C 总线下,且 reg 需体现从机地址。文档说明实例化时地址空间需加 0x1000 偏移(历史约定,与 I2C_OWN_SLAVE_ADDRESS 标志配合使用)。
用户空间示例(slave-interface.rst):
1 | echo slave-24c02 0x1064 > /sys/bus/i2c/devices/i2c-1/new_device |
(0x1064 = 0x1000 + 7 位地址 0x64)
11.2 控制器“从机模式”检测示例
若某 DT 设计让 Linux 控制器监听固定地址,子节点可写:
1 | linux-i2c-slave@50 { |
i2c_detect_slave_mode(&controller->dev) 返回 true → DesignWare 等驱动配置为 硬件从机。
RK3588 产品 DTS 极少 这样配置;常见为 SoC 作 master 访问外设。
12. 与 Master 路径对比
| 维度 | Master(RK3588 常态) | Slave(本文件) |
|---|---|---|
| 配置 | 默认 | CONFIG_I2C_SLAVE |
| 传输 API | i2c_transfer() / SMBus |
无主动 transfer;被动 i2c_slave_event |
| Adapter algo | master_xfer |
reg_slave / unreg_slave |
| DT 标志 | reg = <0xNN> |
reg 含 bit30 或实例化 0x1xxx |
| RK3x | 支持 | 不支持 |
13. 源码全文结构(约 128 行)
1 | L17-18 trace/events/i2c_slave.h |
无其它隐藏逻辑;文件刻意保持 薄封装,便于总线驱动与后端解耦。
14. 启用与调试(非 RK3588 默认)
14.1 内核配置
1 | CONFIG_I2C_SLAVE=y |
重新编译 i2c-core 及所需 bus 驱动、后端模块。
14.2 验证 API 是否编入
1 | grep i2c_slave_register /proc/kallsyms # 需 CONFIG_KALLSYMS |
14.3 Trace
1 | # 若配置了 tracepoint |
14.4 常见错误
| 现象 | 原因 |
|---|---|
-EOPNOTSUPP on register |
adapter 无 reg_slave(rk3x) |
| 地址冲突警告 | 未设 I2C_CLIENT_SLAVE 且与其它 client 同址 |
invalid address |
7 位保留地址未通过 strict 检查 |
15. RK3588 结论与扩展方向
i2c-core-slave.c提供 Linux I2C 从机框架的 4 个核心 API,本身仅约 128 行。- 默认 Rockchip 内核 通常 不启用
CONFIG_I2C_SLAVE,且 rk3x 无硬件从机钩子,故 RK3588 量产路径 不依赖 本文件。 - 若产品需要 SoC 作 I2C 从设备(例如被 MCU/FPGA 访问),需要:
- 确认 RK3588 I2C IP 是否支持 slave 模式(数据手册);
- 在
i2c-rk3x.c中实现reg_slave/unreg_slave及中断路径中调用i2c_slave_event; - 打开
CONFIG_I2C_SLAVE并编写或复用从机后端驱动。
16. 推荐阅读顺序
i2c-core-slave.c— 四个导出函数Documentation/i2c/slave-interface.rst— 事件语义与后端编写i2c-slave-eeprom.c— 完整后端示例drivers/i2c/busses/i2c-stm32f7.c—reg_slave+i2c_slave_event调用示例i2c-core-of.c—I2C_OWN_SLAVE_ADDRESS解析
17. 相关文档
rk3588-kernel-6.1-i2c-core-base.c功能详细分析_zh.mdrk3588-kernel-6.1-i2c-core-of.c功能详细分析_zh.mdrk3588-kernel-6.1-drivers-i2c-busses目录功能详细分析_zh.mdrk3588-kernel-6.1-drivers-i2c目录功能详细分析_zh.md
文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/i2c-core-slave.c 分析。
正在加载留言…