首页/目录/全部文章

全部文章

八个专题的源码、算法与协议笔记都在这里。

笔记列表

PMBus 电源监控框架

PMBus 电源监控框架

1. 分层

1
2
3
4
5
6
7
chip driver (adm1275/ltc2978/...)
|
pmbus_core.c
|
I2C/SMBus
|
HWMON sysfs

pmbus.c 是 generic PMBus driver,专用文件描述不同芯片 capabilities、pages、register 和 quirks。

2. 基本概念

  • pages:多个 rail/channel;
  • standard commands;
  • manufacturer commands;
  • status words;
  • direct/linear/VID formats;
  • read/write byte/word/block;
  • alert/SMBALERT。

3. Driver info

芯片驱动提供 pmbus_driver_info

  • pages;
  • per-page function bits;
  • data formats;
  • coefficients;
  • virtual registers;
  • read/write override;
  • identify callback。

Core据此生成 temp/in/curr/power/fan attributes。

4. Probe

1
2
3
4
5
6
7
8
i2c probe
-> identify chip/revision
-> allocate pmbus_driver_info
-> pmbus_do_probe()
-> check PMBus capability
-> discover pages/functions
-> initialize data
-> create hwmon attributes

generic driver通常需要明确 device ID/DT compatible,避免盲目绑定不兼容 SMBus 设备。

5. 数据格式

Linear11

5-bit signed exponent + 11-bit signed mantissa:

1
value = mantissa * 2^exponent

Linear16

16-bit unsigned mantissa,exponent通常来自 VOUT_MODE。

Direct

使用 m/b/R 系数换算,必须正确处理符号和溢出。

6. Pages

读写多 page device时先选择 PAGE register。Core必须串行 page select + data access,防止并发读不同 rail 串页。

7. Status/Alarm

PMBus status包括:

  • VOUT/IOUT/INPUT;
  • temperature;
  • CML;
  • fan;
  • manufacturer。

清状态可能改变硬件 latch;驱动需区分读取状态和显式 reset history。

8. PEC/SMBus

部分器件支持 SMBus Packet Error Checking。是否启用取决于 adapter 和 device。错误 PEC 会表现为 -EBADMSG 或通信失败,不能通过忽略校验长期运行。

9. PMBus 与 regulator

PMBus HWMON负责观测和标准阈值;若器件同时是 regulator,电压设定/enable 可能由 regulator framework 驱动。两个接口的权限和并发必须协调,不能通过 hwmon 私有属性绕过 regulator consumers。

10. RK3588

本树包含完整 PMBus 驱动,但公共 RK3588 DTS 未显示统一 PMBus 电源控制器。服务器/NVR 定制板若添加器件,需要同时启用 CONFIG_PMBUS 和对应 SENSORS_*

HWMON、Thermal、IIO 与 Power Supply 边界

HWMON、Thermal、IIO 与 Power Supply 边界

1. HWMON

适合:

  • 读取健康监控值;
  • 配置 sensor threshold;
  • 读取 alarm/fault;
  • 人工或 daemon 控制 PWM;
  • libsensors 展示。

2. Thermal

负责:

  • thermal zone;
  • trip point;
  • governor;
  • cooling device;
  • CPU/GPU/NPU cooling;
  • shutdown critical temperature。

RK3588 TSADC直接注册 thermal sensors,温度主要见:

1
/sys/class/thermal/thermal_zone*/

不保证同时出现 tempN_input

3. HWMON 到 Thermal

现代 hwmon driver设置 HWMON_C_REGISTER_TZ,Core按 OF thermal-sensors引用把 temp channel注册到 Thermal。

这适用于外部温度 sensor作为 thermal zone provider。没有 OF引用时注册返回 -ENODEV,hwmon仍可正常存在。

4. Thermal 到 HWMON

hwmon_device_register_for_thermal() 是 legacy 专用 API,只允许 Thermal 子系统使用。新普通 hwmon driver不应调用它。

5. IIO

IIO适合:

  • ADC;
  • buffered sampling;
  • trigger;
  • timestamp;
  • raw/scale/processed;
  • 高速或事件数据。

iio_hwmon.c 将 IIO processed channels桥接成 HWMON inN_input/tempN_input 等,方便 lm-sensors。

6. Power Supply

负责 battery/charger/USB power:

  • voltage_now;
  • current_now;
  • capacity;
  • status;
  • health。

单位和 ABI 与 HWMON 不同。电池 gauge 应优先 power_supply,不应为了 sensors 重复注册一套无协调接口。

7. Regulator

Regulator表示可供 consumer请求的电源 rail setpoint/enable,不等同于物理测量。PMIC寄存器的设定值不能替代 INA/ADC 的实际电压。

8. hwspin/SCMI

SCMI/SCPI firmware sensor可由 scmi-hwmon/scpi-hwmon 暴露。数据由固件提供,Linux无直接寄存器访问,采样率和错误语义受 firmware协议限制。

9. 决策

