RK3588 kernel-6.1/drivers/i2c 目录功能详细分析

RK3588 kernel-6.1/drivers/i2c 目录功能详细分析

1. 文档范围

本文对以下目录做功能级详细分析:

  • 源码路径:rk3588/kernel-6.1/drivers/i2c
  • 文档路径:linuxDoc/drivers/i2c/

分析目标:

  1. 说明该目录在 Linux 内核中的职责与分层结构;
  2. 逐项解释核心文件、算法层、复用器层、总线控制器层的具体功能
  3. 重点说明 RK3588 平台 使用的 Rockchip I2C 控制器驱动(i2c-rk3x.c);
  4. 给出设备树绑定、传输调用链与排障思路。

同目录已有 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
用户态 (i2c-tools / 应用)


i2c-dev.c (/dev/i2c-N) 或 内核 client 驱动


i2c-core (i2c_transfer / i2c_smbus_*)

├── i2c-mux.c (可选,多路复用)


adapter->algo->master_xfer()


busses/i2c-xxx.c (硬件控制器,如 i2c-rk3x.c)


物理 SDA/SCL ──► I2C 从设备 (传感器/PMIC/触摸/Codec 等)

3. 构建与 Kconfig 配置体系

3.1 顶层 Makefile

1
2
3
4
5
6
7
8
9
10
obj-$(CONFIG_I2C)           += i2c-core.o
i2c-core-objs := i2c-core-base.o i2c-core-smbus.o
i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o
i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o
i2c-core-$(CONFIG_OF) += i2c-core-of.o

obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
obj-y += algos/ busses/ muxes/

说明:

  • i2c-core 是必选核心模块(CONFIG_I2C),其余按 Kconfig 裁剪;
  • algos/busses/muxes/ 始终进入编译树,具体 .o 由各自子目录 Makefile + Kconfig 决定;
  • RK3588 板级配置通常使能:I2CI2C_CHARDEVI2C_MUXOFI2C_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
2
3
4
5
client 驱动 (如 xxx_probe 里读写寄存器)
→ i2c_smbus_* / i2c_transfer()
→ __i2c_transfer()
→ adap->algo->master_xfer() // 如 rk3x_i2c_xfer
→ 硬件寄存器 + 中断/DMA

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-notifywakeup-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_listi2c_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_RETRIESI2C_TIMEOUT 等;
  • 用户态工具:i2cdetecti2cgeti2cseti2cdump(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) 切换硬件通道;
  • 传输时:selecti2c_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-5i2c-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.cbusses/)配合:用两个 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 虚拟化/测试

每个控制器驱动典型实现:

  1. platform_driver / pci_driver probe
  2. 映射 MMIO、申请 IRQ、获取 clock/reset/pinctrl;
  3. 填充 struct i2c_adapter + struct i2c_algorithm
  4. i2c_add_numbered_adapter() 注册;
  5. master_xfer() 中完成实际收发。

10. RK3588 平台:Rockchip i2c-rk3x.c 详细分析

10.1 设备树绑定

RK3588 在 rk3588s.dtsi 中定义多个 I2C 控制器,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
i2c0: i2c@fd880000 {
compatible = "rockchip,rk3588-i2c", "rockchip,rk3399-i2c";
reg = <0x0 0xfd880000 0x0 0x1000>;
clocks = <&cru CLK_I2C0>, <&cru PCLK_I2C0>;
clock-names = "i2c", "pclk";
interrupts = <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&i2c0m0_xfer>;
resets = <&cru SRST_I2C0>, <&cru SRST_P_I2C0>;
reset-names = "i2c", "apb";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};

要点:

  • 主 compatiblerockchip,rk3588-i2c(SoC 特有属性);
  • 回退 compatiblerockchip,rk3399-i2c(驱动 of_match 中已注册,共用 rk3399_soc_data);
  • RK3588S 芯片上约有 8 路 I2C(i2c0i2c7 等,具体以 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
2
3
STATE_IDLE → STATE_WRITE / STATE_READ → STATE_STOP → STATE_IDLE
↑__________________________|
IRQ 推进
  • 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-nsscl-fall-ns 计算 motion_low/high 分频;
  • 满足 I2C 规范:tHD;statSU;statSU;stotSU;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
2
3
4
5
6
7
static u32 rk3x_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C |
I2C_FUNC_SMBUS_EMUL |
I2C_FUNC_PROTOCOL_MANGLING |
I2C_FUNC_NOSTART;
}

支持标准 I2C、SMBus 模拟、无 START 优化;具体 SMBus 由 core 层模拟完成。

10.8 Probe 流程摘要

1
2
3
4
5
6
7
8
rk3x_i2c_probe()
→ 解析 bus id (of_alias / ACPI)
→ i2c_parse_fw_timings()
→ ioremap、request_irq、clk/reset
→ 可选 GRF、Thunder Boot 回调
→ adap.algo = &rk3x_i2c_algorithm
→ i2c_add_numbered_adapter()
→ of_i2c_register_devices() [core 自动]

11. 辅助与测试模块

文件 功能
i2c-stub.c 模拟 SMBus 从设备,供驱动开发测试
i2c-slave-eeprom.c 内核模拟 I2C EEPROM 从设备
i2c-slave-testunit.c 测试 unit,验证 multi-master、Host Notify 等

生产内核通常不使能这些选项。


12. 与 RK3588 外设的典型关系

1
2
3
4
5
6
7
8
9
10
11
rk3588s.dtsi (i2c0..i2c7)

├── 板级 .dts 使能 &i2c2 等
│ ├── pmic@xx (电源管理)
│ ├── codec@xx (音频)
│ ├── touchscreen@xx (触摸)
│ └── eeprom@xx (配置存储)

└── 可选 i2c-mux@xx
├── channel@0 → 传感器
└── channel@1 → 摄像头 SCCB
  • Client 驱动位于 drivers/i2c/clients 之外的其他目录(如 drivers/input/touchscreendrivers/mfddrivers/hwmon);
  • drivers/i2c 只提供总线基础设施,不包含具体芯片驱动。

13. 调试与排障指南

13.1 确认 Adapter 是否注册

1
2
ls /sys/bus/i2c/devices/
ls /dev/i2c-* # 需 CONFIG_I2C_CHARDEV

13.2 用户态探测

1
2
i2cdetect -y 2         # 扫描 i2c-2 总线
i2cget -y 2 0x50 0x00 # 读设备 0x50 寄存器 0

13.3 内核日志

  • 打开 CONFIG_I2C_DEBUG_CORE / CONFIG_I2C_DEBUG_BUS
  • 关注 timeoutNACKSCL 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 子系统

  1. Core 定义总线模型、传输 API、OF 枚举、SMBus、恢复与调试基础设施;
  2. i2c-dev 提供用户态访问;
  3. i2c-muxmuxes/ 处理复杂拓扑;
  4. algos/ 提供软件位带等通用算法;
  5. 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. 推荐阅读顺序

  1. drivers/i2c/MakefileKconfig — 模块组成
  2. i2c-core-base.ci2c_transferi2c_register_adapter
  3. i2c-core-of.c — DT 设备注册
  4. i2c-dev.c — 用户态接口
  5. busses/i2c-rk3x.c — RK3588 硬件实现
  6. arch/arm64/boot/dts/rockchip/rk3588s.dtsi — 控制器与外设节点
  7. i2c-mux.c + 所用 muxes/* — 若板级有 MUX

文档版本:基于 rk3588/kernel-6.1 源码树分析。

文章互动

阅读 --

留言

0 条留言

正在加载留言…