RK3506 Linux SMBus 协议与 Alert 机制(中文) 本文档说明 SMBus Alert、ARA 及 Linux 内核实现,并结合 RK3506 MPU 板级设备树(rk3506b-mpu.dtsi)举例。内核源码路径 以当前工程 kernel/ 为准。
术语
缩写
英文全称
中文
ARA
A lert R esponse A ddress
告警响应地址
SMBALERT#
SMBus Alert (active low)
SMBus 告警信号(低有效)
1. SMBus 与 I2C 的关系
项目
说明
物理层
与 I2C 相同(SCL/SDA,开漏)
协议
在 I2C 之上定义超时、ACK 规则、部分命令格式
Linux
CONFIG_I2C_SMBUS 启用后提供 i2c_smbus_*() API;Alert 由 i2c-smbus 模块处理
RK3506 的 I2C 控制器由 drivers/i2c/busses/i2c-rk3x.c 驱动,仅作 主机(Master) ,不实现 I2C 从机模式。
2. SMBus Alert 概述 2.1 信号:SMBALERT#
SMBALERT# :可选的开漏、线与 信号(类似 SCL/SDA)。
从设备有事件需主机处理时,将 SMBALERT# 拉低 。
多条从设备可 同时 拉低同一根线;主机只看到一个低电平 → 触发 一次 GPIO 中断。
2.2 专用地址:ARA(0x0C) ARA 全称:Alert Response Address(告警响应地址)
项目
值
缩写
ARA
英文全称
Alert Response Address
中文
告警响应地址
7 位地址
0x0C
用途
主机在 SMBALERT# 中断后访问,查询 当前正在告警 的从设备身份
「从设备才会响应 ARA」 的含义:
只有 自己把 SMBALERT# 拉低 的从机,才会对地址 0x0C 应答并在读阶段送出 自己的 7 位地址 + 1 位标志 。
未拉 SMBALERT# 的从机(例如总线上有 0x59 节点但未告警)不参与 此次 ARA 访问,等价于不存在。
2.3 与正常访问从设备地址的区别
操作
主机寻址
谁应答
读 PSU 寄存器
0x58
仅 reg = <0x58> 的芯片
处理 SMBus Alert
0x0C (ARA)
仅 正在拉 SMBALERT# 的芯片
3. 多从设备同时告警时的仲裁与读取顺序 3.1 规范行为(SMBus 1.1)
主机对 0x0C 执行 Receive Byte (读 1 字节)。
多个拉低 SMBALERT# 的从机同时参与;在 从机发送地址 阶段使用 标准 I2C 仲裁 :
SCL 为高时,SDA 上 发 0 胜、发 1 败 ;
7 位地址从高位比较 → 地址数值更小(优先级更高)的设备先胜出 。
胜出从机在应答 ARA 后应 释放 SMBALERT# 下拉 。
若传输结束后 SMBALERT# 仍为低 ,主机 再次读 ARA ,处理下一个仍挂起的告警。
3.2 示例:0x58、0x59、0x5a,仅 0x58 与 0x5a 拉线
地址
SMBALERT#
第 1 次 ARA
第 2 次 ARA
0x58
拉低
读出 0x58
—
0x59
未拉低
不参与
不参与
0x5a
拉低
与 0x58 仲裁失败
读出 0x5a
实际读取顺序:0x58 → 0x5a (0x59 不会出现)。
若三者 都 拉低 SMBALERT#,顺序为:0x58 → 0x59 → 0x5a (严格按地址从小到大,每轮 ARA 读出一个)。
3.3 读回字节的格式 1 2 3 4 status = i2c_smbus_read_byte(ara); /* ara->addr == 0x0c */ data.addr = status >> 1; /* 7 位从机地址 */ data.data = status & 1; /* 告警类型标志位 */
4. Linux 内核实现 4.1 相关文件
文件
作用
drivers/i2c/i2c-core-smbus.c
i2c_new_smbus_alert_device():创建 ARA 客户端(0x0c);i2c_setup_smbus_alert()
drivers/i2c/i2c-smbus.c
smbus_alert 驱动:GPIO 中断、for(;;) 循环读 ARA、调用 driver->alert()
drivers/i2c/i2c-core-base.c
适配器注册时调用 i2c_setup_smbus_alert(adap)
drivers/i2c/busses/i2c-rk3x.c
RK3506 I2C 主机驱动(无 硬件 SMBALERT,无 I2C Slave)
4.2 适配器注册时自动挂载 Alert 1 2 res = i2c_setup_smbus_alert(adap);
1 2 3 4 5 6 7 8 int i2c_setup_smbus_alert (struct i2c_adapter *adapter) { irq = device_property_match_string(parent, "interrupt-names" , "smbus_alert" ); if (irq == -EINVAL || irq == -ENODATA) return 0 ; return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL )); }
4.3 ARA 虚拟设备 1 2 3 struct i2c_board_info ara_board_info = { I2C_BOARD_INFO("smbus_alert" , 0x0c ), };
4.4 中断处理与循环读 ARA 流程:
1 2 3 4 5 6 7 8 SMBALERT# GPIO 中断 → smbus_alert() [threaded IRQ] → schedule work → smbalert_work() → for (;;) { i2c_smbus_read_byte(ara); /* 读 0x0C */ smbus_do_alert(); /* 匹配 client->addr,调 driver->alert() */ 若同一地址连续两次且未处理 → smbus_do_alert_force() 后 break; }
内核注释(仲裁与顺序):
1 2 3 4 5 6 status = i2c_smbus_read_byte(ara);
4.5 从设备驱动要求
实现 struct i2c_driver.alert 回调。
在 alert() 中 清除芯片内部告警状态 ,并确保释放 SMBALERT# (硬件规范要求)。
若已处理完毕,应使 alert() 的语义能让上层不再死循环;未实现 alert() 时会打印 no driver alert()。
5. 设备树配置(RK3506) 5.1 每条 I2C 总线仅一路 smbus_alert Linux I2C 核心 每条 adapter 只支持一个 名为 smbus_alert 的中断,不能 在同一条 &i2cN 上配置多根独立 SMBALERT# GPIO。
多路 SMBALERT# 的推荐做法:
场景
做法
BMC、PSU 各有一条 SMBALERT#
分到 不同 I2C 总线 (i2c0 / i2c2 等),各配 1 个 smbus_alert
硬件多根线接同一总线
硬件 线与 成一根 SMBALERT#,软件仍只配 1 个 GPIO
插拔/存在检测
子节点 present-gpios ,由各驱动处理,不是 SMBus Alert
5.2 板级示例(rk3506b-mpu.dtsi) i2c2 (PSU 共用 SMBALERT#,GPIO1_B6):
1 2 3 4 5 6 7 8 9 10 &i2c2 { /delete-property/ interrupts ; interrupts-extended = <&gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH> , <&gpio1 RK_PB6 IRQ_TYPE_LEVEL_LOW> ; interrupt-names = "irq" , "smbus_alert" ; aspower_d2000_0: power-supply@58 { reg = <0x58 > ; }; aspower_d2000_1: power-supply@59 { reg = <0x59 > ; }; aspower_d2000_2: power-supply@5a { reg = <0x5a > ; }; };
irq:I2C 控制器完成传输等中断。
smbus_alert:SMBALERT# 外部 GPIO 中断。
i2c0 (BMC SMBALERT#,示例中当前为注释状态):
5.3 内核配置
CONFIG_I2C=y
CONFIG_I2C_SMBUS=y
CONFIG_I2C_RK3X=y(或对应 Rockchip I2C 选项)
6. RK3506 限制说明
能力
RK3506 / i2c-rk3x
说明
I2C Master
支持
常规 i2c0/1/2
SMBus Alert(GPIO + 软件 ARA)
支持
依赖 DTS smbus_alert + CONFIG_I2C_SMBUS
I2C Slave / SMBus Host Notify
不支持
i2c-rk3x 无 I2C_FUNC_SLAVE,无法让 SoC 作总线从机
7. SMBus Host Notify(扩展,本板不适用)
从设备向地址 0x08 写通知,主机需 I2C 从模式 接收。
实现见 i2c-smbus.c 中 i2c_new_slave_host_notify_device(),依赖适配器 Slave 能力 。
RK3506 当前 i2c-rk3x 不支持 ,不能通过 DTS 单独启用。
8. 时序示意(0x58 + 0x5a 同时告警) 1 2 3 4 5 6 7 8 9 10 11 12 13 Dev@0x58 Dev@0x5a SMBALERT# Host | | | | |---- pull low ---|-----------------| | | |---- pull low ---| | | | |-- GPIO -->| | | | | Read ARA 0x0C |<--- win arb ---->| | | → 0x58 |-- release # ----| | | alert(0x58) | | | (仍低) | | | | | Read ARA 0x0C | |<--- only 0x5a -| | → 0x5a | |-- release # ----| | alert(0x5a) | | | (高) | 结束
9. 调试建议
确认 dmesg 中有 supports SMBALERT#(适配器注册成功后 i2c-smbus 打印)。
触发告警后抓 I2C 波形:应对 0x0C 出现读事务,数据字节含从机地址。
若同一地址反复出现:检查从设备 alert() 是否清除告警 及是否释放 SMBALERT#。
使用 present-gpios 的插拔事件 不会 走 ARA,勿与 SMBALERT# 混淆。
10. 参考
资料
路径 / 说明
SMBus Alert 内核注释
kernel/drivers/i2c/i2c-smbus.c
ARA 设备创建
kernel/drivers/i2c/i2c-core-smbus.c
I2C 绑定 interrupt-names
kernel/Documentation/devicetree/bindings/i2c/i2c.txt
SMBus 协议说明
kernel/Documentation/i2c/smbus-protocol.rst
RK3506 板级 DTS
kernel/arch/arm/boot/dts/rk3506b-mpu.dtsi
SMBus 规范
SMBus 1.1+,Appendix / SMBALERT# 章节
文档版本:基于 RK3506 MPU 工程内核与 rk3506b-mpu.dtsi 整理。
正在加载留言…