RK3588 kernel-6.1/drivers/i2c/busses 目录功能详细分析
1. 文档范围
本文分析目录:
- 源码:
rk3588/kernel-6.1/drivers/i2c/busses
- 文档:
linuxDoc/drivers/i2c/
定位: busses/ 是 Linux I2C 子系统中 I2C/SMBus 主机控制器(Host Controller)驱动 的集合。每个驱动负责:
- 映射硬件寄存器、申请 IRQ、管理 clock/reset/pinctrl;
- 实现
struct i2c_algorithm(主要是 master_xfer);
- 调用
i2c_add_adapter() / i2c_add_numbered_adapter() 向 core 注册总线;
- 由 core 在 adapter 下枚举 DT 子节点并加载 client 驱动。
RK3588 产品路径的核心文件是 i2c-rk3x.c(CONFIG_I2C_RK3X)。
2. 目录规模与构建组织
| 统计项 |
数量 |
| 目录下文件总数 |
约 144 |
.c 源文件 |
约 133 |
Kconfig 选项 I2C_* |
约 128 |
| 复合模块(多 .o 合并) |
如 i2c-designware-*、i2c-at91、i2c-stm32f7 |
Makefile 按 硬件类别 分段编译(注释分区):
1 2 3 4 5 6 7
| ACPI drivers → i2c-scmi Auxiliary → i2c-ccgx-ucsi PC SMBus host controllers → i801, piix4, amd*, via* ... Mac SMBus host controllers → hydra, powermac Embedded system controllers → 绝大多数 SoC I2C IP(含 i2c-rk3x) External I2C/SMBus adapters → USB/并口等外置适配器 Other bus drivers → tunnel, legacy, virtio ...
|
3. 在 I2C 架构中的位置
1 2 3 4 5 6 7 8 9 10 11 12
| i2c-core (i2c_transfer) │ ▼ adapter->algo->master_xfer() │ ┌───────────────────┼───────────────────┐ │ │ │ busses/i2c-rk3x.c busses/i2c-gpio.c busses/i2c-designware-*.c (硬件 IP) + algos/bit (Synopsys DW IP) │ │ ▼ ▼ MMIO + IRQ + DMA GPIO 模拟 SDA/SCL
|
与 algos/ 的分工:
| 类型 |
示例 |
master_xfer 实现位置 |
| 硬件控制器 |
i2c-rk3x, i2c-imx, i2c-designware |
busses 内直接实现 |
| GPIO/并口 |
i2c-gpio, i2c-parport |
algos/i2c-algo-bit + bus 提供 GPIO 回调 |
4. 主机控制器驱动通用模式
几乎所有 busses/*.c 遵循同一模板:
1 2 3 4 5 6 7 8 9
| platform_driver / pci_driver probe → 解析 DT/ACPI,获取 bus number (alias) → devm_ioremap, clk_prepare, reset, pinctrl → 填充 i2c_adapter + i2c_algorithm → i2c_parse_fw_timings() 解析 clock-frequency → i2c_add_numbered_adapter() 或 i2c_add_adapter() → of_i2c_register_devices() [core 自动扫描子节点] remove → i2c_del_adapter()
|
关键结构:
1 2 3 4 5 6
| struct i2c_adapter { struct i2c_algorithm *algo; void *algo_data; int nr; ... };
|
5. 驱动分类总表(按平台/用途)
5.1 PC / 服务器(PCI SMBus)
| Kconfig |
源文件 |
功能 |
I2C_I801 |
i2c-i801.c |
Intel 南桥/ PCH SMBus(ICH 系列) |
I2C_PIIX4 |
i2c-piix4.c |
Intel PIIX4 及兼容芯片组 |
I2C_AMD756 |
i2c-amd756.c |
AMD/nForce SMBus |
I2C_AMD8111 |
i2c-amd8111.c |
AMD 8111 第二 SMBus |
I2C_ISMT |
i2c-ismt.c |
Intel iSMT SMBus |
I2C_ALI1535/1563/15X3 |
i2c-ali*.c |
Acer Labs 芯片组 |
I2C_VIA/VIAPRO |
i2c-via*.c |
VIA 芯片组 |
I2C_NFORCE2 |
i2c-nforce2.c |
nForce SMBus |
I2C_NVIDIA_GPU |
i2c-nvidia-gpu.c |
NVIDIA GPU 上 SMBus |
I2C_THUNDERX |
i2c-thunderx-pcidrv.c + core |
Cavium ThunderX |
I2C_MLXBF |
i2c-mlxbf.c |
Mellanox BlueField |
5.2 Synopsys DesignWare(广泛使用的 IP)
| Kconfig |
源文件 |
功能 |
I2C_DESIGNWARE_CORE |
i2c-designware-common.c, master.c, slave.c |
DW I2C 核心 |
I2C_DESIGNWARE_PLATFORM |
i2c-designware-platdrv.c |
平台设备绑定 |
I2C_DESIGNWARE_PCI |
i2c-designware-pcidrv.c |
PCI 绑定 |
I2C_DESIGNWARE_BAYTRAIL |
i2c-designware-baytrail.c |
BayTrail PMIC 总线仲裁 |
I2C_DESIGNWARE_AMDPSP |
i2c-designware-amdpsp.c |
AMD PSP 共享总线 |
特点:regmap 访问、DW_IC_* 寄存器、支持 Standard/Fast/Fast+ 时序计算、FIFO、可选 slave。
注意: RK3588 不使用 DesignWare I2C,而使用 Rockchip 自研/定制的 rk3x 控制器。
5.3 ARM SoC 厂商(嵌入式主力)
| 厂商/系列 |
Kconfig 示例 |
源文件 |
| Rockchip |
I2C_RK3X |
i2c-rk3x.c |
| NXP i.MX |
I2C_IMX, I2C_IMX_LPI2C |
i2c-imx.c, i2c-imx-lpi2c.c |
| Samsung |
I2C_EXYNOS5, I2C_S3C2410 |
i2c-exynos5.c, i2c-s3c2410.c |
| Qualcomm |
I2C_QUP, I2C_QCOM_GENI, I2C_QCOM_CCI |
i2c-qup.c, i2c-qcom-geni.c, i2c-qcom-cci.c |
| Broadcom |
I2C_BCM2835, I2C_BCM_IPROC |
i2c-bcm2835.c, i2c-bcm-iproc.c |
| TI |
I2C_OMAP, I2C_DAVINCI |
i2c-omap.c, i2c-davinci.c |
| NVIDIA Tegra |
I2C_TEGRA, I2C_TEGRA_BPMP |
i2c-tegra.c, i2c-tegra-bpmp.c |
| STMicro |
I2C_STM32F4/F7 |
i2c-stm32*.c |
| Atmel/Microchip |
I2C_AT91 |
i2c-at91-*.c |
| Renesas |
I2C_RCAR, I2C_RIIC, I2C_SH_MOBILE |
i2c-rcar.c, i2c-riic.c, i2c-sh_mobile.c |
| Allwinner |
I2C_SUN6I_P2WI |
i2c-sun6i-p2wi.c |
| Amlogic |
I2C_MESON |
i2c-meson.c |
| MediaTek |
I2C_MT65XX, I2C_MT7621 |
i2c-mt65xx.c, i2c-mt7621.c |
| HiSilicon |
I2C_HISI, I2C_HIX5HD2 |
i2c-hisi.c, i2c-hix5hd2.c |
| Spreadtrum |
I2C_SPRD |
i2c-sprd.c |
| Marvell |
I2C_MV64XXX |
i2c-mv64xxx.c |
| Xilinx |
I2C_XILINX |
i2c-xiic.c |
| Cadence |
I2C_CADENCE |
i2c-cadence.c |
| Aspeed BMC |
I2C_ASPEED |
i2c-aspeed.c |
5.4 GPIO / 算法依赖型
| Kconfig |
源文件 |
功能 |
I2C_GPIO |
i2c-gpio.c |
2 线 GPIO + i2c-algo-bit |
I2C_OCORES |
i2c-ocores.c |
OpenCores I2C IP |
I2C_PARPORT |
i2c-parport.c |
并口 + algo-bit |
I2C_PCA_PLATFORM |
i2c-pca-platform.c |
PCA9564 桥 + i2c-algo-pca |
I2C_SIMTEC |
i2c-simtec.c |
Simtec 板 + algo-bit |
5.5 外置 / USB / 虚拟
| Kconfig |
源文件 |
功能 |
I2C_TINY_USB |
i2c-tiny-usb.c |
USB I2C 适配器 |
I2C_DLN2 |
i2c-dln2.c |
Delock USB |
I2C_VIRTIO |
i2c-virtio.c |
虚拟化 I2C |
I2C_CROS_EC_TUNNEL |
i2c-cros-ec-tunnel.c |
Chrome EC 隧道 |
I2C_SCMI |
i2c-scmi.c |
ACPI SCMI 代理 I2C |
5.6 特殊 / Legacy
| 源文件 |
功能 |
i2c-cros-ec-tunnel.c |
经 EC 访问 I2C |
i2c-opal.c |
PowerPC OPAL 固件 I2C |
i2c-fsi.c |
IBM FSI 总线 |
i2c-elektor.c, i2c-icy.c |
PCF8584 + algo-pcf |
scx200_acb.c |
SCx200 访问总线 |
6. RK3588 核心驱动:i2c-rk3x.c 详细分析
6.1 配置与启用
arch/arm64/configs/rockchip_linux_defconfig:
1 2
| CONFIG_I2C_CHARDEV=y CONFIG_I2C_RK3X=y
|
模块名:i2c-rk3x(built-in 或 module)。
6.2 设备树绑定
rk3588s.dtsi 示例(共约 8 路 I2C 控制器):
1 2 3 4 5 6 7 8 9 10 11 12
| 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>; resets = <&cru SRST_I2C0>, <&cru SRST_P_I2C0>; reset-names = "i2c", "apb"; #address-cells = <1>; #size-cells = <0>; status = "disabled"; };
|
要点:
- 主 compatible:
rockchip,rk3588-i2c(DT 标识 SoC);
- 回退 compatible:
rockchip,rk3399-i2c(驱动 of_match 已注册,使用 rk3399_soc_data);
- 双时钟:
i2c(功能时钟)+ pclk(APB);
- 板级 dts 设置
status = "okay"、clock-frequency = <400000> 等。
6.3 寄存器地图(摘要)
| 偏移 |
名称 |
功能 |
0x00 |
REG_CON |
使能、模式(TX/RX/REGISTER_TX)、START/STOP、时序 tuning |
0x04 |
REG_CLKDIV |
SCL 分频(div_low/div_high) |
0x08/0x0c |
MRXADDR/MRXRADDR |
组合写读(寄存器地址预置) |
0x10/0x14 |
MTXCNT/MRXCNT |
发送/接收字节数 |
0x18/0x1c |
IEN/IPD |
中断使能/挂起 |
0x100/0x200 |
TX/RX buffer |
FIFO 数据区 |
0x80+ |
DMA_* |
DMA 配置(部分 SoC) |
0x228 |
REG_CON1 |
Auto-Stop(IP v5+) |
6.4 传输路径
1 2 3 4 5 6 7 8 9 10 11 12
| rk3x_i2c_xfer() → rk3x_i2c_xfer_common(polling=false) clk_enable(clk/pclk) for each msg group: rk3x_i2c_setup() // 组合写读优化 rk3x_i2c_start() ├─ len≥阈值: rk3x_i2c_start_dma() └─ 否则: rk3x_i2c_start_fifo() wait_event_timeout(busy) rk3x_i2c_complete_dma() [若 DMA] rk3x_i2c_disable() clk_disable()
|
中断状态机:
| 状态 |
处理函数 |
STATE_WRITE |
rk3x_i2c_handle_write() — MBTF,填 TX buffer |
STATE_READ |
rk3x_i2c_handle_read() — MBRF,读 RX buffer |
STATE_STOP |
rk3x_i2c_handle_stop() — 唤醒等待线程 |
硬件限制:单次 FIFO 读写最多 32 字节;更长数据分段或走 DMA。
6.5 组合写读(REGISTER_TX)
当 num>=2 且第一条为短写、第二条为读时:
1 2 3 4
| if (num >= 2 && msgs[0].len < 4 && !(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) mode = REG_CON_MOD_REGISTER_TX;
|
等效于 SMBus 风格的 register read,减少 STOP/START 开销。
6.6 时序计算
两套 SOC 算法:
| 回调 |
适用 SoC |
特点 |
rk3x_i2c_v0_calc_timings |
rk3066, rk3188, rk3228, rk3288 |
老分频模型 |
rk3x_i2c_v1_calc_timings |
rk3399, rv1108, rv1126, RK3588(经 rk3399) |
SDA/STA/STO tuning 字段 |
支持模式:Standard 100kHz、Fast 400kHz、Fast+ 1MHz(受 clock-frequency 与输入时钟约束)。
rk3x_i2c_clk_notifier_cb():DVFS 改变 i2c 时钟时重新计算分频。
6.7 DMA 路径
- 消息长度超过阈值(约 64/65 字节)时使用
dmaengine;
- bounce buffer:
rk3x_i2c_get_dma_safe_msg_buf();
- 完成后
rk3x_i2c_dma_irq_callback() 唤醒 xfer 线程;
rv1126b 等通过 soc_data->dma_control 管理 DMA 通道生命周期。
6.8 Auto-Stop(REG_CON1)
IP version ≥ 5(RK_I2C_VERSION5)时:
- 短传输可由硬件自动发 STOP;
REG_CON1_AUTO_STOP、TRANSFER_AUTO_STOP、NACK_AUTO_STOP;
- 减少 CPU 参与 STOP 阶段的中断次数。
6.9 特殊平台功能
| 功能 |
说明 |
| GRF 切换 |
老 SoC 通过 rockchip,grf 切换 I2C 接口模式 |
| Thunder Boot |
rockchip,amp-shared + CONFIG_ROCKCHIP_THUNDER_BOOT_SERVICE 延迟使能 IRQ |
| Restart 通知 |
register_restart_handler 在 reboot 时完成进行中的传输 |
| SCL Hold 恢复 |
超时且 REG_INT_SLV_HDSCL 时复位控制器 |
| Repeated START |
硬件无真 REPSTART,通过复位 CON 状态 + 普通 START 模拟 |
6.10 i2c_algorithm 能力
1 2 3 4 5
| static u32 rk3x_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; }
|
master_xfer:中断模式;
master_xfer_atomic:polling 模式(关 IRQ 轮询 rk3x_i2c_irq);
- 无原生
smbus_xfer,SMBus 由 core 模拟。
6.11 支持的 of_device_id
| compatible |
soc_data |
rockchip,rk3066-i2c |
v0 |
rockchip,rk3188-i2c |
v0 |
rockchip,rk3228-i2c |
v0 |
rockchip,rk3288-i2c |
v0 |
rockchip,rk3399-i2c |
v1(RK3588 回退) |
rockchip,rv1108-i2c |
v1 |
rockchip,rv1126-i2c |
v1 |
rockchip,rv1126b-i2c |
v1 + DMA |
无独立 rockchip,rk3588-i2c 表项——依赖 DT 字符串列表中的 fallback。
6.12 PM
rk3x_i2c_suspend_noirq / resume_noirq:标记 suspended,resume 时 rk3x_i2c_adapt_div() 恢复时序。
7. 其他与 RK 生态相关的 bus 驱动
| 驱动 |
RK3588 是否使用 |
说明 |
i2c-rk3x.c |
是 |
主 I2C |
i2c-gpio.c |
可选 |
扩展 GPIO I2C,需 CONFIG_I2C_GPIO + algo-bit |
i2c-designware-* |
否 |
其他平台 DW IP |
i2c-dwc3 等 |
否 |
在 drivers/usb/dwc3,非本目录 |
8. 代表性非 RK 驱动简述(便于对比学习)
8.1 i2c-imx.c — NXP i.MX
- 支持 IMX 各代 I2C 控制器;
- DMA、PM runtime、多 bus;
- 与 rk3x 类似为 平台专用 IP,非 DesignWare。
- 新一代统一串行引擎中的 I2C 模式;
- 与旧
i2c-qup.c 并存。
8.3 i2c-gpio.c — GPIO 模拟
1 2 3 4 5
| bit_data.setsda = i2c_gpio_setsda_val; bit_data.setscl = i2c_gpio_setscl_val; bit_data.getsda = i2c_gpio_getsda; bit_data.getscl = i2c_gpio_getscl; i2c_bit_add_numbered_bus(adap);
|
DT:compatible = "i2c-gpio",gpios = <&gpio SDA>, <&gpio SCL>。
8.4 i2c-tegra.c — NVIDIA
- Tegra SoC 专用 I2C,支持 DMA、时钟门控;
- 结构复杂度与 rk3x 同级。
9. 与 Client 驱动及 DT 的关系
1 2 3 4 5 6 7 8 9
| busses/i2c-rk3x 注册 i2c-2 │ ▼ core: of_i2c_register_devices() │ ├── pmic@20 → MFD/PMIC 驱动 ├── codec@11 → ASoC codec ├── touchscreen@14 → 输入驱动 └── eeprom@50 → nvmem/eeprom
|
Client 驱动不在 busses/,分布在 drivers/hwmon、drivers/mfd、drivers/input 等目录。
10. 调试与排障(RK3588)
10.1 确认控制器
1 2 3
| ls /sys/bus/i2c/devices/ cat /sys/kernel/debug/pinctrl/*/pinmux-pins | grep i2c dmesg | grep -i rk3x
|
10.2 用户态测试
1 2
| i2cdetect -y 2 i2cget -y 2 0x20 0x00
|
需 CONFIG_I2C_CHARDEV=y。
10.3 常见问题
| 现象 |
排查 |
无 i2c-N |
DT status、驱动 CONFIG_I2C_RK3X、clock/reset 失败 |
| -ETIMEDOUT |
clock-frequency 过高、上拉不足、外设未就绪 |
| -ENXIO (NACK) |
从设备地址错误 |
SCL hold by slave |
从设备拉低 SCL,检查硬件或降低速率 |
| 仅某路 I2C 异常 |
对比 pinctrl、assigned-clocks |
| DMA 错误 |
消息长度、dma channel 是否 probe 成功 |
10.4 内核调试
1 2 3
| CONFIG_I2C_DEBUG_BUS=y → busses 驱动 DEBUG 日志 CONFIG_I2C_DEBUG_CORE=y → core 日志 trace: i2c_transfer
|
11. 如何选择/启用驱动(维护者视角)
| 场景 |
操作 |
| 新 Rockchip SoC 复用 rk3x IP |
在 rk3x_i2c_match[] 增加 compatible + soc_data |
| 新板级外设 |
仅需在 DT 对应 &i2cN 下添加子节点 |
| 需要 GPIO I2C |
使能 I2C_GPIO + I2C_ALGOBIT,添加 i2c-gpio 节点 |
| 端口复用冲突 |
检查 pinctrl 与 i2cN 的 pinctrl-0 |
12. 功能对照总表(本目录职责)
| 职责 |
由谁完成 |
| 硬件寄存器访问 |
busses/*.c |
| I2C 时序(START/STOP/字节) |
控制器驱动或 algo-bit |
i2c_adapter 注册 |
控制器驱动 |
| 设备枚举 |
i2c-core-of(非 busses) |
| 传感器/PMIC 逻辑 |
client 驱动(非 busses) |
| 总线拓扑扩展 |
i2c-mux + muxes(非 busses) |
13. 结论
drivers/i2c/busses 目录是 各平台 I2C 主机硬件驱动的仓库:
- 约 128 个可配置驱动,覆盖 x86、ARM、MIPS、USB 虚拟等;
- 按
Makefile 分为 PC、嵌入式、外置等类别;
- RK3588 仅依赖
i2c-rk3x.c,通过 DT rockchip,rk3588-i2c + fallback rk3399-i2c 绑定;
- 驱动实现完整 FIFO/DMA/组合写读/时钟 notifier/Auto-Stop 等机制;
- 与
algos/(GPIO 模拟)、muxes/(拓扑)、i2c-core(框架)分层清晰。
阅读 RK3588 I2C 问题应 优先深入 i2c-rk3x.c,再结合板级 DTS 与具体 client 驱动。
14. 推荐阅读顺序
busses/i2c-rk3x.c — RK3588 主路径
arch/arm64/boot/dts/rockchip/rk3588s.dtsi — 控制器节点
busses/Kconfig + Makefile — 全局索引
i2c-core-base.c — i2c_transfer 如何调用 master_xfer
- (对比)
i2c-designware-master.c — 另一主流 IP 实现风格
- (可选)
busses/i2c-gpio.c — GPIO 扩展总线
15. 相关文档
文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/busses 分析。
正在加载留言…