简介:本资源是针对RK3568平台适配YT8521S千兆以太网PHY芯片的完整驱动补丁包,面向嵌入式Linux内核开发者、BSP工程师及硬件驱动调试人员,解决RK3568在实际项目中接入YT8521S PHY时缺乏官方支持、链路无法建立或loopback测试失败等典型问题。压缩包共11个文件,含6个C源码(如dwmac-rk-tool.c、motorcomm.c)、2个头文件(motorcomm_phy.h等)、2个说明类txt文档及1个关键patch文件(0001_yt8521s_loopback_test.patch),覆盖驱动适配、寄存器配置、环回测试及内核4.4/4.19双版本兼容性处理。资源仅52KB,轻量高效,结构紧凑,便于快速集成与验证。目前已有1644人学习下载,读者可直接获取经过实测的PHY初始化序列、MAC-PHY联动调试要点、以及针对RK平台定制的phy_device.c修改逻辑,显著降低自研PHY驱动的开发门槛与排错周期。
1. RK3568 上跑通 YT8521S PHY:不是加个 .ko 就能亮灯,而是要捅穿 DWMAC 驱动层的三道墙
你手上有块 RK3568 开发板,网口插上 YT8521S 千兆 PHY 芯片,ifconfig eth0 up后ethtool eth0显示 link down,dmesg | grep phy里反复刷出phy_read failed或no PHY found——这不是线没插好,也不是 PHY 没供电,而是 RK 原生 kernel(4.4/4.19)压根不认识 YT8521S 这颗国产 PHY。RK_YTPHY_20210906.zip就是专治这个“认不出”的黑匣子补丁包:它不只提供motorcomm.c驱动源码,更关键的是把dwmac-rk-tool.c工具链、0001_yt8521s_loopback_test.patch回环测试补丁、以及适配 kernel4.4 和 kernel4.19 的两套phy_device.c修改逻辑全打包塞进一个 ZIP。它解决的不是“能不能用”,而是“怎么让 RK 的 DWMAC 控制器主动去握手 YT8521S 的寄存器地址、正确读取 MII 状态、并支持 loopback 自检”——这三步卡在绝大多数 RK3568 客户的量产前夜。适合正在做工业网关、边缘盒子、或国产化替代项目的嵌入式工程师,尤其当你已经试过CONFIG_REALTEK_PHY=y却发现根本没卵用时,这份补丁就是后悔药。
2. 从 ZIP 解包到内核编译:四步落地 YT8521S 驱动
2.1 解压与目录结构还原:别直接make modules,先看清补丁层级
unzip RK_YTPHY_20210906.zip -d rk_ytphy_work cd rk_ytphy_work ls -R输出会显示两个并行路径:kernel4.4/和kernel4.19/,各自包含dwmac-rk-tool.c、motorcomm_phy.h、motorcomm.c、phy_device.c、readme.txt。注意:这不是两个独立驱动包,而是同一套逻辑在不同 kernel 版本下的适配分支。kernel4.4下的phy_device.c修改集中在drivers/net/phy/realtek.c的兼容层注入;而kernel4.19则直接 patchdrivers/net/phy/motorcomm.c并 hook 进phy_init_driver()。readme.txt里那句 “apply patch first, then copy motorcomm.c” 是血泪经验——很多人跳过 patch 直接替换.c文件,结果编译报undefined reference to 'yt8521s_config_init',因为 patch 才真正注册了PHY_ID_MATCH_EXACT(0x00221710)这个 ID。
提示:
0001_yt8521s_loopback_test.patch是独立补丁,必须先git apply到你当前 kernel 源码树的drivers/net/ethernet/stmicro/stmmac/目录下,它修改的是stmmac_main.c中的stmmac_set_mac_loopback()函数,为后续dwmac-rk-tool发送 loopback 命令铺路。
2.2dwmac-rk-tool.c:不只是调试工具,它是 PHY 寄存器级操作的唯一入口
dwmac-rk-tool.c编译后生成的可执行文件,才是验证 YT8521S 是否真正“活过来”的终极手段。它绕过 kernel PHY 子系统,直接通过 RK3568 的 GMAC 寄存器(GMAC_MAC_MDIO_ADDR,GMAC_MAC_MDIO_DATA)读写 PHY 地址0x00(PHY ID1)、0x01(PHY ID2)、0x10(YT8521S 特有寄存器:Extended Status):
// dwmac-rk-tool.c 关键片段(kernel4.19 分支) int mdio_read(int phy_addr, int reg) { writel((phy_addr << 8) | reg, base + GMAC_MAC_MDIO_ADDR); while (readl(base + GMAC_MAC_MDIO_ADDR) & 0x1); // wait busy return readl(base + GMAC_MAC_MDIO_DATA) & 0xffff; }编译命令(需交叉工具链):
aarch64-linux-gnu-gcc -o dwmac-rk-tool dwmac-rk-tool.c -static运行前确保CONFIG_STMMAC_ETH和CONFIG_DWMAC_ROCKCHIP已启用,且stmmac模块已加载:
insmod stmmac.ko ./dwmac-rk-tool -p 0 -r 0x00 # 读 PHY ID1,应返回 0x0022 ./dwmac-rk-tool -p 0 -r 0x01 # 读 PHY ID2,应返回 0x1710 → 合起来就是 0x00221710,YT8521S 的标准 ID如果0x00和0x01返回值不对,说明硬件连接(MDIO clock/data 线)或 PHY 地址拨码(默认 0x00)有问题,此时 kernel 驱动再完善也无济于事。
2.3motorcomm.c编译与模块插入:两套 kernel 的 Makefile 写法差异
kernel4.4和kernel4.19的motorcomm.c不能混用,Makefile 写法也不同:
kernel4.4:需在
drivers/net/phy/Makefile中追加obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o并在
drivers/net/phy/Kconfig中添加:config MOTORCOMM_PHY tristate "Motorcomm YT8521S PHY support" depends on PHYLIB ---help--- Support for Motorcomm YT8521S Gigabit Ethernet PHY.kernel4.19:
motorcomm.c已被纳入主线drivers/net/phy/motorcomm.c,只需在drivers/net/phy/Makefile中确认:obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o且
CONFIG_MOTORCOMM_PHY=m(模块化)或=y(内置)。
编译后插入模块:
# kernel4.19 示例 make modules M=drivers/net/phy/ insmod drivers/net/phy/motorcomm.ko # 观察 dmesg 输出是否出现 "yt8521s: probed on mdio bus"若dmesg无输出,检查phy_device.c是否已按补丁修改:kernel4.19分支中,phy_drivers[]数组末尾必须新增:
{ .phy_id = 0x00221710, .phy_id_mask = 0xffffffff, .name = "Motorcomm YT8521S", .driver = &yt8521s_driver, },3. PHY 初始化失败的五大避坑指南:现象、原因、解法全对齐
3.1 现象:dmesg显示phy phy-ff290000.mdio:00: attached PHY driver [Motorcomm YT8521S],但ethtool eth0仍Link detected: no
- 原因:PHY 初始化函数
yt8521s_config_init()中未正确配置 YT8521S 的0x1f寄存器(Page Select),导致后续0x10(Extended Status)读取失败,link status 无法上报。 - 解决:检查
motorcomm.c中yt8521s_config_init()是否包含以下 page 切换逻辑:phy_write(phydev, 0x1f, 0x0000); // 切回 Page 0 phy_write(phydev, 0x1f, 0x0001); // 切到 Page 1(YT8521S 特有页) phy_write(phydev, 0x10, 0x0001); // Page 1 的 0x10 寄存器使能 auto-negotiation phy_write(phydev, 0x1f, 0x0000); // 切回 Page 0
3.2 现象:dwmac-rk-tool -p 0 -r 0x00返回0xffff,且mdio_read超时
- 原因:RK3568 的 MDIO clock 引脚(通常是 GPIO0_A0)未在 device tree 中配置为
mdio_clk功能,或 PHY 供电(AVDD/3.3V)未稳定。 - 解决:检查
rk3568-evb.dtsi中&gmac节点是否包含:
并用万用表实测 PHY 的 AVDD 引脚电压是否为 3.3V ±5%。pinctrl-names = "default"; pinctrl-0 = <&gmac_mdio>; ... &gmac_mdio { gmac_mdio: mdio-pins { pins = "gpio0_a0"; function = "mdio_clk"; }; };
3.3 现象:insmod motorcomm.ko成功,但cat /sys/bus/mdio_bus/devices/xxx:00/phy_status显示link: down,且phy_read在yt8521s_read_status()中返回-1
- 原因:YT8521S 的
0x00(Basic Control)寄存器 bit12(AN Enable)未置位,auto-negotiation 被禁用。 - 解决:在
yt8521s_config_init()结尾强制写入:
注意:phy_modify(phydev, MII_BMCR, 0, BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);BMCR_SPEED1000对应千兆模式,YT8521S 不支持百兆强制模式,必须走 AN。
3.4 现象:0001_yt8521s_loopback_test.patch应用后make报错stmmac_main.c:1234: undefined reference to 'stmmac_set_mac_loopback'
- 原因:patch 修改了
stmmac_main.c的函数声明,但未同步更新stmmac.h中的函数原型声明。 - 解决:手动在
include/linux/stmmac.h中添加:int stmmac_set_mac_loopback(struct net_device *dev, bool enable);
3.5 现象:ethtool -s eth0 speed 1000 duplex full autoneg off手动设速后 link 仍 up 不了
- 原因:YT8521S 不支持强制模式(Forced Mode),其 datasheet 明确要求
AN Enable = 1,否则 PHY 内部状态机不工作。 - 解决:删除所有
autoneg off的尝试,改用:ethtool -s eth0 autoneg on ethtool eth0 # 等待 5 秒,观察 Link detected: yes
4. Loopback 测试:用dwmac-rk-tool验证 PHY 寄存器级连通性
4.1 为什么必须做 loopback?因为ethtool只验 link,dwmac-rk-tool才验 PHY 内部通路
ethtool的Link detected: yes只表示 PHY 检测到远端信号,不代表 PHY 自身收发通道正常。YT8521S 的 loopback 模式分两级:
- PHY internal loopback(寄存器
0x00bit14):TX 信号在 PHY 内部直连 RX,不经过外部 PIN; - MAC loopback(
stmmac_set_mac_loopback()):GMAC 内部 TX 直连 RX,PHY 完全旁路。
只有PHY internal loopback通过,才能证明 YT8521S 的模拟前端(SerDes)和数字控制逻辑全部就绪。
4.2 执行 loopback 测试的完整命令流
# 步骤1:确保 PHY 已初始化且 link up ethtool eth0 | grep "Link detected" # 步骤2:启用 PHY internal loopback(写 0x00 寄存器 bit14) ./dwmac-rk-tool -p 0 -w 0x00 -v 0x4140 # 0x4140 = 0x2140 | (1<<14),保留 AN 使能 # 步骤3:读取 0x01 寄存器(BMSR),bit11 应为 1(Jabber Detect),bit2 应为 1(Link Status) ./dwmac-rk-tool -p 0 -r 0x01 # 返回值应含 0x0400(bit10)和 0x0004(bit2) # 步骤4:发送 dummy packet 并捕获回环帧(需提前启动 tcpdump) tcpdump -i eth0 -c 1 icmp & ping -c 1 192.168.1.1 # 若 ping 通,说明 loopback 数据通路闭环注意:
-v 0x4140中的0x2140是 YT8521S 默认的BMCR值(AN Enable + Speed1000 + Full Duplex),| (1<<14)是置位 loopback 位。硬编码此值比phy_modify更可靠,避免 kernel PHY 子系统干扰。
4.3 Loopback 失败时的寄存器诊断表
| 寄存器地址 | 期望值(Loopback ON) | 实际值含义 | 排查方向 |
|---|---|---|---|
0x00(BMCR) | 0x4140 | 若为0x3140(bit14=0) | loopback 位未写入,检查dwmac-rk-tool写操作是否成功 |
0x01(BMSR) | 0x796d(bit15~0 全 set) | 若 bit11=0 | PHY 内部时钟未锁定,检查 AVDD 和 REFCLK |
0x10(Ext Status) | 0x0001(1000BASE-T capable) | 若为0x0000 | Page 1 未正确切换,检查0x1f寄存器写入顺序 |
0x1f(Page Select) | 0x0000(Page 0) | 若为0x0001 | page 切换后未切回,导致后续寄存器读写错位 |
5. 进阶技巧:把dwmac-rk-tool改造成自动校准脚本,省掉每次手动dmesg | grep
5.1 为什么需要自动校准?因为量产时每块板的 PHY 供电纹波不同,导致0x10寄存器读取稳定性差异
YT8521S 的0x10(Extended Status)寄存器在电源噪声大时会偶发读取失败(返回0x0000),但0x00/0x01总是稳定的。因此,一个健壮的初始化脚本不应只依赖单次读取,而应做三次重试 + 校验:
#!/bin/bash # yt8521s_calibrate.sh PHY_ADDR=0 MAX_RETRY=3 read_ext_status() { for i in $(seq 1 $MAX_RETRY); do val=$("./dwmac-rk-tool" -p $PHY_ADDR -r 0x10 2>/dev/null) if [ -n "$val" ] && [ "$val" != "0x0000" ]; then echo "$val" return 0 fi sleep 0.1 done echo "FAIL: 0x10 read timeout" return 1 } # 主流程 echo "=== YT8521S Calibration Start ===" if ! ./dwmac-rk-tool -p $PHY_ADDR -r 0x00 | grep -q "0x0022"; then echo "ERROR: PHY ID1 mismatch" exit 1 fi ext_val=$(read_ext_status) if [ "$ext_val" = "FAIL: 0x10 read timeout" ]; then echo "CRITICAL: Extended Status unstable, check AVDD ripple" exit 1 else echo "OK: Extended Status = $ext_val" fi # 启用 loopback 并验证 ./dwmac-rk-tool -p $PHY_ADDR -w 0x00 -v 0x4140 sleep 0.5 if ./dwmac-rk-tool -p $PHY_ADDR -r 0x01 | grep -q "0x.*0400"; then echo "SUCCESS: Loopback enabled and link stable" else echo "FAIL: Loopback not confirmed" exit 1 fi5.2 如何集成进 buildroot?三步搞定开机自检
- 将
dwmac-rk-tool和yt8521s_calibrate.sh放入board/rockchip/rk3568/rootfs_overlay/; - 在
board/rockchip/rk3568/post-build.sh中添加:install -m 0755 ${BOARD_DIR}/rootfs_overlay/dwmac-rk-tool ${TARGET_DIR}/usr/bin/ install -m 0755 ${BOARD_DIR}/rootfs_overlay/yt8521s_calibrate.sh ${TARGET_DIR}/etc/init.d/S99yt8521s-calibrate - 创建
/etc/init.d/S99yt8521s-calibrate:#!/bin/sh /usr/bin/yt8521s_calibrate.sh >> /var/log/yt8521s.log 2>&1
这样,每台设备上电后都会自动执行 PHY 校准,并将结果记入日志。产线工人只需看/var/log/yt8521s.log最后一行是否为SUCCESS,无需懂dmesg或ethtool。
5.3 一个血泪习惯:每次改motorcomm.c,必先git diff drivers/net/phy/motorcomm.c对比原始补丁
我见过太多人,在kernel4.19分支上修完yt8521s_config_init(),却忘了kernel4.4分支的phy_device.c也要同步 patch。更糟的是,有人把kernel4.19的motorcomm.c直接拷进kernel4.4目录,结果编译时struct phy_driver成员名对不上(kernel4.4用phy_id,kernel4.19用phy_id_mask)。从那以后我每次打开motorcomm.c,第一件事就是git diff看改动是否严格对应当前 kernel 版本的补丁内容,第二件事是grep -r "0x00221710" .确认 PHY ID 在phy_drivers[]中只出现一次。这多花 30 秒,但能省掉 3 小时 debug 时间。希望帮到你。
本文还有配套的精品资源,点击获取