1
2
3
4
5
控制系统降频/关机       -> Thermal
展示板级健康值 -> HWMON
ADC/高频采集/触发 -> IIO
电池/充电器 -> Power Supply
电源 rail 使能/设定 -> Regulator

同一物理器件可跨子系统,但应有单一底层数据/锁管理,避免重复硬件访问和控制冲突。

缓存、并发、错误处理与电源管理

缓存、并发、错误处理与电源管理

1. 为什么缓存

一次 sensors 会连续读取 input、min、max、alarm、label。若每个 sysfs read 都访问 I2C:

  • 总线流量高;
  • 读取跨 conversion 不一致;
  • 增加功耗;
  • 触发 read-to-clear 副作用;
  • 放大故障。

2. 常见模式

1
2
3
4
5
6
7
mutex_lock
if invalid or cache expired:
read all related registers
if success:
update data/last_updated/valid
value = cache
mutex_unlock

失败时通常返回错误,是否保留旧值必须由驱动明确决定,不能无提示把 stale 数据当新值。

3. Regmap

优势:

  • bus abstraction;
  • endian;
  • cache;
  • volatile/precious register;
  • bulk/update_bits;
  • debugfs。

传感器数据寄存器通常 volatile;状态寄存器可能 precious/read-clear,不能错误缓存。

4. 锁

常见:

  • mutex:配置、缓存、page/bank select;
  • spinlock:tach IRQ pulse counter;
  • timer/work:周期采样;
  • regmap内部锁;
  • PMBus page access锁。

sysfs回调在进程上下文,可以睡眠;tach IRQ不能直接进行 I2C transaction。

5. 原子快照

多字节寄存器可能需要:

  • SMBus word transaction;
  • latch;
  • bulk read;
  • high-low-high retry;
  • conversion ready bit。

否则可能读到 rollover 中间值。

6. 错误语义

错误 含义
-ENODEV 芯片不存在/移除
-EIO 通信或设备错误
-ETIMEDOUT conversion/总线超时
-EBADMSG CRC/PEC
-EINVAL 属性/channel/value 无效
-EOPNOTSUPP 当前芯片不支持
-EPROBE_DEFER provider 未就绪

监控程序应记录 read failure,不能把错误当作 0。

7. PM

策略因芯片而异:

  • continuous conversion;
  • one-shot;
  • shutdown mode;
  • regulator power gate;
  • runtime PM;
  • suspend保留 alarm wake。

resume 后可能需要恢复 config/threshold/calibration并使 cache invalid。

8. 并发写

用户写 threshold/PWM 与 thermal governor、fan daemon或 kernel worker可能竞争。driver mutex只能防寄存器并发,不能定义多个控制策略的优先级;系统集成必须指定唯一 controller。

9. 生命周期

remove 顺序:

  1. 禁止新硬件事件;
  2. disable IRQ;
  3. del_timer_sync/cancel work;
  4. unregister notifier/cooling;
  5. devm移除 hwmon;
  6. power off。

使用 devm不自动替代对异步任务的同步停止。

10. Trace

HWMON Core有 read/write tracepoints,可配合 ftrace 判断哪个进程高频读取和 callback 延迟。I2C trace、function graph和 dynamic debug应只在调试时使用。

RK3588 监控拓扑与设备树

RK3588 监控拓扑与设备树

1. SoC 温度

RK3588 DTS:

1
2
tsadc@fec00000
compatible = "rockchip,rk3588-tsadc"

rk3588s.dtsi 定义 7 个 thermal sensor channel/zone,覆盖 package、bigcore、littlecore、center、GPU、NPU 等平台定义区域。

驱动:

1
2
drivers/thermal/rockchip_thermal.c
CONFIG_ROCKCHIP_THERMAL=y

它不在 drivers/hwmon/,主要接口是 thermal sysfs。

2. Thermal zones

1
2
3
for z in /sys/class/thermal/thermal_zone*; do
echo "$(cat "$z/type"): $(cat "$z/temp")"
done

温度单位为 millidegree Celsius。zone 的 trip、cooling map 和 governor 决定降频/风扇/临界关机。

3. PWM fan

多个 RK3588 EVB/vehicle/toybrick DTS 定义 compatible = "pwm-fan"

  • PWM period;
  • cooling-levels;
  • #cooling-cells
  • 厂商 rockchip,temp-trips

驱动同时提供:

  • hwmon pwm1
  • 可选 tach fanN_input
  • thermal cooling device,或 Rockchip system monitor notifier。

4. 配置

  • HWMON 默认 y,但最终配置为准;
  • ROCKCHIP_THERMAL=y 在主 defconfig显式启用;
  • SENSORS_PWM_FAN=yrk3588_edge.config 显式启用;
  • rockchip_linux_defconfig 未显式启用 PWM fan;
  • DTS 节点和驱动配置必须同时存在。

5. 外部传感器

公共 RK3588 DTS未呈现统一板载 INA、LM75 或 PMBus方案。定制板应按:

1
2
原理图芯片 -> bus/address -> DTS compatible -> Kconfig driver
-> probe log -> hwmon name/attributes

