新闻详情

新闻详情

首页 / 资讯中心 / 详情

RK平台YTPHY PHY驱动移植实战:从拆包、配置到验证

发布时间:2026/10/2 14:38:35来源:尧图网络
RK平台YTPHY PHY驱动移植实战:从拆包、配置到验证
简介面向RK3568平台的YT8521S以太网PHY驱动补丁专为嵌入式驱动开发与系统移植工程师设计重点是解决YT8521S在RK3568平台上的驱动适配与PHY芯片调试问题。资源按kernel4.19与kernel4.4两个内核版本分目录组织各自包含PHY驱动源码、头文件与说明文档并单独附带一个loopback回环测试补丁方便对照不同内核版本的适配差异快速验证芯片工作状态缩短问题排查时间。压缩包内共包含11个文件其中6个C源文件、2个头文件、2个TXT说明文档及1个patch补丁整体大小仅52KB结构简洁、定位清晰便于按内核版本直接检索。当前已有1644人学习下载。通过这份补丁包读者既可学习RK3568平台以太网PHY驱动的移植流程也能直接复用或裁剪其中代码和补丁同时理解Motorcomm PHY驱动与MAC侧配合的修改思路减少自行分析驱动、寄存器配置和内核编译的时间成本。1. RK_YTPHY_20210906.zip 到底是什么一个瑞芯微 PHY 驱动移植包的自白第一次见到 RK_YTPHY_20210906.zip 这个包是客户发来一句新板子网口起不来这个驱动你们试一下。解压之前我先掂量了一下这个名字RK 是瑞芯微平台的常规前缀YTPHY 大概率指裕太微YT系列以太网 PHY 芯片20210906 是发布版本日期。这是一个典型的 SoC 平台外设驱动适配包瑞芯微主控搭配第三方 PHY厂商把验证过的驱动代码、设备树补丁和移植说明打成一个 zip 发过来。它解决的是实打实的量产问题——板子网口 link 不上、速率协商不对、mac 与 phy 之间不匹配。适合正在做 RK 平台 BSP、linux 驱动移植或者硬件 bring-up 的嵌入式工程师也适合硬件工程师拿来核对原理图设计。这篇就按我自己处理这类包的流程来讲。2. 先拆包再动手从 zip 伪加密到 PHY 驱动包的内部结构2.1 解压前先用 zipinfo 验包别被伪加密和 missing entry 坑了拿到 zip 包第一反应是直接 unzip这其实是翻车率最高的操作。厂商发的包经常经过多次转发、Windows 下压缩再拷贝到 Linux文件头可能被改过甚至有 zip 伪加密的情况。伪加密不是真加密只是 zip 的 general purpose bit flag 第 0 位被置了 1解压时工具误以为有密码。特征是 unzip 会提示输入密码但用 7z 又能正常打开。我一般先跑一遍zipinfo -v看压缩条目状态再决定怎么解# 查看 zip 包的详细条目重点看 Encryption 和压缩方式 zipinfo -v RK_YTPHY_20210906.zip | head -60 # 列出所有文件不实际解压 unzip -l RK_YTPHY_20210906.zip # 如果解压报错或提示加密用 7z 强制列出并解压 7z l RK_YTPHY_20210906.zip 7z x RK_YTPHY_20210906.zip -o./RK_YTPHY_20210906/第一条命令的-v会输出每个文件的压缩方式、CRC 校验值和加密状态。如果看到Encryption: AES-256但手里没密码基本可以断定是伪加密或者厂商加密失误。这时候用十六进制编辑器打开 zip 头找到对应条目 central directory 里的general purpose bit flag把第 0 位清零就能正常解压。如果碰到missing zip entry通常是 zip64 扩展信息损坏多半是工具之间互相转换导致的7z 对它兼容性最好优先用 7z 而不是 unzip。解压之后先别急着改代码对一下文件数量、大小和目录层级确认有没有缺文件。驱动移植包少了 dts 补丁是最常见的但单看 zip 列表是看不出来的得解压完结合 README 一起确认。提示伪加密和真加密在 zipinfo 输出里都能看到Encryption标记但真加密需要密码才能列出文件内容伪加密则只是 flag 置位用 7z 直接列出内部文件通常没问题。2.2 包里的三件套驱动源码、设备树补丁和移植说明解开 RK_YTPHY_20210906.zip 之后里面通常是三类东西PHY 驱动源码一个或几个.c/.h文件、设备树补丁.dts/.dtsi片段或 patch 文件、以及一篇 README 或移植说明。有些厂商还会附上编译好的.ko模块但这东西和内核版本强绑定我一般只当参考不当交付物。先读 README 是这批操作里最划算的一步。它通常会写明这个驱动对应哪个芯片型号、支持 rgmii 还是 rmii 接口、需要内核什么版本的 phy 框架、以及作者验证过的配置。如果包里有 patch 文件我会直接打开看它改了哪些位置——很多情况下它不是给当前内核版本打的需要手动合。源码部分重点关注三个符号phy_driver结构体、match_phy_device函数、config_init回调。这三个决定了驱动能不能被内核识别、能不能匹配上对应 PHY、初始化时干了什么。后面第 3 章会具体展开。设备树补丁一般改两处一是 gmac 节点下的mdio子节点增加ethernet-phy节点并指定reg二是可能涉及复位 GPIO、时钟频率、phy-mode的调整。这部分和硬件原理图强相关厂商默认值未必适配你的板子必须对照原理图核对。2.3 PHY 驱动在 RK 平台的工作原理mdio 总线、PHY ID 和协商理解了包的结构还得知道这套驱动在内核里是怎么被拉起来的否则移植过去出了问题根本不知道去哪查。RK 平台的 gmac一般叫 gmac0 / gmac1通过 mdio 总线访问外部 PHY 芯片。mdio 只有两根线一根时钟一根数据读 PHY 寄存器全靠它。PHY 芯片上电后内核的 mdio 驱动会扫描总线上 0 到 31 这 32 个地址往每个地址读 PHY ID 寄存器寄存器 2 和 3各 16 位拼起来 32 位能读回合法 ID 的地址就认为挂了一个 PHY。这个 PHY ID 就是我们驱动匹配的关键。内核的 PHY 驱动框架用一个phy_driver结构体描述一个驱动里面包含phy_id、phy_id_mask和name。匹配逻辑是把读回来的 ID 和phy_id_mask做与操作再和phy_id比较相等就匹配上。所以厂商给自己的芯片定驱动时PHY ID 的厂商 OUI 部分必须读出来填对mask 要能把同一系列不同型号的差异位屏蔽掉。匹配成功之后内核会调用驱动的config_init做初始化然后进入自动协商流程。协商结果决定当前速率是 10M、100M 还是 1000M双工模式是半双工还是全双工。RK 平台的 gmac 再把phy-modergmii / rmii和协商结果结合起来配置 MAC 侧。整套链路里最容易出问题的就是 PHY ID 没匹配上导致内核 fallback 到 genphy 通用驱动通用驱动虽然也能让链路通但厂商定制的初始化逻辑比如 LED 配置、特定寄存器校准全都不会执行。3. 把 YTPHY 驱动移植进 RK 内核设备树、Kconfig 与驱动注册3.1 内核菜单配置CONFIG_PHY_ROCKCHIP 之外的第二个选择RK 平台的内核默认把CONFIG_PHY_ROCKCHIP编进去这个驱动负责内置的 PHY 或者作为 genphy 兜底。外接 YTPHY 芯片时我们通常把这套驱动编成模块或者直接编进内核。先看厂商驱动有没有提供 Kconfig 片段没有的话自己补一个。以下是我常用的写法# 在 drivers/net/phy/ 目录下新增 Kconfig 条目依赖 MDIO_BUS config YTPHY_PHY tristate YT PHY support depends on MDIO_BUS help Support for YT ethernet PHY.在drivers/net/phy/Makefile里加一行obj-$(CONFIG_YTPHY_PHY) ytphy.o。如果你的内核是 buildroot 或 yocto 管理记得在 defconfig 里把CONFIG_YTPHY_PHYy或m写进去否则 menuconfig 里开了下次编译又没了。3.2 设备树里加 PHY 节点reg 地址、复位 GPIO 和时钟设备树是移植的重头戏。RK 平台一般用gmac0节点在它下面挂mdio子节点再在mdio下挂 PHY 节点。以下是一个典型配置gmac0 { phy-mode rgmii; clock_in_out input; snps,reset-gpio gpio3 RK_PB4 GPIO_ACTIVE_LOW; snps,reset-active-low; reset-delay-us 20000; pinctrl-names default; pinctrl-0 gmac0_rgmii_pins; mdio { compatible snps,dwmac-mdio; #address-cells 1; #size-cells 0; phy0: ethernet-phy0 { reg 0x0; /* 如果需要中断触发 link 变化加上 interrupts */ interrupt-parent gpio3; interrupts RK_PB3 IRQ_TYPE_LEVEL_LOW; }; }; };这段配置里最关键的是reg 0x0它决定了内核去 mdio 总线哪个地址扫 PHY。如果你的 PHY 芯片通过硬件 pin 把地址拉成了 1这里就写0x1写错直接扫不到。snps,reset-gpio是 RK gmac 驱动解析的属性上电时先拉低再拉高复位 PHYreset-delay-us决定复位后等多久再开始 mdio 枚举。20ms 是我习惯的下限有些 PHY 上电要求 50ms 以上具体看 datasheet。pinctrl-0这里引用的是gmac0_rgmii_pins得确认你板子的 dtsi 里有没有这个 pinmux 定义。如果没有dts 编译倒是能过但 mac 侧的数据线根本没有复用成 rgmii 功能phy 通了也收不到数据。3.3 驱动代码的最小挂载phy_driver 结构体和一个 probe内核 PHY 驱动框架演进过几次老的phy_driver.probe和新的read_mmd/read_status都有人用。厂商给的 2021 年的驱动包大概率还是经典写法。一个最小可用的驱动骨架长这样#include linux/phy.h static int ytphy_config_init(struct phy_device *phydev) { /* 厂商初始化序列写特定寄存器校准、配置 LED 模式 */ phy_write(phydev, 0x1f, 0x0001); /* 切换到扩展寄存器页 */ phy_write(phydev, 0x10, 0x1234); /* 写入校准值 */ phy_write(phydev, 0x1f, 0x0000); /* 切回标准页 */ return 0; } static int ytphy_probe(struct phy_device *phydev) { /* 可以在这里读取芯片版本做差异化处理 */ return 0; } static struct phy_driver ytphy_drivers[] { { .phy_id 0x0000ffff, /* 从 datasheet OUI 换算 */ .phy_id_mask 0xffff0000, .name YT ethernet PHY, .probe ytphy_probe, .config_init ytphy_config_init, .config_aneg genphy_config_aneg, .read_status genphy_read_status, .suspend genphy_suspend, .resume genphy_resume, }, }; module_phy_driver(ytphy_drivers); MODULE_LICENSE(GPL);phy_id不是乱填的它由芯片的 OUI 和型号位组成。算的方法是把 datasheet 给的 OUI组织唯一标识符转成 32 位 PHY ID 格式再与寄存器 2/3 读出来的值对照。我这里用0x0000ffff表示你需要在填你自己芯片的实际值。phy_id_mask用来屏蔽差异位比如同一系列不同型号低 12 位不同就 mask 掉低 12 位让它们共用同一个驱动。注意module_phy_driver会把数组里的所有驱动注册到内核 PHY 驱动链表中所以这个数组可以放多个条目。如果你发现驱动编进去后没有匹配先用dmesg | grep mdio看枚举时读到的 PHY ID 是多少再回来对着改phy_id别凭感觉猜。4. 移植完怎么验证编译、启动日志和 PHY 寄存器读写4.1 编成模块还是编进内核两种方式的选择驱动的挂载方式直接影响调试效率。我的习惯是先编成模块CONFIG_YTPHY_PHYm这样改了代码只需要重新编译模块、拷贝到板子 insmod不用每次烧整个 kernel。内核启动后自动 load 依赖顺序也简单。等模块验证稳定了再改回y编进内核减少启动时依赖 modules 文件系统的环节。模块编译的常见问题是拿当前运行的 kernel 源码编但 build 目录不干净。我用以下命令确认版本一致再编# 查看板子上的内核版本 uname -r # 本地源码目录确认版本匹配并准备好 modules_prepare make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- modules_prepare # 单独编译 ytphy 模块 make ARCHarm64 CROSS_COMPILEaarch64-linux-gnu- Mdrivers/net/phy/ CONFIG_YTPHY_PHYm modules # 拷贝到板子后加载注意加载顺序 insmod ytphy.komodules_prepare这一步不能省它生成编译模块必需的Module.symvers和头文件产物。交叉编译工具链前缀以你实际用的为准RK 官方 SDK 一般是aarch64-linux-gnu-。加载模块后用lsmod确认挂上了再看dmesg | tail有没有驱动注册信息。4.2 dmesg 里看 mdio 枚举和 PHY ID确认驱动 match 上驱动注册后能不能匹配启动日志立刻见分晓。重点关注这几行# 查看 mdio 总线枚举和 PHY 探测 dmesg | grep -E mdio|phy|gmac|eth # 查看 PHY 是否用上了我们的驱动 dmesg | grep -E ytphy|YTPHY|attached正常的日志里能看到类似mdio_bus 0xfe2b0000.ethernet: MDIO device at address 0 is YT ethernet PHY后面跟attached PHY driver [YT ethernet PHY]。这表示 PHY 地址和驱动都对了。如果看到的是genphy开头的驱动名说明我们的驱动没匹配上多半是phy_id不对或者 mask 把不该屏蔽的位也屏蔽了。还有一种情况是日志里直接报mdio_bus: probe of ... failed with error -5这通常是 PHY 上电时序问题复位 GPIO 没拉或者供电晚了。先用电表测 PHY 的 clock 引脚有没有时钟、reset 引脚电平是否正常再回来看代码。4.3 用 mdio 工具和 devmem2 读寄存器link 状态和速率协商日志验证只能确认驱动挂上真正的链路质量和协商结果还得读寄存器。内核提供了mdio工具也可以直接devmem2读写 mdio 控制器的寄存器但对新手我更推荐用前者因为它的语义直白# 读 PHY 地址 0 的基本模式状态寄存器寄存器 1 mdio eth0 phy 0 reg 1 # 读协商伙伴能力寄存器寄存器 5 mdio eth0 phy 0 reg 5 # 读 PHY ID 寄存器 2 和 3 mdio eth0 phy 0 reg 2 mdio eth0 phy 0 reg 3寄存器 1 是 BMSRbit 2 是 link 状态读回来 bit2 为 1 表示链路 up。寄存器 5 是 LPA低 6 位表示对端协商到的 10M/100M/1000M 能力。如果 lpa 全为 0常见原因是网线对端没起来或者 PHY 的时钟源有问题寄存器根本读不到有效值。寄存器 2 和 3 拼起来的 PHY ID 要和驱动里phy_id对一下。我遇到过厂商手册写的是一个 ID实际芯片又是另一个 ID 的情况批次不同、封装版本不同都可能有差异。以实际读出来的为准这比手册可靠。提示mdio工具读不到数据时先排除 PHY 供电和复位。用devmem2 0xfe2b0000 32的方式直接读 mdio 控制器状态寄存器也可以但不同芯片地址差异大不如先看原理图确认 PHY 地址和供电网络。5. 移植踩坑记录解压报错、PHY 扫描不到和 link 不稳定5.1 zip 解压报 missing zip entry换工具也没用现象unzip 解压到一半报missing zip entry文件不全换 7z 解压后少了 README。原因这个 zip 是被某些老旧的 Windows 压缩工具生成central directory 里的 entry 偏移和 local header 不一致。7z 能列出所有 entry 但不代表能正确恢复所有文件。解决先zipinfo -v看报错 entry 附近有没有可疑的字段再用 Python 的zipfile模块重新打包做一次归一化import zipfile with zipfile.ZipFile(RK_YTPHY_20210906.zip, r) as zin: with zipfile.ZipFile(RK_YTPHY_20210906_ok.zip, w, zipfile.ZIP_DEFLATED) as zout: for item in zin.infolist(): data zin.read(item.filename) zout.writestr(item, data)这段代码把原来有问题的 zip 重新读出来再写一遍新的 zip 的 entry 偏移全部重新计算解压就不会再报 missing entry。5.2 设备树 reg 写错PHY 始终 scanning 不到现象启动日志里没有任何 mdio device 被枚举ifconfig eth0 up报No such device或者一直link is not ready。原因PHY 芯片的硬件地址 pin如 PHYAD[2:0]被原理图拉成 0b001dts 里写的reg 0x0内核去地址 0 读 ID 读不到东西。解决回到原理图查 PHYAD 引脚的上拉下拉电阻换算成二进制地址改 dts 里reg值。如果地址被硬件固定死只能改 dts个别板子留了电阻跳线可以焊下来改地址来迁就软件。改完后 dmesg 里应该出现对应地址的枚举。5.3 复位 GPIO 时序不对link 灯亮了但 ping 不通现象PHY 能被识别link 状态是 up速率也对但ping丢包率 100%。原因rk 的 gmac 驱动在复位 PHY 之后立刻开始读寄存器、发数据包但 PHY 内部固件还在加载环路测试没通过直接进入错误状态。解决把reset-delay-us调大我调过 50ms 才稳定。同时确认snps,reset-active-low的方向——有的板子复位是高有效这里写反了会导致复位信号一直生效PHY 处于复位中link 灯亮是假象灯直接吃了复位前的电平。5.4 50M 时钟没配PHY 完全不上电现象mdio 扫描每次都失败PHY 寄存器读出来全是 0xff量 PHY 的 clock 引脚没有波形。原因PHY 的时钟源比如 25M/50M 晶体或 SoC 输出的 clk没有在 dts 里使能。RK 平台的 gmac0 有一个clk_mac输出引脚需要在 pinctrl 里配成 clock 输出功能。解决检查原理图里 PHY 的 XI 引脚接的是无源晶体还是 SoC 的 clock 输出。如果是后者在 dts 的 pinctrl 里加上gmac0_miim和对应的 clk 输出 pinmux并且在 gmac 节点的assigned-clocks里把频率设对。这块很容易被忽略因为原理图上看着有器件实际上没有驱动它工作。5.5 内核自带的 PHY 驱动抢先匹配代码没跑进你的 probe现象dmesg 里显示attached PHY driver [Generic PHY]我们自己编的 ytphy.ko 加载了但没匹配。原因内核的 genphy 驱动是百年兜底但它不会主动抢人抢人的多半是内核里另一个同类芯片厂商驱动OUI 相同导致 mask 之后匹配上了别人的phy_driver。解决先确认我们芯片的 PHY ID 和已有驱动的 OUI 段是否真的相同。如果是同 OUI 的大小号芯片就要看 mask 位和型号位怎么划分。改法有两个要么在别人的驱动里把 mask 收紧要么在我们的驱动里把phy_id_mask放宽到能覆盖整个系列并让我们的驱动在匹配链表里排在前面。优先级由内核里注册顺序决定编进内核时Makefile里obj-y的顺序会影响它但最可靠的办法是把我们驱动 config 设为y编进内核同时把有冲突的其它驱动设为m不自动加载。6. 把这套移植做成一劳永逸的 BSP 维护流程每次换内核版本都重新手打 dts 和驱动这套流程撑不过三个项目。我最后会做两件事把厂商的补丁转换成 git format-patch 风格的 commit按目录归档再把验证命令写成脚本放到 SDK 的device/rockchip/common/下面让以后接手的同事一条命令跑完。补丁归档的路径我会用kernel/drivers/net/phy/ytphy/放源码kernel/arch/arm64/boot/dts/rockchip/放 dts 补丁然后每个补丁文件头部写明适用芯片型号、对应提交 ID 和验证日期。RK_YTPHY_20210906 这个包我归档时会把它重命名成带芯片型号的格式比如rk3568-ytphy-gmac0.dtsi这样半年后再看也知道它属于哪块板子。验证脚本固定检查四样东西PHY ID 读数、驱动名、link 状态、速率协商结果。脚本写成以下几种命令行#!/bin/bash # BSP bring-up 快速验证脚本 dmesg | grep -E mdio|attached PHY | tail -10 mdio eth0 phy 0 reg 1 # 期望 bit21 mdio eth0 phy 0 reg 5 # 期望非零 ethtool eth0 # 期望 Speed: 1000Mb/s, Duplex: Full这套流程走完我也养成了一个习惯所有外设驱动包拿到手第一反应永远是先看 hash、看解压日志、看 README 的日期字段而不是直奔源码编译。很多“灵异问题”其实在第一步验包的时候就已经埋下了。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

