RK3588 kernel-6.1/drivers/i2c/muxes 目录功能详细分析
1. 文档范围
本文分析目录:
- 源码:
rk3588/kernel-6.1/drivers/i2c/muxes - 文档:
linuxDoc/drivers/i2c/
前提: muxes/ 中的驱动都依赖上层 i2c-mux.c(位于 drivers/i2c/) 提供的多路复用框架。本文先说明框架机制,再逐项分析 muxes/ 下 9 个具体驱动/模块的功能、实现差异与 RK3588 使用场景。
2. 为什么需要 I2C Mux
2.1 问题场景
| 场景 | 说明 |
|---|---|
| 地址冲突 | 多条支路挂相同 7 位地址设备(如多个 EEPROM 0x50) |
| 拓扑扩展 | 一条物理 I2C 需服务多组独立外设(摄像头 SerDes、传感器等) |
| 引脚复用 | SoC 同一 I2C 控制器 SDA/SCL 可路由到不同引脚组 |
| 多主仲裁 | 两个主机共享一条从总线,需互斥获取总线 |
| 多主机切换 | 运行时在不同物理 I2C 主控之间切换(demux) |
2.2 内核抽象
Linux 不把 mux 做成“透明转发”,而是为每个通道(或逻辑段)注册独立的 i2c_adapter:
1 | 物理 I2C 主控 (i2c-2, rk3x) |
用户态可见多个 /dev/i2c-*;client 驱动挂在子 adapter 对应的 DT 子节点下。
3. 与 i2c-mux.c 核心的关系
muxes/ 不包含通用 mux 框架,只实现各硬件/机制的 select / deselect 回调。
3.1 核心数据结构(include/linux/i2c-mux.h)
1 | struct i2c_mux_core { |
3.2 传输路径(i2c-mux.c)
每次在子 adapter 上 i2c_transfer() 时:
1 | i2c_mux_master_xfer() |
- 支持 SMBus 透传(
i2c_mux_smbus_xfer); - 支持 多级 mux(子 adapter 下再挂 mux);
- 通过
parent->mux_lock与lock_ops避免父子 adapter 重复加锁死锁。
3.3 驱动开发模板
典型 mux 芯片驱动流程:
1 | probe |
4. 目录与构建配置
4.1 文件列表
| 源文件 | Kconfig | 模块名 |
|---|---|---|
i2c-mux-pca954x.c |
I2C_MUX_PCA954x |
i2c-mux-pca954x |
i2c-mux-pca9541.c |
I2C_MUX_PCA9541 |
i2c-mux-pca9541 |
i2c-mux-gpio.c |
I2C_MUX_GPIO |
i2c-mux-gpio |
i2c-mux-pinctrl.c |
I2C_MUX_PINCTRL |
i2c-mux-pinctrl |
i2c-mux-reg.c |
I2C_MUX_REG |
i2c-mux-reg |
i2c-mux-gpmux.c |
I2C_MUX_GPMUX |
i2c-mux-gpmux |
i2c-mux-ltc4306.c |
I2C_MUX_LTC4306 |
i2c-mux-ltc4306 |
i2c-mux-mlxcpld.c |
I2C_MUX_MLXCPLD |
i2c-mux-mlxcpld |
i2c-demux-pinctrl.c |
I2C_DEMUX_PINCTRL |
i2c-demux-pinctrl |
i2c-arb-gpio-challenge.c |
I2C_ARB_GPIO_CHALLENGE |
i2c-arb-gpio-challenge |
依赖:全部需要 CONFIG_I2C_MUX(i2c-mux.c 核心)。
4.2 分类概览
1 | i2c-mux.c (核心框架) |
5. 各驱动功能详细分析
5.1 i2c-mux-pca954x.c — NXP PCA954x/PCA984x(最常用)
硬件: NXP I2C 多路复用器/开关,自身也是 I2C 从设备,通过写 8 位控制寄存器 选通通道。
支持型号:
| 类型 | 型号 | 通道数 | 行为 |
|---|---|---|---|
| Mux | PCA9540/42/44/45/47/9548 | 2~8 | 互斥,同一时刻仅一路 |
| Switch | PCA9543/46/9846~9849 | 2~8 | 可 多路同时 接通(位掩码) |
核心实现:
| 函数 | 功能 |
|---|---|
pca954x_reg_write() |
用 __i2c_smbus_xfer() 写寄存器,避免 i2c_transfer 二次锁总线 |
pca954x_select_chan() |
计算 regval,若与 last_chan 不同则写入 |
pca954x_deselect_mux() |
按 idle-state:保持 / 断开 / 切到指定通道 |
pca954x_irq_setup() |
部分型号支持 INT,为每通道建 nested irq_domain |
idle_state sysfs |
运行时配置空闲时通道策略 |
设备树示例:
1 | pca9548: mux@70 { |
RK3588 关联: 车载/多摄板级 DTS 中常见 GPIO 位控制的 i2c-mux 节点(见 §8);若硬件使用 PCA9548,则绑定 nxp,pca9548 由本驱动管理。
5.2 i2c-mux-pca9541.c — NXP PCA9541 总线主选择器
硬件语义: 不是“多通道扩展”,而是 两个 I2C 主机争用一条从总线 的仲裁芯片。
功能要点:
- 建模为 单通道 mux:
select= 获取总线所有权,deselect= 释放; - 通过
PCA9541_CONTROL/PCA9541_ISTAT寄存器协商; - 超时:
ARB_TIMEOUT(125ms 强制)、ARB2_TIMEOUT(250ms 失败); - 读写寄存器使用
__i2c_smbus_xfer,同样避免重入锁。
适用: 双 CPU / 双 BMC 共享传感器总线;RK3588 普通嵌入式板较少使用。
5.3 i2c-mux-gpio.c — GPIO 控制的多路复用
硬件: 用 N 根 GPIO 编码选择 2^N 条 I2C 支路(板级 CPLD/逻辑电路)。
核心实现:
| 函数 | 功能 |
|---|---|
i2c_mux_gpio_set() |
gpiod_set_array_value_cansleep() 一次性设置所有 GPIO |
i2c_mux_gpio_select() |
chan 作为 GPIO 位图写入 |
i2c_mux_gpio_deselect() |
写入 idle-state(I2C_MUX_GPIO_NO_IDLE 表示不恢复) |
设备树:
i2c-parent:phandle 指向父 adapter;- 子节点
reg= 该通道的 GPIO 编码值; idle-state:空闲时 GPIO 值。
平台: platform_driver,支持 OF 与 ACPI。
5.4 i2c-mux-pinctrl.c — pinctrl 引脚复用型 Mux
场景: SoC 的 I2C 信号可通过 pinctrl 路由到不同引脚组,每组对应一条“逻辑总线”(如 I2C0 走 pinmux A 或 B)。
核心实现:
| 函数 | 功能 |
|---|---|
i2c_mux_pinctrl_select() |
pinctrl_select_state(pinctrl, states[chan]) |
i2c_mux_pinctrl_deselect() |
切到 states[num_adapters](idle 状态) |
i2c_mux_pinctrl_root_adapter() |
校验各 state 是否指向同一 root adapter |
设备树:
i2c-parent:父 adapter;pinctrl-names/pinctrl-0…:每个 channel 对应一个 state;- 额外一个 idle state(
pinctrl-names最后一项)。
与 GPIO mux 区别: 切换的是 SoC 引脚复用,不是外部 mux 芯片。
5.5 i2c-mux-reg.c — MMIO 寄存器控制型 Mux
硬件: 板级用一个 内存映射寄存器 的若干位选择 I2C 路由(常见于 PowerPC/QorIQ 等)。
核心实现:
| 函数 | 功能 |
|---|---|
i2c_mux_reg_set() |
iowrite8/16/32 写通道号,posted bus 上 ioread 确保写完成 |
i2c_mux_reg_select/deselect() |
select 写 chan_id;deselect 可选写 idle |
设备树: reg 指定寄存器物理地址;little-endian / big-endian;idle-in-use + idle。
5.6 i2c-mux-gpmux.c — 通用 MUX 子系统接口
设计: 不直接操作 GPIO/寄存器,而是调用 mux_control_select() / mux_control_deselect()(Linux multiplexer 子系统)。
核心实现:
1 | mux_control_select(mux->control, chan); // select |
设备树:
1 | compatible = "i2c-mux"; |
优点: 硬件选通逻辑可复用于 SPI/I2C 等其他子系统;抽象层次最高。
5.7 i2c-mux-ltc4306.c — Analog LTC4305/4306
硬件: ADI I2C mux/switch,带 rise time accelerator、upstream/downstream 加速配置。
功能:
| 特性 | 说明 |
|---|---|
| regmap | LTC_REG_STATUS/CONFIG/MODE/SWITCH |
| LTC4306 | 4 通道 + 2 个可选 GPIO(gpio_chip 导出) |
| LTC4305 | 2 通道 |
| select | 写 LTC_REG_SWITCH 选通通道 |
与 pca954x 类似: I2C 控制的专用 mux 芯片,适合长走线、电容负载大的场景。
5.8 i2c-mux-mlxcpld.c — Mellanox CPLD Mux
场景: Mellanox 网卡/服务器主板,CPLD 寄存器控制 I2C 路由。
核心实现:
| 函数 | 功能 |
|---|---|
mlxcpld_mux_reg_write() |
1/2 字节寄存器写入选通值 |
mlxcpld_mux_select_chan() |
仅当 last_val != regval 时写入,减少总线流量 |
| 平台数据 | mlxcpld_mux_plat_data:寄存器地址、宽度 |
拓扑(驱动注释): i2c-mlxcpld 桥接 → CPLD mux 寄存器 → 多条虚拟 bus → 外设。
RK3588 产品树通常 不包含 此驱动。
5.9 i2c-demux-pinctrl.c — pinctrl 反多路复用(Demux)
与 mux 的本质区别:
| 对比项 | Mux (i2c-mux-*.c) |
Demux (i2c-demux-pinctrl) |
|---|---|---|
| 父总线数量 | 1 个 parent | 多个 parent(≥2) |
| 子 adapter | 每个 channel 一个,同时存在 | 仅 1 个 当前 active adapter |
| 切换方式 | 每次传输 select 通道 | 运行时 换主控 + OF overlay |
| 用户接口 | 标准 i2c adapter 编号 | sysfs current_master |
工作流程:
1 | 用户写 sysfs current_master = N |
sysfs:
available_masters:可读所有候选主控;current_master:读写当前主控索引。
场景: 同一组引脚在“内部 I2C0”与“外部 I2C 扩展”之间动态切换(Renesas 等平台常见)。
5.10 i2c-arb-gpio-challenge.c — GPIO 挑战-应答仲裁
不是通道扩展,而是 多主机互斥:
| GPIO | 作用 |
|---|---|
our-gpio |
本方声明要占用总线 |
their-gpio |
检测对方是否已占用 |
select 流程:
- 拉高
our-gpio; - 轮询
their-gpio是否为低(对方释放); - 超时则放弃并重试;
- 成功则返回 0,允许在 parent 上传输。
标志: i2c_mux_alloc(..., I2C_MUX_ARBITRATOR, ...)。
场景: 两个主控(如 AP + MCU)共享一条 I2C,无专用 PCA9541 时的软件仲裁方案。
6. Mux 与 Switch 语义对比(以 PCA954x 为代表)
| 类型 | 寄存器写法 | 同时导通 |
|---|---|---|
| Mux | chan | enable |
否,仅一路 |
| Switch | 1 << chan |
是,位掩码可多 bit |
驱动在 pca954x_regval() 中统一处理,对上层均暴露为独立 channel adapter。
7. 锁机制与嵌套 Mux
i2c-mux.c 提供两套 lock_ops:
| 模式 | 行为 |
|---|---|
| 默认 | 子 adapter 锁 parent->mux_lock + 可选 root lock |
I2C_MUX_LOCKED |
mux 自身持有段锁,防止 select 期间父总线被其他客户端抢占 |
多级 mux 示例:
1 | i2c-2 (rk3x) |
传输时依次 select 两级;i2c_adapter_depth() 用于嵌套锁层级。
8. RK3588 平台使用场景
8.1 内置 I2C 控制器
RK3588 自带多路 rockchip,rk3588-i2c,不经过 muxes/ 目录驱动,由 i2c-rk3x.c 直接提供 adapter。
8.2 板级 DTS 中的 i2c-mux 节点
在 RK3588 车载/多摄相关 DTS 中大量出现 逻辑名 i2c-mux 的节点,例如:
rk3588-vehicle-evb-maxim-max96722-dphy0.dtsirk3588-vehicle-maxim-cameras-s66.dtsi
典型结构:
1 | /* 父 I2C 上 */ |
说明:
- 节点名
i2c-mux是 DT 拓扑约定,表示其下每个i2c@N对应一条逻辑子总线; - 实际选通可能由 板级 GPIO、SerDes 内部逻辑或外部 PCA954x 完成;
- 若
compatible = "i2c-mux"且使用 MUX 子系统,内核加载i2c-mux-gpmux.c; - 若为
nxp,pca9548等,加载i2c-mux-pca954x.c; - 部分方案可能在 驱动/固件内部 完成通道切换,DT 仅描述拓扑,不绑定上述 mux 驱动之一。
8.3 RK3588 常用驱动优先级建议
| 硬件实现 | 推荐驱动 |
|---|---|
| NXP PCA954x/984x 芯片 | i2c-mux-pca954x |
| GPIO 选通 | i2c-mux-gpio |
| SoC 引脚复用多组 I2C 走线 | i2c-mux-pinctrl |
| 绑定 mux-controller | i2c-mux-gpmux |
| 双主争用 | i2c-mux-pca9541 或 i2c-arb-gpio-challenge |
| 运行时切换不同 I2C 主控 | i2c-demux-pinctrl |
9. 调试与排障
9.1 确认子 adapter
1 | ls /sys/bus/i2c/devices/ |
9.2 在正确通道上探测
1 | # 应对子 adapter 编号,而非仅父 bus |
9.3 常见问题
| 现象 | 可能原因 |
|---|---|
| 子总线无设备 | 未 select 到正确 channel;reg 与硬件通道不一致 |
| 偶发 -EBUSY | 多主仲裁失败(pca9541 / arb-gpio) |
| 仅某 channel 失败 | switch 型芯片被配成多通,电气冲突 |
| probe defer | i2c-parent phandle 对应 adapter 尚未注册 |
| pca954x idle 异常 | 检查 idle-state sysfs / DT 属性 |
9.4 PCA954x 专用
1 | # 查看/设置空闲通道策略(若 sysfs 存在) |
10. 功能对照总表
| 文件 | 控制手段 | 通道模型 | 典型平台 |
|---|---|---|---|
i2c-mux-pca954x.c |
I2C 寄存器 | 2~8 路 mux/switch | 通用嵌入式、服务器 |
i2c-mux-pca9541.c |
I2C 寄存器 | 单通道仲裁 | 双主共享总线 |
i2c-mux-gpio.c |
GPIO 位编码 | N 路 | 自定义 CPLD/逻辑 |
i2c-mux-pinctrl.c |
pinctrl state | N 路引脚组 | Tegra 等 SoC 引脚复用 |
i2c-mux-reg.c |
MMIO 寄存器 | N 路 | PowerPC/QorIQ 等 |
i2c-mux-gpmux.c |
mux 子系统 | N 路 | 现代 DT 通用方案 |
i2c-mux-ltc4306.c |
I2C 寄存器 | 2/4 路 + 加速 | 长电缆/大电容负载 |
i2c-mux-mlxcpld.c |
CPLD I2C 寄存器 | 多路 | Mellanox 网卡 |
i2c-demux-pinctrl.c |
pinctrl + OF | 多主控选一 | Renesas 等 |
i2c-arb-gpio-challenge.c |
GPIO 握手 | 单通道仲裁 | 双 GPIO 多主 |
11. 结论
drivers/i2c/muxes 目录提供 9 种 I2C 拓扑扩展/仲裁实现,均通过 i2c-mux.c 统一为:
select:传输前选通通道或获取总线;deselect:传输后恢复 idle(可选);i2c_mux_add_adapter:为每个 channel 导出独立i2c_adapter。
对 RK3588 开发:
- 物理层 由
i2c-rk3x.c提供父 adapter; - 拓扑层 根据硬件选用
pca954x、gpio、gpmux或pinctrl等; - 车载多摄 DTS 中
i2c-mux节点描述子总线结构,需结合具体compatible与原理图确认实际加载的 mux 驱动。
12. 推荐阅读顺序
drivers/i2c/i2c-mux.c— 框架与锁include/linux/i2c-mux.h— APImuxes/i2c-mux-pca954x.c— 最典型芯片实现muxes/i2c-mux-gpio.c或i2c-mux-gpmux.c— 板级常见方案Documentation/devicetree/bindings/i2c/下各 binding- RK3588 板级 DTS 中带
i2c-mux的 dtsi
13. 相关文档
rk3588-kernel-6.1-drivers-i2c目录功能详细分析_zh.md— 整个drivers/i2c目录rk3588-kernel-6.1-i2c总线架构分析.md— 架构与 rk3x 传输链
文档版本:基于 rk3588/kernel-6.1 源码树 drivers/i2c/muxes 分析。