逐项核对。

6. IIO bridge

若 SARADC 采样热敏电阻/rail,可:

  • 由 thermal ADC sensor driver提供 thermal;
  • 由 IIO用户态接口读取;
  • iio_hwmon 桥接到 hwmon。

不要同时由多个 consumer无协调改变 ADC 配置。

7. 风扇控制路径

本厂商 pwm-fan:

1
2
3
4
5
有 ROCKCHIP_SYSTEM_MONITOR + rockchip,temp-trips
-> Rockchip notifier直接控制

否则 CONFIG_THERMAL
-> generic thermal cooling device

两条路径不同,不能只看 /sys/class/thermal/cooling_device* 判断风扇是否受控。

8. 电源观测

PMIC/regulator节点描述 setpoint 和约束,不一定提供实际 voltage/current hwmon。需要功耗测量时应使用板载 shunt monitor、PMBus或外部仪器校准。

9. RK3588 高负载

视频编解码、GPU、NPU、ISP并发时:

  • 观察各 thermal zone;
  • 检查 fan state/PWM;
  • 观察 cpufreq/devfreq throttling;
  • 记录环境温度;
  • 检查散热器接触;
  • 避免只看单一 package 温度。

10. 验证

1
2
3
4
zcat /proc/config.gz | grep -E 'HWMON|PWM_FAN|ROCKCHIP_THERMAL|IIO_HWMON'
ls /sys/class/hwmon
ls /sys/class/thermal
dmesg | grep -Ei 'hwmon|pwm.fan|thermal|tsadc'

HWMON 部署、调试、监控与安全建议

HWMON 部署、调试、监控与安全建议

1. 枚举

1
2
3
4
5
6
for h in /sys/class/hwmon/hwmon*; do
echo "== $h =="
cat "$h/name" 2>/dev/null
readlink -f "$h/device"
ls "$h"
done

2. lm-sensors

1
2
sensors
sensors -u

嵌入式 DT 平台不要无差别运行 sensors-detect --auto;它会探测 I2C地址,某些非 sensor设备不安全。优先使用原理图和 DTS。

3. 分层排障

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
没有 hwmonN
-> final .config
-> module loaded
-> DTS status/compatible/address
-> bus controller
-> probe errno

有 hwmonN 无属性
-> name
-> chip variant/capability
-> is_visible/channel info

属性读取失败
-> I2C/SPI error
-> power/reset
-> CRC/PEC
-> conversion ready
-> runtime PM

值不合理
-> ABI unit
-> shunt/divider/PPR
-> signed conversion
-> stale cache
-> calibration

4. 动态调试

1
2
3
mount -t debugfs none /sys/kernel/debug
echo 'file drivers/hwmon/pwm-fan.c +p' \
> /sys/kernel/debug/dynamic_debug/control

也可针对具体 sensor、PMBus core、I2C core。高频日志会改变时序并占用存储。

5. Trace

1
2
echo 1 > /sys/kernel/debug/tracing/events/hwmon/enable
cat /sys/kernel/debug/tracing/trace_pipe

用于定位高频 poll、write来源和延迟。生产环境设置频率限制。

6. Poll interval

监控周期不应远小于 sensor conversion/update interval。典型板级健康监控 1–5 秒已足够;过密读取增加总线、功耗和锁竞争,数据却不更新。

7. 告警

不要只依赖轮询:

  • 配置 hardware threshold;
  • 使用 alarm IRQ/uevent(若驱动支持);
  • 与 thermal critical trip配合;
  • daemon设置 debounce/hysteresis;
  • 记录 sensor read failure。

8. 权限

只读 sensor可开放给普通监控用户;以下应限制:

  • PWM;
  • threshold;
  • update interval;
  • power cap;
  • reset history;
  • chip-specific control。

错误写值可能停风扇、屏蔽 alarm或造成热损坏。使用 udev group和最小权限,不要全局 chmod 666。

9. 容器

不应把整个 /sys 可写挂载给容器。若需监控:

  • host exporter采集;
  • 只读代理;
  • 精确 bind mount;
  • 禁止直接写 PWM/threshold。

10. 稳定性

  • 不写死 hwmonN;
  • 数据附带 timestamp和 sensor identity;
  • 标记 stale/invalid;
  • 对突变做物理范围验证但保留原始错误;
  • 监控 fan command 与 fan RPM 一致性;
  • 做环境温度、高低负载和 suspend/resume测试。

11. RK3588 建议

  • SoC 热保护以 thermal zone/trip 为主;
  • hwmon用于外部 sensor和 fan可观测性;
  • 明确 generic thermal 与 Rockchip notifier 的 fan控制权;
  • 产品最终镜像检查 SENSORS_PWM_FAN
  • 编解码压力测试同时记录 CPU/GPU/NPU devfreq、温度、PWM/RPM和 throttling。

HWMON 子系统架构与源码总览

HWMON 子系统架构与源码总览

1. 定位

