RK3588 kernel-6.1/drivers/i2c 目录功能详细分析
1. 文档范围
本文对以下目录做功能级详细分析:
- 源码路径:
rk3588/kernel-6.1/drivers/i2c - 文档路径:
linuxDoc/drivers/i2c/
分析目标:
- 说明该目录在 Linux 内核中的职责与分层结构;
- 逐项解释核心文件、算法层、复用器层、总线控制器层的具体功能;
- 重点说明 RK3588 平台 使用的 Rockchip I2C 控制器驱动(
i2c-rk3x.c); - 给出设备树绑定、传输调用链与排障思路。
同目录已有
rk3588-kernel-6.1-i2c总线架构分析.md,侧重架构与调用链;本文在其基础上扩展目录全貌与各模块职责。
2. 目录总览
drivers/i2c 共约 177 个源文件,按 Makefile 分为五层:
| 层级 | 路径/文件 | 主要职责 |
|---|---|---|
| 核心层 | i2c-core-*.c, i2c-boardinfo.c |
总线注册、设备/驱动匹配、传输入口、OF/ACPI、SMBus 协议、从模式框架 |
| 用户态接口 | i2c-dev.c |
/dev/i2c-* 字符设备,供 i2c-tools 等用户程序访问 |
| 拓扑扩展 | i2c-mux.c, muxes/ |
I2C 多路复用,将每条下游段抽象为独立 adapter |
| 算法层 | algos/ |
软件位带(bit-banging)等通用传输算法 |
| 控制器驱动 | busses/(约 140+ 个 .c 文件) |
各 SoC/PCI 的 I2C Host Controller 硬件驱动 |
| 辅助/测试 | i2c-stub.c, i2c-slave-*.c, i2c-smbus.c |
测试桩、从设备模拟、SMBus Alert/Host Notify |
整体架构可概括为:
1 | 用户态 (i2c-tools / 应用) |
3. 构建与 Kconfig 配置体系
3.1 顶层 Makefile
1 | obj-$(CONFIG_I2C) += i2c-core.o |
说明:
i2c-core是必选核心模块(CONFIG_I2C),其余按 Kconfig 裁剪;algos/、busses/、muxes/始终进入编译树,具体.o由各自子目录Makefile+Kconfig决定;- RK3588 板级配置通常使能:
I2C、I2C_CHARDEV、I2C_MUX、OF、I2C_RK3X(或等效选项名)。
3.2 主要 Kconfig 选项
| 选项 | 功能 |
|---|---|
I2C |
启用 I2C 子系统核心 |
I2C_CHARDEV |
用户态 /dev/i2c-* 接口 |
I2C_MUX |
多路复用核心框架 |
I2C_SMBUS |
SMBus Alert / Host Notify 等扩展协议 |
I2C_SLAVE |
内核作为 I2C 从设备(需控制器支持) |
I2C_BOARDINFO |
静态 board info 注册(非 DT 平台) |
I2C_COMPAT |
旧版用户态兼容(class 设备) |
I2C_STUB |
测试用 SMBus 桩驱动 |
I2C_DEBUG_* |
核心/算法/总线调试日志 |
4. 核心层(Core)功能详解
核心由 i2c-core 复合模块组成,是所有 I2C 操作的统一入口。
4.1 i2c-core-base.c — 总线与传输主框架
主要功能:
| 功能域 | 代表接口/机制 | 说明 |
|---|---|---|
| 总线类型 | i2c_bus_type |
注册 .match、.probe、.remove,连接 client 与 driver |
| Adapter 注册 | i2c_add_adapter()、i2c_add_numbered_adapter()、i2c_del_adapter() |
控制器向 core 注册/注销 |
| 设备注册 | i2c_new_client_device()、i2c_unregister_device() |
在 adapter 上创建 client |
| 驱动注册 | i2c_register_driver() |
client 驱动挂到总线 |
| 传输入口 | i2c_transfer()、__i2c_transfer() |
加锁、重试、trace、调用 algo->master_xfer |
| SMBus 封装 | i2c_smbus_read_byte() 等(部分在 core-smbus) |
通过 I2C 消息模拟 SMBus |
| 地址检查 | i2c_check_7bit_addr_validity_strict() |
7 位地址合法性 |
| 总线恢复 | i2c_recover_bus()、i2c_generic_scl_recovery() |
SCL 卡死时 GPIO/bit-bang 恢复 |
| 锁机制 | i2c_lock_bus() / i2c_unlock_bus() |
根 adapter 与 mux 父子锁 |
| Host Notify | i2c_handle_smbus_host_notify() |
SMBus 主机通知 IRQ 域 |
| 时序解析 | i2c_parse_fw_timings() |
从 DT 读取 clock-frequency、rise/fall 等 |
| Debugfs | i2c_debugfs_root |
调试节点 |
| Trace | trace/events/i2c.h |
ftrace 跟踪传输 |
传输调用链(内核 client 驱动路径):
1 | client 驱动 (如 xxx_probe 里读写寄存器) |
4.2 i2c-core-smbus.c — SMBus 协议实现
- 在 I2C 消息之上实现 SMBus 块读写、PEC(CRC8)、Quick Command 等;
- 若 adapter 未实现
smbus_xfer,则由 core 用 I2C 消息模拟 SMBus 时序; - 被
hwmon、电源管理、传感器等大量驱动依赖。
4.3 i2c-core-of.c — Device Tree 支持
| 函数 | 功能 |
|---|---|
of_i2c_get_board_info() |
从 DT 节点解析 reg(地址)、compatible(type)、host-notify、wakeup-source 等 |
of_i2c_register_devices() |
adapter 注册后,扫描子节点并 i2c_new_client_device() |
i2c_of_match_device() |
OF 匹配表支持 |
RK3588 上绝大多数 I2C 从设备(触摸、PMIC、Codec)通过 DT 子节点自动枚举,不依赖 i2c_register_board_info()。
4.4 i2c-core-acpi.c — ACPI 支持
- 在 x86/ACPI 平台解析 ACPI I2C 设备;
- RK3588 为 ARM64 + DT,通常不编译或未使用此路径。
4.5 i2c-core-slave.c — 从模式框架
i2c_slave_register()/i2c_slave_unregister();- 要求
adapter->algo->reg_slave由控制器实现; - RK3588 的
i2c-rk3x.c以实现 Master 为主,从模式非主要用途。
4.6 i2c-boardinfo.c — 静态板级信息
i2c_register_board_info(busnum, info, len):在 arch 初始化阶段静态声明设备;- 多用于无 DT 的旧 ARM/x86 板;RK3588 以 DT 为主,此路径较少使用。
4.7 i2c-core.h
- core 内部头文件,声明
__i2c_board_list、i2c_devinfo等仅 core 使用的符号。
5. 用户态接口层
5.1 i2c-dev.c — /dev/i2c-*
功能:
- 每个已注册的
i2c_adapter对应一个字符设备i2c-N(N =adap->nr); - 通过
ioctl支持:I2C_RDWR:组合读写;I2C_SMBUS:SMBus 访问;I2C_FUNCS:查询 adapter 能力;I2C_SLAVE/I2C_SLAVE_FORCE:绑定从地址;I2C_RETRIES、I2C_TIMEOUT等;
- 用户态工具:
i2cdetect、i2cget、i2cset、i2cdump(i2c-tools 包)。
典型用途: bring-up 阶段探测总线、读写 EEPROM、验证硬件连线。
6. SMBus 扩展模块
6.1 i2c-smbus.c
在 i2c-core-smbus 基础协议之上,增加:
| 机制 | 功能 |
|---|---|
| SMBus Alert | 从设备拉 Alert# 线,ARA(Alert Response Address)轮询,调用各 driver 的 .alert() |
| SMBus Host Notify | 从设备向主机发通知,通过 host-notify DT 属性与 IRQ 域映射 |
依赖 CONFIG_I2C_SMBUS,PC 服务器平台更常见;嵌入式 SoC 按需使能。
7. I2C 多路复用(Mux)层
7.1 i2c-mux.c — 复用框架
设计思想: 一条物理 I2C 上挂 MUX 芯片,每个通道对应一条逻辑总线。
- 为每个 channel 创建子
i2c_adapter; select(chan)/deselect(chan)切换硬件通道;- 传输时:
select→i2c_transfer(parent)→deselect; - 支持 多级 mux(mux 后再挂 mux)。
7.2 muxes/ 目录 — 具体 MUX 芯片驱动
| 驱动文件 | 芯片/机制 | 功能 |
|---|---|---|
i2c-mux-pca954x.c |
NXP PCA954x/984x | 最常见 I2C 开关/多路器 |
i2c-mux-pca9541.c |
PCA9541 | 主选择器(双主仲裁场景) |
i2c-mux-gpio.c |
GPIO | 用 GPIO 选通通道 |
i2c-mux-reg.c |
寄存器 | 写寄存器位选通 |
i2c-mux-pinctrl.c |
pinctrl | 通过引脚复用切换 I2C 信号路由 |
i2c-demux-pinctrl.c |
pinctrl | 反向:多主机选路 |
i2c-mux-gpmux.c |
MUX 子系统 | 通用 MUX 控制器抽象 |
i2c-mux-ltc4306.c |
LTC4306/5 | 带 rise time 加速的开关 |
i2c-mux-mlxcpld.c |
Mellanox CPLD | 服务器 CPLD 控制 mux |
i2c-arb-gpio-challenge.c |
GPIO | 多主 GPIO 仲裁 |
RK3588 板子上若多个同地址设备分属不同通道,会在 DTS 中出现 i2c-mux-pca954x 等节点,用户态会看到 i2c-5、i2c-6 等多个 adapter。
8. 算法层(algos/)
用于没有专用硬件控制器、或硬件仅提供 GPIO 线位的场景。
| 文件 | 功能 |
|---|---|
i2c-algo-bit.c |
软件位带:通过 setsda/setscl/getsda/getscl 回调 bit 级操作 SDA/SCL |
i2c-algo-pca.c |
Philips PCA9564 等并行总线桥 |
i2c-algo-pcf.c |
PCF8584 适配 |
常与 i2c-gpio.c(busses/)配合:用两个 GPIO 模拟 I2C 总线。
RK3588 内置硬件 I2C 控制器,正常产品路径不走 algo-bit,但 bring-up 或特殊板可能仍用 GPIO I2C。
9. 总线控制器层(busses/)
9.1 规模与分类
- 约 140 个
.c源文件; Kconfig中约 128 个config I2C_*选项;- 按平台/总线类型可粗分为:
| 类别 | 代表驱动 | 典型平台 |
|---|---|---|
| Rockchip | i2c-rk3x.c |
RK3588/RK3399/RK3568 等 |
| Synopsys DesignWare | i2c-designware-*.c |
Intel、部分 ARM SoC |
| NXP/Freescale | i2c-imx.c, i2c-mpc.c |
i.MX、PowerPC |
| Samsung | i2c-exynos5.c, i2c-s3c2410.c |
Exynos |
| Qualcomm | i2c-qup.c, i2c-qcom-geni.c |
高通 |
| Broadcom | i2c-bcm2835.c, i2c-bcm-iproc.c |
树莓派等 |
| PCI/ACPI PC | i2c-i801.c, i2c-piix4.c |
x86 芯片组 SMBus |
| GPIO 模拟 | i2c-gpio.c |
任意 GPIO |
| Virtio/测试 | i2c-virtio.c, i2c-stub.c |
虚拟化/测试 |
每个控制器驱动典型实现:
platform_driver/pci_driverprobe;- 映射 MMIO、申请 IRQ、获取 clock/reset/pinctrl;
- 填充
struct i2c_adapter+struct i2c_algorithm; i2c_add_numbered_adapter()注册;master_xfer()中完成实际收发。
10. RK3588 平台:Rockchip i2c-rk3x.c 详细分析
10.1 设备树绑定
RK3588 在 rk3588s.dtsi 中定义多个 I2C 控制器,例如:
1 | i2c0: i2c@fd880000 { |
要点:
- 主 compatible:
rockchip,rk3588-i2c(SoC 特有属性); - 回退 compatible:
rockchip,rk3399-i2c(驱动of_match中已注册,共用rk3399_soc_data); - RK3588S 芯片上约有 8 路 I2C(
i2c0~i2c7等,具体以 dtsi 为准); - 板级 dts 通过
status = "okay"、clock-frequency、子节点使能外设。
10.2 驱动支持的 SoC 列表(rk3x_i2c_match[])
| compatible | 时序算法 | 备注 |
|---|---|---|
rockchip,rk3066-i2c |
v0 | 老 GRF 切换 |
rockchip,rk3188-i2c |
v0 | |
rockchip,rk3228-i2c |
v0 | |
rockchip,rk3288-i2c |
v0 | |
rockchip,rk3399-i2c |
v1 | RK3588 回退使用 |
rockchip,rv1108-i2c |
v0 | |
rockchip,rv1126-i2c |
v1 | |
rockchip,rv1126b-i2c |
v1 + DMA |
RK3588 无独立 rk3588_soc_data 条目,通过 DT 字符串回退到 rk3399 实现(v1 时序计算、双时钟 i2c+pclk)。
10.3 硬件寄存器与传输模式
主要寄存器:
| 偏移 | 名称 | 功能 |
|---|---|---|
0x00 |
REG_CON | 使能、主/从模式、START/STOP、ACK 策略、SDA/STA/STO 时序 tuning |
0x04 |
REG_CLKDIV | SCL 高低电平分频 |
0x08/0x0c |
MRXADDR/MRXRADDR | 组合写读(寄存器地址 + 读数据) |
0x10/0x14 |
MTXCNT/MRXCNT | 发送/接收字节数 |
0x18/0x1c |
IEN/IPD | 中断使能/挂起 |
0x80+ |
DMA_* | DMA 地址、配置(部分 SoC) |
0x228 |
REG_CON1 | Auto-Stop(v5+ 硬件) |
传输路径:
| 模式 | 条件 | 说明 |
|---|---|---|
| FIFO | 默认,短消息 | TX/RX buffer 在 0x100/0x200,每次最多 32 字节 |
| DMA | 较长消息、SoC 支持 | dmaengine + bounce buffer,完成后 rk3x_i2c_complete_dma() |
| 组合写读 | num>=2 且首包为短写 |
硬件 REGISTER_TX 模式,一次完成「写寄存器地址 + 读数据」 |
10.4 状态机与中断
1 | STATE_IDLE → STATE_WRITE / STATE_READ → STATE_STOP → STATE_IDLE |
rk3x_i2c_irq():读REG_IPD,按状态调用handle_write/read/stop;- 上层
rk3x_i2c_xfer_common()通过wait_event_timeout(i2c->wait, !i2c->busy)同步; - Atomic 路径:
rk3x_i2c_xfer_polling()关中断轮询rk3x_i2c_irq(),用于 atomic 上下文。
10.5 时序计算(v1,RK3399/RK3588 路径)
rk3x_i2c_v1_calc_timings():根据clock-frequency(100k/400k/1M 等)和 DT 中的scl-rise-ns、scl-fall-ns计算motion_low/high分频;- 满足 I2C 规范:
tHD;sta、tSU;sta、tSU;sto、tSU;dat等; rk3x_i2c_clk_notifier_cb():时钟频率变化时重新rk3x_i2c_adapt_div(),避免 DVFS 后时序违规。
10.6 特殊功能
| 功能 | 说明 |
|---|---|
| Auto-Stop | IP version ≥ 5 时 autostop_supported,短传输硬件自动发 STOP |
| GRF 切换 | 老 SoC 通过 rockchip,grf 切换 I2C 接口模式 |
| Thunder Boot | rockchip,amp-shared + CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE 延迟使能 IRQ |
| SCL Hold 检测 | 超时且 REG_INT_SLV_HDSCL 时复位控制器并告警 |
| Restart 兼容 | 硬件无真 Repeated START,通过复位内部状态 + 普通 START 模拟 |
10.7 i2c_algorithm 能力
1 | static u32 rk3x_i2c_func(struct i2c_adapter *adap) |
支持标准 I2C、SMBus 模拟、无 START 优化;具体 SMBus 由 core 层模拟完成。
10.8 Probe 流程摘要
1 | rk3x_i2c_probe() |
11. 辅助与测试模块
| 文件 | 功能 |
|---|---|
i2c-stub.c |
模拟 SMBus 从设备,供驱动开发测试 |
i2c-slave-eeprom.c |
内核模拟 I2C EEPROM 从设备 |
i2c-slave-testunit.c |
测试 unit,验证 multi-master、Host Notify 等 |
生产内核通常不使能这些选项。
12. 与 RK3588 外设的典型关系
1 | rk3588s.dtsi (i2c0..i2c7) |
- Client 驱动位于
drivers/i2c/clients之外的其他目录(如drivers/input/touchscreen、drivers/mfd、drivers/hwmon); drivers/i2c只提供总线基础设施,不包含具体芯片驱动。
13. 调试与排障指南
13.1 确认 Adapter 是否注册
1 | ls /sys/bus/i2c/devices/ |
13.2 用户态探测
1 | i2cdetect -y 2 # 扫描 i2c-2 总线 |
13.3 内核日志
- 打开
CONFIG_I2C_DEBUG_CORE/CONFIG_I2C_DEBUG_BUS; - 关注
timeout、NACK、SCL hold by slave(rk3x 特有); trace_event i2c i2c_transfer(若使能 trace)。
13.4 常见问题对照
| 现象 | 可能原因 | 排查方向 |
|---|---|---|
无 /dev/i2c-N |
adapter 未注册或 CHARDEV 未开 | dmesg、status in DT |
| -ETIMEDOUT | 时钟/上拉/地址错误、总线锁死 | 示波器、降低 clock-frequency |
| -ENXIO (NACK) | 从设备地址错误或未上电 | i2cdetect、硬件原理图 |
| 仅某通道失败 | MUX 未切换 | 检查 mux 驱动与子 adapter 编号 |
| DVFS 后偶发错误 | I2C 时钟变化未适配 | rk3x clk notifier、固定频率测试 |
14. 功能模块对照总表
| 模块 | 源文件 | 对 RK3588 的意义 |
|---|---|---|
| 核心传输 | i2c-core-base.c |
所有 I2C 访问必经 |
| SMBus | i2c-core-smbus.c, i2c-smbus.c |
传感器/电源 SMBus 访问 |
| DT 枚举 | i2c-core-of.c |
板级外设自动加载 |
| 用户态 | i2c-dev.c |
调试与工具链 |
| Mux | i2c-mux.c, muxes/* |
多设备同板拓扑 |
| 算法 | algos/* |
GPIO I2C 备用方案 |
| 主机控制器 | busses/i2c-rk3x.c |
RK3588 内置 I2C 硬件驱动 |
| 从模式 | i2c-core-slave.c |
一般不使用 |
| 测试 | i2c-stub.c, i2c-slave-*.c |
开发阶段可选 |
15. 结论
rk3588/kernel-6.1/drivers/i2c 目录实现的是 Linux 通用 I2C 子系统:
- Core 定义总线模型、传输 API、OF 枚举、SMBus、恢复与调试基础设施;
- i2c-dev 提供用户态访问;
- i2c-mux 与 muxes/ 处理复杂拓扑;
- algos/ 提供软件位带等通用算法;
- busses/ 包含各平台硬件控制器,其中 RK3588 使用
i2c-rk3x.c,DT 兼容rockchip,rk3588-i2c+rockchip,rk3399-i2c。
对 RK3588 开发与排障:
- 外设驱动问题 → 查具体 client 驱动与 DT 节点;
- 整条总线异常 → 重点分析
i2c-rk3x.c的 xfer 状态机、时钟分频、中断与 pinctrl; - 用户态验证 →
i2c-dev+ i2c-tools。
16. 推荐阅读顺序
drivers/i2c/Makefile、Kconfig— 模块组成i2c-core-base.c—i2c_transfer、i2c_register_adapteri2c-core-of.c— DT 设备注册i2c-dev.c— 用户态接口busses/i2c-rk3x.c— RK3588 硬件实现arch/arm64/boot/dts/rockchip/rk3588s.dtsi— 控制器与外设节点i2c-mux.c+ 所用muxes/*— 若板级有 MUX
文档版本:基于 rk3588/kernel-6.1 源码树分析。
正在加载留言…