ProAgent:重构LLM智能体的主动性与协作范式 2026/10/2 16:08:34

ProAgent:重构LLM智能体的主动性与协作范式

1. ProAgent不是又一个“调用LLM封装API”的玩具项目最近翻AAAI 2024录用论文列表时,一眼扫到ProAgent: Building Proactive Cooperative Agents with Large Language Models这个标题,心里咯噔一下——不是因为名字里带“Pro”显得高级,而是它…

阅读更多 →
OpenRig开源驾驶舱DIY:用铝型材打造高性价比模拟赛车座舱 2026/10/2 16:08:34

OpenRig开源驾驶舱DIY:用铝型材打造高性价比模拟赛车座舱

1. OpenRig 在解决一个什么现实问题 作为一个既喜欢折腾 DIY 又沉迷模拟赛车的玩家,我这两年时间几乎把市面上能买到的成品驾驶舱都研究了一遍,最后却选择了一个叫 OpenRig 的开源项目来自己搭建。如果你不了解这个圈子,可能会觉得花几千块买…

阅读更多 →
双指针算法详解:从对撞指针到滑动窗口的实战与复杂度分析 2026/10/2 16:08:27

双指针算法详解:从对撞指针到滑动窗口的实战与复杂度分析

1. 双指针算法到底解决什么问题?1.1 从暴力枚举聊起我最早接触双指针算法,是被一道题逼的:在有序数组里找两个数,让它们的和等于目标值。当时第一反应就是暴力枚举——两层 for 循环嵌套,把所有组合都试一遍。逻辑没问…