HWMON 为温度、电压、电流、功率、能量、湿度、风扇、PWM 和机箱入侵传感器提供统一 sysfs ABI。

1
2
3
4
5
6
7
8
9
lm-sensors / monitoring daemon
|
/sys/class/hwmon/hwmonN/
|
HWMON Core (hwmon.c)
|
native driver / PMBus / IIO bridge / firmware
|
I2C/SMBus / SPI / MMIO / PCI / USB-HID / mailbox

2. Core

hwmon.c 注册 class "hwmon",每个监控设备获得动态 hwmonN。主要对象:

  • hwmon_device
  • hwmon_chip_info
  • hwmon_channel_info
  • hwmon_ops
  • 自动生成的 hwmon_device_attribute

3. 传感器类型

1
2
3
4
5
6
7
8
9
10
hwmon_chip
hwmon_temp
hwmon_in
hwmon_curr
hwmon_power
hwmon_energy
hwmon_humidity
hwmon_fan
hwmon_pwm
hwmon_intrusion

每种类型有标准属性位,例如 HWMON_T_INPUTHWMON_F_INPUTHWMON_PWM_INPUT

4. 现代注册

1
2
3
4
5
6
7
8
bus/platform probe
-> allocate private data
-> initialize regmap/hardware
-> define hwmon_ops
-> define HWMON_CHANNEL_INFO(...)
-> devm_hwmon_device_register_with_info()
-> Core asks is_visible()
-> generate standard sysfs attributes

5. 读取

1
2
3
4
5
6
cat temp1_input
-> sysfs show
-> hwmon_attr_show()
-> chip->ops->read(dev, hwmon_temp, hwmon_temp_input, channel, &val)
-> driver reads/cache/converts register
-> decimal integer + newline

写阈值/PWM同理由 write() 完成。

6. 标准 ABI

典型:

1
2
3
4
5
6
name
temp1_input / temp1_max / temp1_crit / temp1_alarm
in1_input / curr1_input / power1_input
fan1_input / fan1_min / fan1_alarm
pwm1 / pwm1_enable
humidity1_input

单位由 ABI 固定,不能由驱动自行选择。

7. Driver families

  • I2C/SMBus 温度/电力 sensor;
  • SPI temperature/ADC;
  • platform SoC PVT;
  • Super-I/O;
  • PMBus power controller;
  • firmware SCMI/SCPI;
  • IIO to hwmon bridge;
  • PWM/GPIO fan;
  • USB/HID 水冷和 PSU。

8. 与 Thermal 的边界

HWMON 面向观测、阈值和人工控制;Thermal 框架负责 thermal zone、trip、governor、cooling device。Core 可用 HWMON_C_REGISTER_TZ 将温度 channel 注册成 OF thermal sensor,但 RK3588 主 TSADC 直接由 drivers/thermal/rockchip_thermal.c 管理,不通过 drivers/hwmon

9. RK3588

实际重点:

  • SoC 温度:Rockchip TSADC / thermal zones;
  • 板级风扇:pwm-fan.c,同时暴露 hwmon 与 cooling device;
  • 外置 INA/LM75/PMBus 等:仅在板级 DTS 和 Kconfig 明确启用时存在;
  • IIO ADC 电压可经 iio_hwmon 暴露;
  • regulator voltage 不自动等于 hwmon voltage。

10. 版本事实

本目录约 272 个文件。大部分是跨平台驱动,源码存在不代表 RK3588 构建或板上有该芯片。分析必须同时核对 Kconfig、最终 .config、DTS compatible 和实际 I2C/SPI 设备。

Linux 6.1 HWMON 子系统文档索引

Linux 6.1 HWMON 子系统文档索引

源码:rk3588/kernel-6.1/drivers/hwmon/
平台:RK3588 / ARM64,Rockchip Linux 6.1 厂商树

文档

编号 文档 内容
总览 HWMON子系统架构与源码总览.md 分层、对象、数据路径
索引 源码目录与驱动索引.md Makefile、Kconfig、驱动分类
01 HWMON-Core注册与生命周期.md class device、注册、devres
02 Sysfs-ABI属性单位与告警.md 标准属性、单位、权限、事件
03 驱动模型hwmon_ops与Legacy接口.md 新旧 API、channel info
04 温度湿度传感器驱动.md LM75/TMP/SHT、阈值与缓存
05 电压电流功率与能量监控.md INA、ADC、shunt、量纲换算
06 风扇转速PWM与热管理.md PWM fan、tach、cooling device
07 PMBus电源监控框架.md PMBus core、page、format、status
08 HWMON-Thermal-IIO-PowerSupply边界.md 子系统职责与桥接
09 缓存并发错误处理与电源管理.md regmap、update interval、锁、PM
10 RK3588监控拓扑与设备树.md TSADC、PWM fan、配置事实
11 部署调试监控与安全建议.md lm-sensors、排障、权限、调优

推荐阅读

