RK3568 以太网 PHY 移植没那么难:YT8521SC 接入全过程拆解
前言使用的是内核自带的 motorcomm 驱动。该驱动支持多种 Motorcomm 系列 PHY 芯片包括 YT8521SC。驱动支持的芯片YT8511YT8521 (包括 YT8521SC)YT8531RK631YT8521SC通过硬件引脚设置PHY地址通过引脚电平状态来决定PHY地址。PHY地址范围看通常是0-315位地址对应十六进制 0x0 ~ 0x1F。PHY地址计算公式PHY地址 (ADDR2 2) | (ADDR1 1) | ADDR0硬件连接一共2路以太网分别接到GAMC0和GMAC1控制器。YT8521SC-CA通过3个引脚决定PHY地址PHYAD0、PHYAD1、PHYAD2 三个引脚的组合可以设置 0-7 的地址。根据原理图3个引脚都接了GND所以得出PHY的地址是0x00。2路PHY硬件连接都是差不多的PHY地址都是0x00。GMAC0这一路PHY的复位引脚是GPIO0_C6。GMAC1这一路的复位引脚是GPIO0_C2。YT8521SC移植内核配置RK 使用 Synopsys DesignWare GMAC驱动路径drivers/net/ethernet/stmicro/stmmac/需要使能的内核选项CONFIG_STMMAC_ETHy CONFIG_DWMAC_GENERICy CONFIG_DWMAC_ROCKCHIPy # RK 平台特定支持 CONFIG_MDIO_BUS_MUX_GPIOy # 多路 MDIO (如有) CONFIG_DWMAC_RK_AUTO_DELAYLINEy # RGMII delayline 自动扫描PHY 驱动对应使能CONFIG_PHY_MOTORCOMMy这个配置在drivers/net/phy/Kconfig中定义。内核源码位置kernel/drivers/net/phy/motorcomm.cRGMII Delayline 调试 (1000M 稳定性关键)这是 RK GMAC 移植最容易出问题的环节Delayline的系统上调试有如下方法第一种是手动扫描# 进入 delayline sysfs echo 1 /sys/devices/platform/fe2a0000.ethernet/phy_lb_scan cat /sys/devices/platform/fe2a0000.ethernet/rgmii_delayline第二种是配置内核自动扫描CONFIG_DWMAC_RK_AUTO_DELAYLINEy编写/修改设备树节点GMAC1控制器设备节点kernel/arch/arm64/boot/dts/rockchip/rk3568.dtsigmac0: ethernetfe2a0000 { compatible rockchip,rk3568-gmac, snps,dwmac-4.20a; reg 0x0 0xfe2a0000 0x0 0x10000; interrupts GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH, GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH; interrupt-names macirq, eth_wake_irq; rockchip,grf grf; clocks cru SCLK_GMAC0, cru SCLK_GMAC0_RX_TX, cru SCLK_GMAC0_RX_TX, cru CLK_MAC0_REFOUT, cru ACLK_GMAC0, cru PCLK_GMAC0, cru SCLK_GMAC0_RX_TX, cru CLK_GMAC0_PTP_REF, cru PCLK_XPCS, cru CLK_XPCS_EEE; clock-names stmmaceth, mac_clk_rx, mac_clk_tx, clk_mac_refout, aclk_mac, pclk_mac, clk_mac_speed, ptp_ref, pclk_xpcs, clk_xpcs_eee; resets cru SRST_A_GMAC0; reset-names stmmaceth; snps,mixed-burst; snps,tso; snps,axi-config gmac0_stmmac_axi_setup; snps,mtl-rx-config gmac0_mtl_rx_setup; snps,mtl-tx-config gmac0_mtl_tx_setup; status disabled; mdio0: mdio { compatible snps,dwmac-mdio; #address-cells 0x1; #size-cells 0x0; }; gmac0_stmmac_axi_setup: stmmac-axi-config { snps,wr_osr_lmt 4; snps,rd_osr_lmt 8; snps,blen 0 0 0 0 16 8 4; }; gmac0_mtl_rx_setup: rx-queues-config { snps,rx-queues-to-use 1; queue0 {}; }; gmac0_mtl_tx_setup: tx-queues-config { snps,tx-queues-to-use 1; queue0 {}; }; }; gmac1: ethernetfe010000 { compatible rockchip,rk3568-gmac, snps,dwmac-4.20a; reg 0x0 0xfe010000 0x0 0x10000; interrupts GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH, GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH; interrupt-names macirq, eth_wake_irq; rockchip,grf grf; clocks cru SCLK_GMAC1, cru SCLK_GMAC1_RX_TX, cru SCLK_GMAC1_RX_TX, cru CLK_MAC1_REFOUT, cru ACLK_GMAC1, cru PCLK_GMAC1, cru SCLK_GMAC1_RX_TX, cru CLK_GMAC1_PTP_REF, cru PCLK_XPCS, cru CLK_XPCS_EEE; clock-names stmmaceth, mac_clk_rx, mac_clk_tx, clk_mac_refout, aclk_mac, pclk_mac, clk_mac_speed, ptp_ref, pclk_xpcs, clk_xpcs_eee; resets cru SRST_A_GMAC1; reset-names stmmaceth; snps,mixed-burst; snps,tso; snps,axi-config gmac1_stmmac_axi_setup; snps,mtl-rx-config gmac1_mtl_rx_setup; snps,mtl-tx-config gmac1_mtl_tx_setup; status disabled; mdio1: mdio { compatible snps,dwmac-mdio; #address-cells 0x1; #size-cells 0x0; }; gmac1_stmmac_axi_setup: stmmac-axi-config { snps,wr_osr_lmt 4; snps,rd_osr_lmt 8; snps,blen 0 0 0 0 16 8 4; }; gmac1_mtl_rx_setup: rx-queues-config { snps,rx-queues-to-use 1; queue0 {}; }; gmac1_mtl_tx_setup: tx-queues-config { snps,tx-queues-to-use 1; queue0 {}; }; };设备树文件kernel/arch/arm64/boot/dts/rockchip/rk3568-iot-ddr4.dtsi根据实际硬件情况向GMAC节点追加或修改gmac0 { phy-mode rgmii; // PHY接口模式 clock_in_out output; // 时钟方向 snps,reset-gpio gpio0 RK_PC6 GPIO_ACTIVE_LOW; // 复位GPIOGPIO0_C6 snps,reset-active-low; // 复位低电平有效 snps,reset-delays-us 100000 200000 150000; //复位时序 assigned-clocks cru SCLK_GMAC0_RX_TX, cru SCLK_GMAC0; assigned-clock-parents cru SCLK_GMAC0_RGMII_SPEED, cru CLK_MAC0_2TOP; assigned-clock-rates 0, 125000000; pinctrl-names default; pinctrl-0 gmac0_miim gmac0_tx_bus2 gmac0_rx_bus2 gmac0_rgmii_clk gmac0_rgmii_bus; tx_delay 0x30; // TX延迟值 rx_delay 0x10; // RX延迟值 phy-handle rgmii_phy0; // PHY句柄 status okay; }; gmac1 { phy-mode rgmii; clock_in_out output; snps,reset-gpio gpio0 RK_PC2 GPIO_ACTIVE_LOW; // GPIO0_C2 snps,reset-active-low; snps,reset-delays-us 100000 200000 150000; assigned-clocks cru SCLK_GMAC1_RX_TX, cru SCLK_GMAC1; assigned-clock-parents cru SCLK_GMAC1_RGMII_SPEED, cru CLK_MAC1_2TOP; assigned-clock-rates 0, 125000000; pinctrl-names default; pinctrl-0 gmac1m1_miim gmac1m1_tx_bus2 gmac1m1_rx_bus2 gmac1m1_rgmii_clk gmac1m1_rgmii_bus; tx_delay 0x30; rx_delay 0x10; phy-handle rgmii_phy1; status okay; };1、设以下是phy-mode可选择的参数本次移植设置为置 phy-mode 为 rgmiirgmiiRGMIIMAC 提供 TX/RX delayrgmii-rxidRGMIIPHY 提供 RX delay (推荐兼容性好)rgmii-txidRGMIIPHY 提供 TX delayrmiiRMII 模式sgmiiSGMII (RK3568/RK3588 支持)2、配置时钟参数时钟参数根据不同phy-mode有不同的设置。GMAC时钟配置涉及DTS以下几个关键属性gmac0 { clock_in_out input; // 时钟方向: input / output clocks cru SCLK_GMAC0, // MAC 主时钟 cru SCLK_GMAC0_RX_TX, cru SCLK_GMAC0_RGMII_SPEED, cru CLK_MAC0_REFOUT; clock-names stmmaceth, // 驱动 required mac_clk_rx_tx, clk_mac_speed, clk_mac_refout; assigned-clocks cru SCLK_GMAC0; assigned-clock-parents cru SCLK_GMAC0_SRC; // 时钟源选择 };clock-names各ge通道的意义如下clock-name说明stmmacethMAC 主时钟驱动时钟门控mac_clk_rx_txRGMII 的 TX/RX 时钟 (125MHz) 或 RMII 的 REF_CLK (50MHz)clk_mac_speed速率切换时钟 (RGMII: 125M/25M/2.5MRMII: 50M)clk_mac_refoutREF_CLK 输出给外部 PHY 的时钟 (可选)关键点是 clock_in_out assigned-clock-parents 决定了时钟走线方式phy-mode为RGMII 模式时1、PHY 提供 125MHz 时钟给MAC也就是输入inputclock_in_out input; assigned-clocks cru SCLK_GMAC0_RX_TX, cru SCLK_GMAC0; assigned-clock-parents gmac0_clk, cru SCLK_GMAC0_RX_TX;PHY 的 125MHz CLK125 输出 → SoC 的 ETH_CLK 引脚 →**font stylecolor:rgb(0, 206, 185);background-color:rgb(252, 252, 252);gmac0_clk/font**SoC 用外部输入的 125M 分频出 125M/25M/2.5M 给 RGMII2、SoC 输出 125MHz 给 PHY 也就是SOC给PHY提供时钟方向为outputclock_in_out output; // 时钟方向 assigned-clocks cru SCLK_GMAC0_RX_TX, cru SCLK_GMAC0; assigned-clock-parents cru SCLK_GMAC0_RGMII_SPEED, cru CLK_MAC0_2TOP; assigned-clock-rates 0, 125000000;SoC 内部 PLL 分频给 GMAC DIV GMAC再分配 输出 125M 时钟给 PHY。当phy-mode是RMII模式时1、外部 50MHz 晶振 (SoC input)phy-mode rmii; clock_in_out input; assigned-clocks cru SCLK_GMAC0_RX_TX; assigned-clock-parents cru SCLK_GMAC0_RMII_SRC;2、SoC 输出 50MHz 给 PHY (output)phy-mode rmii; clock_in_out output; assigned-clocks cru SCLK_GMAC0_RX_TX; assigned-clock-parents cru CLK_GMAC0_RMII_M0; assigned-clock-rates 50000000;上电后可以再sysfs中确认时钟# 查看 GMAC 时钟是否使能 cat /sys/kernel/debug/clk/gmac0_clk/clk_rate # 预期: 125000000 cat /sys/kernel/debug/clk/sclk_gmac0_rx_tx/clk_rate cat /sys/kernel/debug/clk/clk_gmac0_phy/clk_rate # RMII 50M 参考时钟总的来说时钟的设置关键如下clock_in_out 决定方向assigned-clock-parents 选时钟源assigned-clock-rates 定频率。最常用的是 RGMII input 模式PHY 提供 125M → SoC 内部路由到 mac_clk_rx_tx。3、配置复位 GPIO、复位有效电平、复位时序snps,reset-gpio gpio0 RK_PC6 GPIO_ACTIVE_LOW; // 复位GPIOGPIO0_C6 snps,reset-active-low; // 复位低电平有效 snps,reset-delays-us 100000 200000 150000; //复位时序设备树复位时序三个值snps,reset-delays-us a b c;它们含义如下位置参数名含义典型值adelay before reset拉低 RESET 引脚前的等待时间。从 phy_device_register()或 phy_probe()开始计时等待 a μs 后才把复位引脚拉低。主要用于某些需要先稳定电源的 PHY。0breset pulse widthRESET 引脚保持低电平的持续时间复位脉冲宽度。PHY 芯片在这个低电平期间被复位。这个值必须 ≥ PHY 手册中的 t_reset。10000~20000 μscdelay after reset释放 RESET拉高后等待 PHY 内部 PLL 稳定/自校准完成才能通过 MDIO 访问其寄存器。在这个等待期间驱动不会访问 PHY。必须 ≥ PHY 手册中的 t_ready。50000~100000 μsYT8521SC-CA 的复位时序如下符号描述MinTypMax单位T2Reset 低电平保持时间 (reset pulse width)10--msT1所有电源稳定到 Reset 释放的时间10--ms手册未要求上电后等待再拉低可直接复位未作要求设置数值也没啥问题。手册同样未给出t_ready值参考同类千兆 PHY 经验值来取值。这里移植就设置成如下值了snps,reset-delays-us 100000 200000 150000;4、配置TX/RX 延迟经验值参考TX delay: 0x30 ~ 0x50步进 0x01RX delay: 0x20 ~ 0x40目标ping 不丢包 iperf 吞吐率正常tx_delay/rx_delay 与 PHY 芯片和硬件设计密切相关主要是以下影响因素1、PHY芯片差异不同 PHY 的内部 delay 特性不同2、PCB走线长度这个是最关键的。RGMII delayline 本质上就是在补偿 PCB 上 clock 与 data 的走线长度差TX_CLK 与 TXD[0:3] 之间的长度差会影响tx_delayRX_CLK 与 RXD[0:3] 之间的长度差 会影响rx_delay每差 1 inch ≈ 150~170ps 延时差3、SoC 芯片本身的工艺偏差 (PVT)4、工作频率- **font stylecolor:rgb(23, 23, 23);background-color:rgb(252, 252, 252);1000M (125MHz)/font**font stylecolor:rgb(23, 23, 23);background-color:rgb(252, 252, 252); delay 要求严格需要精确调/font - **font stylecolor:rgb(23, 23, 23);background-color:rgb(252, 252, 252);100M (25MHz)/font**font stylecolor:rgb(23, 23, 23);background-color:rgb(252, 252, 252); 时序裕量大通常不需要调 delayline/font - font stylecolor:rgb(23, 23, 23);background-color:rgb(252, 252, 252);RMII 模式下完全不涉及 delayline/fontRK官方推荐的调试方法先用 PHY 提供 delayrgmii-rxid再用 SoC delayline 微调phy-mode rgmii-rxid; // PHY 负责 RX delay tx_delay 0x3c; // SoC 只调 TX 侧使能自动扫描也就是内核配置使能CONFIG_DWMAC_RK_AUTO_DELAYLINE每个板子启动时自动扫描最佳值解决 PVT 差异。5、指定 phy-handlemdio0 { rgmii_phy0: phy0 { compatible ethernet-phy-ieee802.3-c22; reg 0x0; // PHY地址 }; }; mdio1 { rgmii_phy1: phy0 { compatible ethernet-phy-ieee802.3-c22; reg 0x0; // PHY地址 }; };对于 PHY 节点需要做以下配置 1、在 MDIO 总线上添加 PHY 节点2、设置 compatible 为 ethernet-phy-ieee802.3-c223、设置正确的 reg PHY 地址移植总结移植主要是三步1、首先肯定是配置内核确保GMAC驱动已经使能了。2、然后编写 DTS 节点phy-mode、时钟、delayline、复位引脚、复位时序等3、最后调试RGMII delayline确保网卡稳定。常见问题排查现象排查方向DMA init failed检查 clock/pinctrl 是否正确PHY not found检查 MDIO 连接、PHY 地址、复位时序Link up 但 ping 不通delayline 值不合适速率只有 100MRGMII 时钟或 delayline 问题TX queue 0 timeout检查 IO-DOMAIN 电压、PCB 走线iperf 吞吐低delayline 不优、驱动中断亲和性RK官方参考文档Linux/Common/GMAC/Rockchip_Developer_Guide_Linux_GMAC_CN.pdfLinux/Common/GMAC/Rockchip_Developer_Guide_Linux_GMAC_Mode_Configuration_CN.pdfLinux/Common/GMAC/Rockchip_Developer_Guide_Linux_GMAC_RGMII_Delayline_CN.pdf