阅读更多 →
前端图片字节形态详解:Blob、ArrayBuffer与base64 2026/10/2 16:08:27

前端图片字节形态详解:Blob、ArrayBuffer与base64

1. 一张图片在浏览器里到底有几个"身子":先把Blob、ArrayBuffer、base64的关系捋直 刚接触图片处理的前端,八成都会被同一件事绕晕:同样是一张图片,为什么有的地方要传文件对象,有的地方要传一串以 data:im…

阅读更多 →
Windows 安装 Open Interpreter 完整指南:一条命令本地运行代码,3 分钟上手 2026/10/2 16:08:27

Windows 安装 Open Interpreter 完整指南:一条命令本地运行代码,3 分钟上手

Windows 安装 Open Interpreter 完整指南:一条命令本地运行代码,3 分钟上手 【免费下载链接】openinterpreter A coding agent for open models like Kimi K3 and GLM 5.3 项目地址: https://gitcode.com/GitHub_Trending/op/openinterpreter 先说…

阅读更多 →
轮胎橡胶数字化:从数据流到门尼预测与硫化曲线建模 2026/10/2 16:08:21

轮胎橡胶数字化:从数据流到门尼预测与硫化曲线建模

简介:这是一份聚焦轮胎橡胶行业工艺与自动化应用的演示文稿资料,适合轮胎制造技术人员、自动化工程师及行业研究者学习参考。资源共一个文件,为pptx格式演示文稿,压缩包仅4.59MB,内容精炼而信息密集。资料以罗克韦尔自…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