1
2
3
4
5
6
总览 -> 01 Core -> 02 ABI -> 03 驱动 API
├-> 04 温湿度
├-> 05 电力
├-> 06 风扇
└-> 07 PMBus
-> 08 子系统边界 -> 10 RK3588 -> 11 运维

快速观察

1
2
3
4
5
6
for h in /sys/class/hwmon/hwmon*; do
echo "[$h] $(cat "$h/name" 2>/dev/null)"
done
sensors
cat /sys/class/thermal/thermal_zone*/type
cat /sys/class/thermal/thermal_zone*/temp

hwmonN 编号不稳定,程序应按 name、父设备路径或 libsensors 配置识别,不能写死编号。

drivers/hwmon/ 源码目录与驱动索引

drivers/hwmon/ 源码目录与驱动索引

1. 构建

1
2
3
4
5
CONFIG_HWMON      -> hwmon.o
CONFIG_HWMON_VID -> hwmon-vid.o
CONFIG_PMBUS -> pmbus/
CONFIG_SENSORS_PECI -> peci/
CONFIG_SENSORS_OCC -> occ/

HWMON_DEBUG_CHIP 为本目录编译增加 DEBUG 日志。

2. 核心

文件 作用
hwmon.c class、现代 API、属性生成、thermal bridge
hwmon-vid.c 传统 CPU VID 换算
include/linux/hwmon.h sensor types、attributes、ops/API
include/trace/events/hwmon.h read/write tracepoints
Documentation/hwmon/ ABI、内核 API、每驱动说明

本树没有单独的 hwmon-sysfs.c;sysfs 自动属性生成直接实现在 hwmon.c。大量 legacy 驱动则在自身文件中用 SENSOR_DEVICE_ATTR* 定义属性。

3. 总线分类

类型 代表
I2C/SMBus lm75lm90tmp102ina2xxsht3x
SPI adt7310lm70max31722ltc2947-spi
Platform/MMIO pwm-fangpio-fanmr75203bt1-pvt
PCI/ACPI/x86 coretempk10tempacpi_power_meter
Firmware scmi-hwmonscpi-hwmon
USB/HID corsair-*aquacomputer_d5nextnzxt-*
IIO bridge iio_hwmon

4. 类型分类

功能 代表驱动
温度 lm75/lm90/tmp*/jc42
温湿度 aht10/sht*/hih6130
电压 ADC ads7828/pcf8591/mcp3021
电流/功率 ina2xx/ina238/ina3221/ltc2945
风扇/PWM pwm-fan/gpio-fan/emc2305/max31790
电源控制器 pmbus/
SoC PVT mr75203/bt1-pvt/as370
硬盘温度 drivetemp

5. PMBus

pmbus/pmbus_core.c 实现协议通用层;pmbus.c 是 generic PMBus driver;其余文件提供芯片 pages、功能位、寄存器和格式 quirks。

6. RK3588 相关性

本树 RK3588 DTS 明确出现大量 pwm-fan 节点。主 defconfig 没有显式写 SENSORS_PWM_FAN,仅 rk3588_edge.config 明确启用,因此必须检查产品最终配置。

SoC TSADC 使用 drivers/thermal/rockchip_thermal.cCONFIG_ROCKCHIP_THERMAL=y,不在本目录。

主配置中的 SENSORS_ISL29018SENSORS_TSL2563 是环境光 IIO/input 类配置,不是本目录 HWMON sensor。

7. 文档

本树 Documentation/hwmon/ 有 200 余篇驱动文档,通用接口重点:

  • sysfs-interface.rst
  • hwmon-kernel-api.rst
  • userspace-tools.rst
  • pwm-fan.rst
  • pmbus-core.rst

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

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

1. 文档范围

本文分析目录:

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

核心定位: algos/ 提供 I2C 传输算法(struct i2c_algorithm 的软件实现,本身不直接操作具体 SoC 硬件。各 bus 控制器驱动busses/)或 GPIO I2C 驱动 负责提供底层读写 SDA/SCL 或桥接芯片寄存器的回调,再调用 i2c_bit_add_bus() / i2c_pca_add_bus() / i2c_pcf_add_bus() 将算法挂到 i2c_adapter 上。


2. 在 I2C 子系统中的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
i2c-core (i2c_transfer)


adapter->algo->master_xfer() ← algos/ 目录实现

├── i2c-algo-bit.c (软件位带 START/STOP/字节/ACK)
├── i2c-algo-pca.c (PCA9564/9665 状态机)
└── i2c-algo-pcf.c (PCF8584 状态机)


