RK3588 kernel-6.1 drivers/i2c 总线架构分析
1. 范围说明
本文聚焦目录:
rk3588/kernel-6.1/drivers/i2c
分析目标:
- I2C 子系统在 Linux 设备模型中的位置
i2c-core的总线、适配器、驱动、传输调用链- RK3588 所在 Rockchip I2C 主控驱动(
i2c-rk3x.c)实现特点 - 面向开发与排障的实践方法
2. 目录分层与模块组织
从 drivers/i2c/Makefile 可以看出四层结构:
- 核心层:
i2c-core-base.c、i2c-core-smbus.c、i2c-core-of.c、i2c-core-acpi.c
提供总线注册、设备/驱动匹配、传输入口、OF/ACPI 枚举与 SMBus 扩展能力。 - 用户态接口层:
i2c-dev.c
对外暴露/dev/i2c-*,用于用户态工具(如 i2c-tools)访问总线。 - 拓扑扩展层:
i2c-mux.c+muxes/
把多路复用后的每条下游链路抽象成独立i2c_adapter。 - 控制器驱动层:
busses/
各 SoC I2C Host Controller 驱动,Rockchip 关键文件是busses/i2c-rk3x.c。
这说明 I2C 架构本质上是:core 定义规则 + controller 驱动提供 algorithm + client 驱动按地址挂载到 adapter。
3. I2C 在 Linux 设备模型中的角色
在 i2c-core-base.c 中,I2C 总线对象是 i2c_bus_type,并注册了:
.match:匹配i2c_client与i2c_driver.probe:调用 client 驱动探测逻辑.remove:解绑时回收
因此,I2C 也是标准 bus_type,在系统里遵循统一的 device model 生命周期。
可以把三类对象理解为:
i2c_adapter:控制器实例(一条物理/逻辑总线)i2c_client:该总线上的从设备抽象(地址 + 属性)i2c_driver:具体芯片驱动(如触摸、PMIC、传感器)
4. 注册与绑定主链路
4.1 控制器侧(Host)注册
控制器驱动完成硬件初始化后,调用:
i2c_add_adapter()(动态 bus id)i2c_add_numbered_adapter()(固定 bus id)
两者最终进入 i2c_register_adapter(),由 core 把 adapter 纳入 I2C 总线并触发设备侧匹配。
4.2 客户端驱动(Client)注册
I2C client 驱动通过 i2c_register_driver() 注册。
完成后 core 会尝试把该驱动与现有 i2c_client 逐个匹配。
4.3 匹配结果
匹配成功后进入 i2c_device_probe(),再调用具体 client 驱动的 probe;
卸载走 i2c_device_remove()。
5. 传输调用链(最关键)
I2C 数据传输链路分两层:
i2c_transfer()/__i2c_transfer():core 通用入口,做重试、锁、trace、能力检查等。adapter->algo->master_xfer():具体控制器驱动实现,真正触发硬件收发。
也就是:协议框架在 core,时序细节在 bus controller 驱动。
对 RK3588 来说,master_xfer() 对应 i2c-rk3x.c 中的 rk3x_i2c_xfer()。
6. Rockchip I2C 控制器驱动架构(i2c-rk3x.c)
i2c-rk3x.c 是平台驱动(platform_driver),通过 of_match_table 适配多代 Rockchip SoC。
该驱动对 RK3588 这类平台的价值是:把 SoC 寄存器/中断/时钟差异封装成统一 I2C adapter 能力。
6.1 驱动入口与资源初始化
rk3x_i2c_probe() 主要做:
- 解析 bus id(OF alias / ACPI UID)
- 解析 timing(
i2c_parse_fw_timings) - 映射寄存器、申请 IRQ、获取时钟与复位
- 设置
i2c_adapter字段(algo、retries、nr、parent等) - 调
i2c_add_numbered_adapter()向 core 注册
这条路径体现了 Linux 控制器驱动通用模板:platform probe -> resource init -> adapter register。
6.2 i2c_algorithm 回调实现
Rockchip 驱动提供:
.master_xfer = rk3x_i2c_xfer.master_xfer_atomic = rk3x_i2c_xfer_polling.functionality = rk3x_i2c_func
其中 rk3x_i2c_xfer_common() 是核心传输函数,负责:
- 消息分段处理(支持组合写读)
- 中断模式与 polling 模式切换
- 超时、NACK、STOP、恢复与错误上报
6.3 状态机与中断驱动执行
驱动内部状态机:
STATE_IDLESTATE_WRITESTATE_READSTATE_STOP
IRQ 入口 rk3x_i2c_irq() 根据状态分发到:
rk3x_i2c_handle_write()rk3x_i2c_handle_read()rk3x_i2c_handle_stop()
这是典型主控 I2C 驱动范式:寄存器配置 + 中断推进状态机 + waitqueue 同步上层调用线程。
6.4 FIFO 与 DMA 双通路
驱动根据消息长度/方向选择:
- FIFO 路径(短消息)
- DMA 路径(较长消息,含 bounce buffer 和 DMA map/unmap)
相关逻辑在:
rk3x_i2c_start_fifo()rk3x_i2c_start_dma()rk3x_i2c_complete_dma()
这套实现兼顾低延迟与吞吐量。
6.5 时序计算与动态时钟适配
Rockchip 驱动提供 v0/v1 两套 timing 计算函数:
rk3x_i2c_v0_calc_timings()rk3x_i2c_v1_calc_timings()
并在时钟变化通知中重算分频:
rk3x_i2c_clk_notifier_cb()rk3x_i2c_adapt_div()
这保证 DVFS 或时钟调整后,I2C 仍满足标准/快速/快速+模式时序约束。
6.6 SoC 差异封装点
通过 struct rk3x_i2c_soc_data 抽象差异:
grf_offsetcalc_timingsdma_control
并在 rk3x_i2c_match[] 里按 compatible 选择具体实现。
这种做法能让同一驱动覆盖 rk3066/rk3399/rv1126 等多代硬件。
7. I2C 设备树与总线编号关系
该驱动通过 of_alias_get_id(np, "i2c") 获取 bus id,并赋给 adap.nr,最终对应用户态 i2c-X 编号。
所以系统里 i2c-0/i2c-1/... 稳定性很大程度取决于 DTS alias 配置。
此外,i2c_parse_fw_timings() 会读取固件里的时序属性(如 bus 频率、上升下降沿参数),直接影响硬件分频计算结果。
8. 用户态接口与调试入口
8.1 用户态接口
若使能 CONFIG_I2C_CHARDEV,i2c-dev.c 会创建 /dev/i2c-*。
这给 bring-up 和问题定位提供了快速验证通道。
8.2 常用排障思路
- 确认枚举
- 适配器是否注册成功(
i2c_add_numbered_adapter路径) /dev/i2c-*是否出现(启用I2C_CHARDEV)
- 适配器是否注册成功(
- 确认时序
i2c,clk-rate与硬件支持模式是否匹配- 查看是否出现 timeout / NACK / SCL hold 报错
- 确认中断与状态机
- IRQ 是否触发
- 是否卡在
STATE_STOP或等待队列超时
- 确认总线拓扑
- 是否经过 mux,目标设备是否在正确下游 adapter
9. 面向驱动开发的结论
在 RK3588 kernel-6.1 中,I2C 架构可以总结为:
- Core 负责“总线规则”:注册、匹配、生命周期与统一 API。
- Controller 驱动负责“硬件执行”:时序、状态机、中断/DMA、容错恢复。
- Client 驱动负责“芯片语义”:寄存器协议、功能逻辑、PM/中断等。
如果你要新增一个 I2C 设备驱动,优先关注的是 client 驱动;
如果你遇到“整条总线异常”,则应回到 i2c-rk3x.c 的传输状态机、时钟时序与中断链路。
10. 推荐阅读顺序(只看关键文件)
drivers/i2c/i2c-core-base.c(总线/注册/传输主流程)drivers/i2c/i2c-core-of.c(OF 枚举)drivers/i2c/i2c-dev.c(用户态接口)drivers/i2c/busses/i2c-rk3x.c(Rockchip 控制器实现)drivers/i2c/muxes/*+drivers/i2c/i2c-mux.c(复杂拓扑场景)
一句话:RK3588 的 I2C 是“Linux 通用 I2C core + Rockchip rk3x 控制器状态机实现”的组合架构。
正在加载留言…