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

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)驱动 的集合。每个驱动负责:

  1. 映射硬件寄存器、申请 IRQ、管理 clock/reset/pinctrl;
  2. 实现 struct i2c_algorithm(主要是 master_xfer);
  3. 调用 i2c_add_adapter() / i2c_add_numbered_adapter() 向 core 注册总线;
  4. 由 core 在 adapter 下枚举 DT 子节点并加载 client 驱动。

RK3588 产品路径的核心文件是 i2c-rk3x.cCONFIG_I2C_RK3X)。


2. 目录规模与构建组织

统计项 数量
目录下文件总数 约 144
.c 源文件 约 133
Kconfig 选项 I2C_* 约 128
复合模块(多 .o 合并) i2c-designware-*i2c-at91i2c-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; /* master_xfer, functionality */
void *algo_data; /* 驱动私有数据 */
int nr; /* 总线号 → /dev/i2c-N */
...
};

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";
};

要点:

  • 主 compatiblerockchip,rk3588-i2c(DT 标识 SoC);
  • 回退 compatiblerockchip,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
/* rk3x_i2c_setup() */
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_STOPTRANSFER_AUTO_STOPNACK_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。

8.2 i2c-qcom-geni.c — 高通 GENI

  • 新一代统一串行引擎中的 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/hwmondrivers/mfddrivers/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 与 i2cNpinctrl-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. 推荐阅读顺序

  1. busses/i2c-rk3x.c — RK3588 主路径
  2. arch/arm64/boot/dts/rockchip/rk3588s.dtsi — 控制器节点
  3. busses/Kconfig + Makefile — 全局索引
  4. i2c-core-base.ci2c_transfer 如何调用 master_xfer
  5. (对比)i2c-designware-master.c — 另一主流 IP 实现风格
  6. (可选)busses/i2c-gpio.c — GPIO 扩展总线

15. 相关文档


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

文章互动

阅读 --

留言

0 条留言

正在加载留言…