busses/*.c 提供的底层回调
例: i2c-gpio.c → setsda/setscl/getsda/getscl
i2c-pca-platform.c → read_byte/write_byte/wait_for_completion

RK3588 内置 I2Ci2c-rk3x.c)的关系:

对比项 algos/ i2c-rk3x.c
角色 通用 算法库 硬件主机控制器
master_xfer bit/pca/pcf 软件实现 rk3x_i2c_xfer 寄存器+中断
RK3588 默认 通常不启用(有硬件 I2C) 主要路径
可选场景 CONFIG_I2C_GPIO + I2C_ALGOBIT 用 GPIO 模拟 I2C 所有 i2c0i2c7

3. 目录与构建

3.1 文件列表

文件 说明
i2c-algo-bit.c 位带(bit-banging)算法,最常用
i2c-algo-pca.c NXP PCA9564 / PCA9665 并行总线桥算法
i2c-algo-pcf.c Philips PCF8584 算法
i2c-algo-pcf.h PCF8584 寄存器位定义(内部头文件)
Makefile / Kconfig 三模块独立编译选项

3.2 Kconfig

选项 模块 功能
I2C_ALGOBIT i2c-algo-bit.ko GPIO/并口等位带 I2C
I2C_ALGOPCA i2c-algo-pca.ko PCA9564/9665 桥
I2C_ALGOPCF i2c-algo-pcf.ko PCF8584 桥

顶层 drivers/i2c/KconfigI2C_HELPER_AUTO(默认 y)会在需要时自动选中对应 algo,无需手动配置。

menu "I2C Algorithms" 仅在 !I2C_HELPER_AUTO 时对用户可见。


4. 算法层设计模式(共性)

三类算法均遵循同一模式:

  1. Bus 驱动 分配 i2c_adapter,在 algo_data 中填入硬件相关结构体;
  2. 调用 i2c_*_add_bus() / i2c_*_add_numbered_bus()
  3. Add 函数内设置 adap->algo = &xxx_algo,再 i2c_add_adapter()
  4. Core 调用 adap->algo->master_xfer() 完成传输。

对外导出的符号(供 bus 驱动链接):

算法 导出接口 算法结构体
bit i2c_bit_add_bus, i2c_bit_add_numbered_bus i2c_bit_algo
pca i2c_pca_add_bus, i2c_pca_add_numbered_bus 内部 pca_algo
pcf i2c_pcf_add_bus 内部 pcf_algo

5. i2c-algo-bit.c — 软件位带算法(核心)

5.1 适用场景

  • 无专用 I2C 硬件 IP,仅用 GPIO 或并口线模拟 SDA/SCL;
  • 老平台、FPGA、扩展板、调试用 bit-bang;
  • RK3588 上对应驱动:busses/i2c-gpio.ccompatible = "i2c-gpio")。

5.2 底层回调结构(include/linux/i2c-algo-bit.h

1
2
3
4
5
6
7
8
9
10
11
12
struct i2c_algo_bit_data {
void *data;
void (*setsda)(void *data, int state);
void (*setscl)(void *data, int state);
int (*getsda)(void *data);
int (*getscl)(void *data); /* 可选,NULL 则无法检测 clock stretch */
int (*pre_xfer)(struct i2c_adapter *);
void (*post_xfer)(struct i2c_adapter *);
int udelay; /* 半时钟周期延时 (us) */
int timeout; /* SCL 拉高等待 (jiffies) */
bool can_do_atomic;
};

Bus 驱动只需实现 拉高/拉低/读取 SDA/SCL;时序由 algo 统一完成。

5.3 时序原语

函数 I2C 语义
i2c_start() START:SDA 高→低,SCL 高→低
i2c_repstart() Repeated START
i2c_stop() STOP:SCL 高,SDA 低→高
i2c_outb() 发送 8 bit + 读 ACK
i2c_inb() 接收 8 bit
sclhi() SCL 置高并等待(支持 clock stretching 检测)

udelay 决定速率:例如 udelay=5 约对应标准模式量级(需结合上升沿实测)。

5.4 传输主流程 bit_xfer()

1
2
3
4
5
6
7
8
pre_xfer (可选)
→ i2c_start()
→ 对每条 i2c_msg:
若非 I2C_M_NOSTART: bit_doAddress() (7/10 位地址 + 重试)
若 I2C_M_RD: readbytes() + ACK/NAK
否则: sendbytes()
→ i2c_stop()
post_xfer (可选)

支持特性bit_func()):

  • 标准 I2C、SMBus 模拟(含 block read I2C_M_RECV_LEN);
  • I2C_M_NOSTARTI2C_M_STOPI2C_M_IGNORE_NAK
  • 10 位地址 I2C_M_TEN
  • master_xfer_atomic(需 can_do_atomic)。

5.5 总线自检 test_bus()

i2c_bit_add_bus() 时若 bit_test 模块参数非 0,会:

  • 检查 SDA/SCL 是否空闲;
  • 拉低/拉高 SDA、SCL 验证线路未 stuck;
  • bit_test=2 时失败则拒绝注册 adapter。

5.6 依赖本算法的 bus 驱动(节选)

