4. 设备树MAC节点核心属性:compatible、reg、interrupts、phy-mode等
设备树中以太网MAC节点的核心属性是驱动与硬件之间契约的载体。正确配置这些属性,是确保MAC控制器被正确识别、寄存器空间被正确映射、中断信号被正确路由以及PHY接口模式被正确初始化的前提。本节将逐一拆解这些关键属性,并给出典型配置示例。
4.1 核心属性总览
一个完整的MAC节点通常包含以下五类核心属性,它们分别对应驱动匹配、地址空间、中断机制、接口协议和PHY连接关系。
| 属性名 | 作用域 | 数据类型 | 是否必需 | 典型值示例 |
|---|---|---|---|---|
| compatible | 驱动匹配 | 字符串列表 | 是 | "fsl,imx6q-fec" |
| reg | 地址映射 | <u32> 数组 |
是 | <0x02188000 0x4000> |
| interrupts | 中断信号 | <u32> 数组 |
是 | <0 118 4> |
| phy-mode | 接口协议 | 字符串 | 是 | "rgmii-id" |
| phy-handle | PHY绑定 | phandle | 推荐 | <&phy0> |
关键提示: 在Linux内核中,
compatible 属性是驱动与设备绑定的第一道关卡。如果该属性值与驱动中 of_match_table 列表不匹配,后续所有属性都不会被解析。
4.2 compatible:驱动匹配的钥匙
compatible 属性是一个字符串列表,用于标识设备的具体型号。内核通过该属性在设备驱动模型中查找对应的驱动程序。其格式通常为 "厂商,型号",并可以包含多个备选字符串,按优先级从高到低排列。
/* 示例:i.MX6ULL 的 FEC 控制器 */
&fec1 {
compatible = "fsl,imx6ul-fec", "fsl,imx6q-fec";
/* ... */
};
上述示例中,内核会优先尝试匹配 "fsl,imx6ul-fec",如果失败则回退到 "fsl,imx6q-fec"。这种机制允许同一驱动兼容多个硬件版本。
4.3 reg:寄存器地址与内存映射
reg 属性定义了MAC控制器的寄存器基地址和地址范围。它通常由一组 <地址 长度> 对组成,对应芯片手册中MAC模块的起始地址和占用的地址空间大小。
/* 示例:STM32MP1 的 GMAC 控制器 */
ethernet: ethernet@5800a000 {
compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
reg = <0x5800a000 0x2000>;
/* ... */
};
在驱动中,内核通过 of_iomap() 或 platform_get_resource() 函数读取该属性,并将物理地址映射到内核虚拟地址空间,从而实现对MAC控制器的寄存器读写。
避坑指南: 地址范围(第二个值)必须大于或等于芯片手册中MAC模块实际占用的寄存器空间。如果设置过小,驱动访问高偏移寄存器时可能导致系统崩溃或总线错误。
4.4 interrupts:中断信号配置
interrupts 属性描述了MAC设备向CPU发送中断请求的信号线。其格式依赖于中断控制器(通常是GIC)的规范,一般包含中断类型、中断号和触发方式。
| 中断控制器类型 | 属性格式 | 示例 | 说明 |
|---|---|---|---|
| GIC (ARM) | <中断类型 中断号 触发方式> |
<0 118 4> |
类型0=SPI,中断号118,触发方式4=高电平 |
| RISC-V PLIC | <中断号 触发方式> |
<31 2> |
中断号31,触发方式2=边沿触发 |
| 简单中断控制器 | <中断号> |
<5> |
仅指定中断号 |
/* 示例:Allwinner H3 的 EMAC 中断配置 */
emac: ethernet@1c30000 {
compatible = "allwinner,sun8i-h3-emac";
reg = <0x01c30000 0x10000>;
interrupts = <0 82 4>;
/* ... */
};
4.5 phy-mode:MAC与PHY的接口协议
phy-mode 属性定义了MAC控制器与外部PHY芯片之间的数据接口标准。不同的接口模式决定了数据线的数量、时钟频率和信号时序。常见的模式包括MII、RMII、RGMII及其变体。
| phy-mode 值 | 数据线数量 | 最大速率 | 时钟源 | 适用场景 |
|---|---|---|---|---|
"mii" |
16 | 100 Mbps | 外部晶振/MAC | 传统10/100M以太网 |
"rmii" |
6 | 100 Mbps | 外部50MHz时钟 | 引脚受限的嵌入式设计 |
"rgmii" |
12 | 1 Gbps | 125MHz时钟 | 千兆以太网 |
"rgmii-id" |
12 | 1 Gbps | MAC内部延迟 | 千兆以太网(含内部延迟) |
"rgmii-rxid" |
12 | 1 Gbps | 仅RX延迟 | 千兆以太网(RX延迟) |
"rgmii-txid" |
12 | 1 Gbps | 仅TX延迟 | 千兆以太网(TX延迟) |
"sgmii" |
4(串行) | 1 Gbps | SerDes | 高速背板/光纤 |
/* 示例:不同 phy-mode 的配置对比 */
/* RGMII 模式,MAC 内部不添加延迟 */
&mac1 {
phy-mode = "rgmii";
phy-handle = <&phy1>;
};
/* RGMII 模式,MAC 内部添加 TX 和 RX 延迟 */
&mac2 {
phy-mode = "rgmii-id";
phy-handle = <&phy2>;
};
/* RMII 模式,用于引脚数较少的场景 */
&mac3 {
phy-mode = "rmii";
phy-handle = <&phy3>;
};
重要警告:
rgmii 与 rgmii-id 的区别在于时钟延迟的添加位置。如果PCB走线长度导致时钟与数据信号之间出现相位偏移,必须选择合适的延迟模式。错误的配置会导致链路无法建立或数据包错误。
4.6 综合配置示例
以下是一个完整的MAC节点配置示例,展示了所有核心属性的协同工作方式。
/* 完整 MAC 节点示例:基于 NXP i.MX8M Plus 的 FEC */
&fec1 {
compatible = "fsl,imx8mp-fec", "fsl,imx6q-fec";
reg = <0x30be0000 0x10000>;
interrupts = <0 118 4>, <0 119 4>, <0 120 4>;
interrupt-names = "int0", "pps", "wakeup";
phy-mode = "rgmii-id";
phy-handle = <ðphy0>;
phy-supply = <®_eth_phy>;
clocks = <&clk IMX8MP_CLK_ENET1_ROOT>,
<&clk IMX8MP_CLK_ENET1_TIME_ROOT>;
clock-names = "ipg", "ptp";
status = "okay";
mdio {
#address-cells = <1>;
#size-cells = <0>;
ethphy0: ethernet-phy@1 {
compatible = "ethernet-phy-ieee802.3-c22";
reg = <1>;
reset-gpios = <&gpio4 22 GPIO_ACTIVE_LOW>;
reset-assert-us = <10000>;
reset-deassert-us = <20000>;
};
};
};
4.7 常见配置错误与排查
- compatible 不匹配: 驱动无法加载,dmesg 中显示
No driver found。检查内核配置是否包含对应驱动,以及 compatible 字符串是否完全一致。 - reg 地址错误: 驱动 ioremap 失败,返回 NULL。核对芯片手册中的基地址和地址范围,注意地址对齐要求。
- interrupts 配置错误: 中断无法触发或触发异常。检查中断号是否在中断控制器范围内,触发方式是否与硬件设计一致。
- phy-mode 不匹配: 链路无法建立,PHY 状态显示
Link is Down。确认 MAC 和 PHY 都支持相同的接口模式,并检查 PCB 走线延迟。
调试技巧: 使用
devicetree/unittest 框架或 dt-validate 工具对设备树进行静态检查。在驱动中添加 dev_info() 打印解析到的属性值,与预期值进行对比,可以快速定位配置问题。