从 RGMII 到 SGMII:Linux 以太网 PHY 接口、时序与驱动配置科普讲解
-
-
- [从 RGMII 到 SGMII:Linux 以太网 PHY 接口、时序与驱动配置科普讲解](#从 RGMII 到 SGMII:Linux 以太网 PHY 接口、时序与驱动配置科普讲解)
- 引言
- [一、RGMII 为什么能"用 4 位数据线跑千兆"?](#一、RGMII 为什么能“用 4 位数据线跑千兆”?)
- [二、RGMII 的"双沿 DDR"到底在传什么?](#二、RGMII 的“双沿 DDR”到底在传什么?)
- [三、为什么 RGMII 必须补 2 ns 延迟?](#三、为什么 RGMII 必须补 2 ns 延迟?)
- [四、phy-mode 的几种取值是什么意思?](#四、phy-mode 的几种取值是什么意思?)
- [五、SGMII 和 RGMII 有什么本质区别?](#五、SGMII 和 RGMII 有什么本质区别?)
- [六、SerDes 在 SGMII 里做什么?](#六、SerDes 在 SGMII 里做什么?)
- [七、Linux 驱动里谁负责 RGMII 控制信号复用?](#七、Linux 驱动里谁负责 RGMII 控制信号复用?)
- [八、phy-mode 从设备树到硬件的完整链路](#八、phy-mode 从设备树到硬件的完整链路)
- [九、RGMII 调试时最容易踩的坑](#九、RGMII 调试时最容易踩的坑)
- 十、实际排查时可以按这条链走
- 小结
-
从 RGMII 到 SGMII:Linux 以太网 PHY 接口、时序与驱动配置科普讲解
从 RGMII 到 SGMII:Linux 以太网 PHY 接口、时序与驱动配置详解
引言
做嵌入式 Linux 网络开发时,经常会遇到 RGMII、SGMII、phy-mode、RGMII delay、SerDes 这些词。单独看每一个都不难,但把它们串起来,就容易混乱:为什么 RGMII 要补延迟?SGMII 为什么不需要?phy-mode 到底是谁在用?Linux 驱动里又该怎么看?
这篇博客尝试用一条清晰的链路,把这些概念串起来:从 RGMII 的 DDR 双沿采样开始,到 SGMII 的串行传输,再到 Linux 设备树中 phy-mode 的解析路径,最后落到实际调试时该怎么排查。
一、RGMII 为什么能"用 4 位数据线跑千兆"?
RGMII 的全称是 Reduced Gigabit Media Independent Interface,也就是"精简千兆媒体无关接口"。
它的核心特点是:
- 数据线只有 4 位:RXD3:0 / TXD3:0;
- 时钟频率是 125 MHz;
- 采用 DDR 双沿采样;
- 控制信号被复用到 TX_CTL / RX_CTL 上。
如果只是 125 MHz × 4 bit,带宽只有 500 Mbps,不够千兆。但 RGMII 每个时钟周期会采样两次:
- 上升沿传一次 4 bit;
- 下降沿再传一次 4 bit。
所以实际带宽是:
text
125 MHz × 4 bit × 2 = 1000 Mbps
这就是 RGMII 能用很少的引脚跑出千兆带宽的原因。
二、RGMII 的"双沿 DDR"到底在传什么?
RGMII 的数据线比较简单。一个 8 bit 字节会被拆成两半:
- 上升沿:传低 4 位,D3:0;
- 下降沿:传高 4 位,D7:4。
接收端把两次采样拼起来,就还原成一个完整字节。
比较麻烦的是控制线。RGMII 为了省引脚,把原来的多个控制信号合并到了 TX_CTL 和 RX_CTL 上。
| 信号 | 上升沿 | 下降沿 |
|---|---|---|
| TX_CTL | TX_EN | TX_EN XOR TX_ER |
| RX_CTL | RX_DV | RX_DV XOR RX_ER |
这里有一个常见误解:下降沿并不是直接传 TX_ER 或 RX_ER。
例如 RX_CTL:
- RXC 上升沿采到的是 RX_DV;
- RXC 下降沿采到的是
RX_DV XOR RX_ER。
所以要还原 RX_ER,必须同时看同一个时钟周期里的上升沿和下降沿:
text
RX_DV = RXC 上升沿时的 RX_CTL
RX_ER = RX_DV XOR (RXC 下降沿时的 RX_CTL)
TX_CTL 也是同样的道理。
三、为什么 RGMII 必须补 2 ns 延迟?
RGMII 的时钟是 125 MHz,一个周期 8 ns。DDR 双沿采样意味着每 4 ns 就要采一次数据。
如果时钟和数据完全同时到达,接收端就很难稳定采样。因为时钟沿正好落在数据跳变附近时,setup/hold 时间可能不够,导致采错。
所以 RGMII 标准要求:时钟和数据之间要有大约 2 ns 的偏移。
这个 2 ns 延迟可以放在三个位置:
- PHY 内部补:很多千兆 PHY 支持内部 TX/RX delay;
- MAC 内部补:部分 SoC 的 MAC 支持内部 delay;
- PCB 走线补:把数据线比时钟线绕长,产生传播延迟。
最常见的做法是让 PHY 内部补延迟,这样 PCB 布线时所有 RGMII 信号等长即可。
四、phy-mode 的几种取值是什么意思?
Linux 设备树中,phy-mode 用来描述 MAC 和 PHY 之间的接口模式。
常见 RGMII 取值如下:
| phy-mode | 含义 |
|---|---|
rgmii |
原始 RGMII,MAC/PHY 都不补 delay |
rgmii-id |
PHY 内部同时补 TX/RX delay |
rgmii-txid |
PHY 只补 TX delay |
rgmii-rxid |
PHY 只补 RX delay |
选择时有一个简单原则:delay 只能补一次,不能两边都补。
如果 PHY 已经通过 rgmii-id 补了 delay,MAC 侧通常就不应该再开内部 delay;如果 PHY 不支持内部 delay,就需要通过 MAC 侧 delay 或 PCB 走线来补。
五、SGMII 和 RGMII 有什么本质区别?
RGMII 是并行接口,SGMII 是串行接口。
SGMII 的信号非常简单:
- TX_P / TX_N:1 对差分发送线;
- RX_P / RX_N:1 对差分接收线;
- MDC / MDIO:管理接口;
- 可选参考时钟。
它没有独立的数据时钟线,时钟信息嵌在串行数据流里。
SGMII 的线速率是 1.25 Gbps ,采用 8B/10B 编码。也就是说,每传输 10 bit,只有 8 bit 是有效数据,所以有效带宽仍然是 1 Gbps。
这里会提到一个概念:UI,Unit Interval。
text
1 UI = 1 / 1.25 GHz = 0.8 ns = 800 ps
UI 就是串行链路上传输 1 bit 所占用的时间。对于 SGMII 来说,接收端每 800 ps 就要采样一次。
RGMII 里的 ~1 ns 指的是并行信号的 setup/hold 容差;SGMII 里的 800 ps UI 指的是串行链路的单比特时长。两者数字接近,但含义不同。
六、SerDes 在 SGMII 里做什么?
SerDes 是 Serializer/Deserializer 的缩写,也就是"串行器/解串器"。
在 SGMII 链路中,数据流动大致是这样的:
text
MAC 并行数据
→ SerDes 发送端串行化
→ TX_P / TX_N 差分线
→ PHY SerDes 接收端恢复
→ PHY 内部并行数据
发送端把并行数据变成高速串行比特流;接收端从串行比特流中恢复时钟和数据。
恢复时钟的关键模块叫 CDR,Clock Data Recovery。它不需要外部时钟线,而是通过观察数据流中的跳变沿,调整本地采样相位,使采样点落在每个 UI 的中间位置。
这也是 SGMII 比 RGMII 更适合长距离传输的原因:
- RGMII 是并行接口,多根线之间必须严格等长;
- SGMII 是差分串行接口,只要差分对内长度匹配即可;
- 差分信号抗干扰能力更强;
- 同一套 SerDes 通道可以升级到 2.5G、5G、10G。
代价是 SoC 必须集成 SerDes,PCB 需要做 100Ω 差分阻抗控制,调试门槛也更高。
七、Linux 驱动里谁负责 RGMII 控制信号复用?
很多人会先看 drivers/net/phy/dp83640.c,认为 RGMII 控制信号复用是由 PHY 驱动解析的。
其实不是。
dp83640.c 主要处理的是:
- MDIO 扩展寄存器访问;
- PTP 硬件时间戳;
- RX/TX 时间戳队列;
- PTP 时钟注册;
- 外部时间戳事件。
它并不解析 RGMII 的 TX_CTL/RX_CTL 复用关系。
而且 DP83640 本身是百兆 PHY,通常使用 MII/RMII 接口,并不是千兆 RGMII PHY。
RGMII 的双沿采样、控制信号解复用,通常由 MAC 侧硬件完成。例如 MAC 内部使用 IDDR/ODDR 或类似逻辑,把外部双沿信号拆成内部单沿数据。
Linux 驱动层面,真正关心 phy-mode 的通常是 MAC 驱动,而不是 PHY 驱动。
八、phy-mode 从设备树到硬件的完整链路
一条典型的解析链路是这样的:
text
设备树 dts
→ of_get_phy_mode() / fwnode_get_phy_mode()
→ enum phy_interface_t
→ MAC 驱动 probe / init
→ 配置 MAC 寄存器、时钟、内部 delay
→ PHY 驱动配置 PHY 侧 delay
→ RGMII 时序对齐
设备树示例:
dts
ethernet@xxx {
compatible = "snps,dwmac-xxx";
phy-mode = "rgmii-id";
phy-handle = <ð_phy>;
};
驱动中通常会这样获取接口模式:
c
enum phy_interface_t interface;
interface = of_get_phy_mode(pdev->dev.of_node, &err);
if (err)
return err;
of_get_phy_mode() 会把字符串 "rgmii-id" 解析成内核枚举 PHY_INTERFACE_MODE_RGMII_ID。
随后 MAC 驱动会根据这个枚举决定:
- 是否选择 RGMII 接口模式;
- 是否开启 MAC 侧 TX/RX delay;
- 是否调整 RGMII 时钟相位;
- 是否需要配置引脚复用。
PHY 驱动也会参考 phydev->interface,决定是否打开 PHY 内部 delay。
九、RGMII 调试时最容易踩的坑
-
两边都补 delay
phy-mode = "rgmii-id"表示 PHY 已经补了 delay,如果 MAC 驱动又开了内部 delay,链路很可能不通。 -
两边都不补 delay
phy-mode = "rgmii"表示都不补,但 PCB 也没有绕线延迟,时钟和数据几乎同时到达,采样窗口不够。 -
只看 phy-mode,不看 SoC 手册
同一个
rgmii,在不同 SoC 上可能意味着 MAC 补 delay,也可能意味着 MAC 不补 delay。 -
把 phy-mode 当成寄存器值
phy-mode 只是内核枚举,真正寄存器配置在 MAC 驱动里,不同平台完全不同。
-
误以为 PHY 驱动会解析 RGMII 双沿
RGMII 双沿采样由 MAC 硬件完成,PHY 驱动主要负责链路状态、自协商、速率和 delay 配置。
十、实际排查时可以按这条链走
- 确认设备树
phy-mode是什么; - 确认 PHY 是否支持内部 delay;
- 确认 SoC MAC 是否支持内部 delay;
- 查看 MAC 驱动如何处理该 phy-mode;
- 查看 PHY 驱动是否根据 interface 配置了 delay;
- 用
dmesg、驱动打印确认最终接口模式; - 必要时用示波器或逻辑分析仪观察 RGMII 波形;
- 确认 TXC/RXC 与数据、控制信号之间的相位关系。
小结
RGMII 和 SGMII 代表了两种不同的以太网接口思路。
RGMII 用并行 DDR 双沿采样,在少量引脚上实现千兆带宽,但时序约束紧,必须处理 2 ns 延迟。SGMII 用 SerDes 把数据串行化,通过差分对和 CDR 恢复时钟,布线更简单,扩展性更好,但对 SoC 和 PCB 要求更高。
在 Linux 系统中,phy-mode 是连接设备树、MAC 驱动和 PHY 驱动的关键字段。理解它并不代表寄存器值,而是代表一种接口模式约定,才能避免"两边都补 delay"或"两边都不补"的典型问题。