驱动 平台/用途
i2c-gpio.c GPIO 模拟 I2C(与嵌入式最相关
i2c-parport.c 并口
i2c-acorn.c Acorn
i2c-hydra.c Mac Hydra
i2c-via.c VIA 芯片组
i2c-simtec.c Simtec 板
i2c-versatile.c ARM Versatile

5.7 RK3588 上的 i2c-gpio 示例

i2c-gpio.c 通过 GPIO 子系统获取 sda/scl,填入 i2c_algo_bit_data,最后:

1
ret = i2c_bit_add_numbered_bus(adap);

设备树典型节点:

1
2
3
4
5
6
7
8
i2c_gpio: i2c-gpio {
compatible = "i2c-gpio";
gpios = <&gpio SDA GPIO_ACTIVE_HIGH>,
<&gpio SCL GPIO_ACTIVE_HIGH>;
i2c-gpio,delay-us = <5>;
#address-cells = <1>;
#size-cells = <0>;
};

RK3588 默认 defconfig 通常不启用 I2C_GPIO,仅在缺硬件通道或特殊板级需要时打开。


6. i2c-algo-pca.c — PCA9564/PCA9665 算法

6.1 适用场景

NXP PCA9564 / PCA9665I2C 转并行总线 的桥接芯片:主机通过访问桥上的寄存器,由芯片硬件状态机产生 SDA/SCL 波形。

6.2 底层回调(include/linux/i2c-algo-pca.h

1
2
3
4
5
6
7
8
9
10
struct i2c_algo_pca_data {
void *data;
void (*write_byte)(void *data, int reg, int val);
int (*read_byte)(void *data, int reg);
int (*wait_for_completion)(void *data); /* 等待 SI 中断 */
void (*reset_chip)(void *data);
unsigned int i2c_clock;
unsigned int chip; /* 9564 or 9665 */
struct pca_i2c_bus_settings bus_settings;
};

Bus 驱动(i2c-pca-platform.ci2c-pca-isa.c)负责 MMIO/ISA 端口读写与中断等待。

6.3 寄存器与芯片差异

寄存器 PCA9564 PCA9665
控制 I2C_PCA_CON (STA/STO/SI/ENSIO) 间接寄存器 I2C_PCA_INDPTR + I2C_PCA_IND
数据 I2C_PCA_DAT 同上
状态 I2C_PCA_STA (类似 0xF8 idle) 状态机码相同风格

pca_probe_chip():写 I2C_PCA_IADR 探测是否为 9665,否则按 9564 处理。

6.4 传输状态机 pca_xfer()

基于 状态寄存器值(如 0xF8 idle、0x08 START 已发、0x18 SLA+W ACK)驱动:

1
2
3
4
5
6
等待 bus idle (0xF8)
→ pca_start / pca_repeated_start
→ pca_address (写 DAT + 清 SI)
→ 写路径: pca_tx_byte 循环
→ 读路径: pca_rx_ack + pca_rx_byte
→ pca_stop

错误处理:0x20/0x30/0x38 NAK/仲裁丢失、0x70/0x90 SDA/SCL stuck 时 pca_reset()

6.5 时钟配置

  • PCA9564:8 档固定频率(330kHz~36kHz),i2c_clock 可为 Hz 或档位索引;
  • PCA9665:按目标 Hz 计算 tlow/thi,支持 Standard / Fast / Fast+ / Turbo 模式。

6.6 能力

pca_func()I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL(无 10bit、无 NOSTART 等 bit 算法的灵活标志)。


7. i2c-algo-pcf.c — PCF8584 算法

7.1 适用场景

Philips PCF8584 为较老的 I2C 总线控制器(并行接口),用于 ISA/定制总线扩展。现多见于 复古硬件(如 i2c-elektor.ci2c-icy.c)。

7.2 底层回调(include/linux/i2c-algo-pcf.h

1
2
3
4
5
6
7
8
9
10
struct i2c_algo_pcf_data {
void *data;
void (*setpcf)(void *data, int ctl, int val); /* ctl=0 数据, 1 控制 */
int (*getpcf)(void *data, int ctl);
int (*getown)(void *data);
int (*getclock)(void *data);
void (*waitforpin)(void *data);
void (*xfer_begin/end)(void *data);
unsigned long lab_mdelay; /* 多主仲裁丢失后延时 */
};

7.3 控制/状态位(i2c-algo-pcf.h

含义
I2C_PCF_STA / STO START / STOP
I2C_PCF_BB Bus Busy
I2C_PCF_LRB Last Received Bit (ACK)
I2C_PCF_LAB Lost Arbitration

7.4 传输流程 pcf_xfer()

1
2
3
4
5
6
7
8
9
xfer_begin
→ wait_for_bb() /* 等待总线空闲 */
→ 每条 msg:
pcf_doAddress
i2c_start (首条)
wait_for_pin /* 等待 PIN 中断 */
写: pcf_sendbytes
读: pcf_readbytes (含 dummy read)
→ xfer_end

多主: wait_for_pin 返回 -EINTR 表示仲裁丢失,handle_lab() 复位 PCF 并 lab_mdelay 退避。

7.5 初始化 pcf_init_8584()

检测 PCF8584 是否存在(写 OWNADR/CLKREG 等),配置时钟与 ESO。

7.6 能力

I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING(无 atomic xfer)。


8. 三种算法对比总表

特性 bit-bang PCA9564/9665 PCF8584
硬件形态 GPIO/并口线 I2C-Parallel 桥 并行 I2C 控制器
时序实现 软件 bit 操作 芯片状态机+主机轮询/中断 芯片状态机+PIN
Clock stretch 支持(需 getscl) 硬件处理 硬件处理
10 位地址 支持 不支持 不支持
SMBus block 支持(RECV_LEN) 模拟 模拟
多主仲裁 未完整实现 有(0x38) LAB + mdelay
典型年代 一直使用 2000s 工业板 1990s
RK3588 相关性 可选(GPIO I2C) 极低

9. 与 i2c-core 的衔接细节

9.1 谁调用算法

1
2
3
4
5
6
/* i2c-core-base.c */
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
...
ret = adap->algo->master_xfer(adap, msgs, num);
}

9.2 Quirks(bit 专用)

getscl == NULLi2c_bit_add_bus() 设置:

1
adap->quirks = &i2c_bit_quirk_no_clk_stretch;  /* I2C_AQ_NO_CLK_STRETCH */

告知上层该总线可能无法正确处理从设备拉长 SCL。

9.3 调试

  • CONFIG_I2C_DEBUG_ALGOccflags -DDEBUG(bit 中 bit_dbg);
  • bit 模块参数:bit_testi2c_debug
  • pca/pcf 模块参数:i2c_debug

10. RK3588 平台实践说明

10.1 默认路径

RK3588 使用 DesignWare 风格 Rockchip I2C IPi2c-rk3x.c),在 adapter 内直接实现 i2c_algorithm不经过 algos/

10.2 何时需要 algos

需求 配置建议
额外 GPIO 模拟 I2C CONFIG_I2C_GPIO=y + CONFIG_I2C_ALGOBIT=y(通常由 HELPER_AUTO 选中)
外接 PCA9564 并口桥 CONFIG_I2C_ALGOPCA + i2c-pca-platform
复古/特殊 PCF8584 板 CONFIG_I2C_ALGOPCF + 对应 bus 驱动

arch/arm64/configs/*rk3588* 中一般看不到 I2C_ALGOBIT;部分 RK 衍生配置(如 rv1126b_robot.config)会显式 CONFIG_I2C_ALGOBIT=y

10.3 与总线恢复的关系

i2c-core-base.ci2c_generic_scl_recovery() 在 adapter 有 bus_recovery_info 时,也可用 GPIO bit-bang 恢复卡死的 SDA/SCL;这与 i2c-algo-bit 思想相同,但是 core 内独立路径,不要求加载 i2c-algo-bit 模块。


11. 数据流示意(以 GPIO I2C 为例)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
传感器驱动 / i2c_transfer()


i2c-gpio adapter (i2c-10)


i2c_bit_algo.master_xfer ← i2c-algo-bit.c

├── setsda(0/1) ──► gpiod_set_value (SDA)
├── setscl(0/1) ──► gpiod_set_value (SCL)
└── getsda/getscl ──► gpiod_get_value


物理 SDA/SCL 引脚

12. 调试建议

问题 排查
GPIO I2C 无响应 检查 i2c-gpio,delay-us、上拉、开漏配置
Not I2C compliant: can't read SCL 未接 getscl,clock stretch 不可靠
test_bus 失败 SDA/SCL stuck,硬件短路或外设拉死
PCA 超时 0x?? wait_for_completion 中断未接;时钟配置错误
PCF Timeout waiting for BB 总线被占用或多主冲突
1
2
3
4
5
# 查看是否加载算法模块
lsmod | grep i2c_algo
# 查看 GPIO I2C adapter
ls /sys/bus/i2c/devices/ | grep mux
i2cdetect -y <bus>

13. 结论

drivers/i2c/algos 目录包含 3 个可加载的 I2C 算法模块,职责是:

  1. 实现统一的 i2c_algorithm.master_xfer
  2. 将 I2C 协议时序(START/STOP/字节/ACK)从 bus 驱动中解耦
  3. 通过 回调结构体 适配 GPIO、PCA 桥、PCF8584 等不同硬件形态。

对 RK3588 而言:

  • 主 I2Ci2c-rk3x,与 algos/ 无关
  • 扩展/备用 总线可通过 i2c-gpio + i2c-algo-bit 实现;
  • i2c-algo-pca / i2c-algo-pcf 主要用于特定外设桥与 legacy 硬件,产品树中较少出现。

理解 algos/ 有助于区分「硬件控制器驱动」与「纯软件/GPIO/桥片算法」两条 I2C 主机实现路径。


14. 推荐阅读顺序

  1. include/linux/i2c-algo-bit.h — 回调接口
  2. algos/i2c-algo-bit.cbit_xferi2c_bit_add_bus
  3. busses/i2c-gpio.c — RK 平台最可能用到的组合
  4. algos/i2c-algo-pca.c — 状态机桥接范例
  5. i2c-core-base.ci2c_transfer 入口

15. 相关文档


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

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 分析。