当前位置: 首页 > news >正文

[Linux] 从YT8531SH出发看Linux网络PHY驱动

从YT8531SH出发看Linux网络PHY驱动

博客关联代码下载链接:https://download.csdn.net/download/jz_ddk/91940396

文章目录

  • 从YT8531SH出发看Linux网络PHY驱动
    • 引言
    • 一、Linux网络驱动架构概述
    • 二、PHY驱动核心结构:phy_driver
      • 关键回调函数解析:
    • 三、PHY驱动加载全流程
      • 阶段一:基础设施初始化
      • 阶段二:设备探测与匹配
      • 阶段三:驱动绑定与初始化
      • 阶段四:网络子系统集成
    • 四、YT8531SH设备树配置详解
      • 配置选项详解:
    • 五、调试与问题排查
      • 常见问题及解决方法:
      • 调试工具:
    • 六、总结

引言

在嵌入式Linux系统中,网络功能是不可或缺的核心能力。一个完整的网络子系统由MAC控制器和PHY芯片组成,其中PHY(物理层接口)负责数模转换、链路协商等底层物理信号处理。本文将以Motorcomm YT8531SH PHY芯片的驱动为例,深入剖析Linux网络PHY驱动的框架结构、加载机制及设备树配置。

一、Linux网络驱动架构概述

Linux网络子系统采用分层设计架构:

  • MAC驱动:控制网络核心控制器,通常集成在SoC中,负责DMA、数据帧处理
  • PHY驱动:控制物理层收发器芯片,通过MDIO总线与MAC通信
  • MDIO总线:简单的两线串行接口(MDC和MDIO),用于MAC访问PHY寄存器
Linux网络子系统
MDIO总线
RGMII/MII
网络协议栈
IP/TCP/UDP
MAC驱动
以太网控制器
PHY驱动
YT8531SH
物理层芯片
YT8531SH
网络线缆

二、PHY驱动核心结构:phy_driver

Linux内核通过struct phy_driver抽象PHY驱动,YT8531SH驱动定义如下:

static struct phy_driver motorcomm_phy_drvs[] = {{.phy_id = PHY_ID_YT8531,           // 芯片标识符.phy_id_mask = PHY_ID_YT_MASK,     // 标识符掩码.name = "YT8531 Gigabit Ethernet", // 驱动名称.features = PHY_GBIT_FEATURES,     // 支持的功能特性.probe = &yt8531_probe,            // 设备探测函数.config_init = &yt8531_config_init, // 初始化配置.suspend = &genphy_suspend,        // 电源管理-挂起.resume = &genphy_resume,          // 电源管理-恢复.get_wol = &ytphy_get_wol,         // 获取WoL设置.set_wol = &yt8531_set_wol,        // 设置WoL设置.link_change_notify = &yt8531_link_change_notify, // 链路变化通知},// ... 其他型号支持
};

关键回调函数解析:

  1. probe函数:设备初始化时调用,进行硬件检测和私有数据结构设置
  2. config_init函数:PHY初始化配置,包括:
    • RGMII时序调整(解决PCB布线时序问题)
    • 驱动强度配置(优化信号完整性)
    • 时钟输出配置
  3. 电源管理函数:处理系统休眠/唤醒时的电源状态管理
  4. WoL函数:实现网络唤醒功能配置
  5. link_change_notify:链路状态变化回调,用于动态调整配置

三、PHY驱动加载全流程

PHY驱动的加载是一个从内核到硬件逐层初始化的过程,其完整流程如下:

硬件探测与匹配过程
读取PHY ID寄存器
MDIO Controller探测硬件
遍历MDIO总线驱动列表
PHY ID & Mask 匹配?
调用驱动的probe函数
继续下一个驱动
内核启动/模块加载
MDIO总线控制器驱动初始化
注册MDIO总线(mdio_bus_type)
PHY驱动注册(phy_driver_register)
将phy_driver添加到MDIO总线驱动列表
创建phy_device结构体
初始化PHY(调用config_init等)
MAC驱动通过of_phy_connect找到并连接PHY
链路状态轮询/中断
整个网络子系统就绪

阶段一:基础设施初始化

  1. MDIO总线注册:内核启动时,MDIO总线控制器驱动首先初始化,注册mdio_bus_type总线结构。

  2. 驱动注册:PHY驱动模块通过module_phy_driver(motorcomm_phy_drvs)宏注册到内核,实质是调用phy_driver_register函数。

  3. 导出设备表MODULE_DEVICE_TABLE(mdio, motorcomm_tbl)创建模块别名信息,供depmod工具生成modules.alias文件,实现模块自动加载。

阶段二:设备探测与匹配

  1. 硬件探测:MDIO总线控制器驱动扫描总线上所有可能地址(0-31)。

  2. 读取PHY ID:读取每个地址的MII_PHYSID1MII_PHYSID2寄存器,识别有效PHY设备。

  3. 总线匹配mdio_bus_match函数遍历已注册的phy_driver,计算phy_id = (PHYID1 << 16 | PHYID2)并与驱动标识符比较。

  4. 匹配算法(phy_id & phy_driver->phy_id_mask) == (phy_driver->phy_id & phy_driver->phy_id_mask)

阶段三:驱动绑定与初始化

  1. 创建设备并绑定驱动:匹配成功后创建phy_device结构体,与驱动绑定。

  2. 执行probe函数:调用驱动特定的probe函数(如yt8531_probe),完成硬件初始化。

阶段四:网络子系统集成

  1. MAC驱动连接PHY:MAC驱动从设备树解析phy-handle属性,通过of_phy_connect函数查找并连接PHY设备。

  2. PHY初始化和启动:调用.config_init.config_aneg函数,启动自动协商。

  3. 链路就绪:自动协商完成后,链路状态变为UP,网络子系统准备就绪。

四、YT8531SH设备树配置详解

基于驱动代码分析,YT8531SH的完整设备树配置如下:

&mdio0 {status = "okay";yt8531_phy: ethernet-phy@0 {compatible = "motorcomm,yt8531", "ethernet-phy-ieee802.3-c22";reg = <0>;  /* PHY地址,根据硬件连接确定 *//* 时钟输出配置 */motorcomm,clk-out-frequency-hz = <125000000>; /* 125MHz输出 *//* RGMII时序调整 - 接收延迟 */rx-internal-delay-ps = <1950>; /* 默认值1.95ns *//* RGMII时序调整 - 发送延迟 */tx-internal-delay-ps = <1950>; /* 默认值1.95ns *//* 驱动强度配置 */motorcomm,rx-clk-drv-microamp = <3970>; /* RX时钟驱动电流 */motorcomm,rx-data-drv-microamp = <3970>; /* RX数据驱动电流 *//* 电源管理配置 */motorcomm,auto-sleep-disabled; /* 禁用自动睡眠 */motorcomm,keep-pll-enabled; /* 保持PLL始终启用 *//* TX时钟调整配置(特定于JH7110 SoC) */motorcomm,tx-clk-adj-enabled; /* 启用TX时钟调整 */motorcomm,tx-clk-10-inverted; /* 10M速度下反转TX时钟 */motorcomm,tx-clk-100-inverted; /* 100M速度下反转TX时钟 */motorcomm,tx-clk-1000-inverted; /* 1000M速度下反转TX时钟 *//* 中断支持(如果连接了中断线) */interrupt-parent = <&gpio0>;interrupts = <12 IRQ_TYPE_EDGE_FALLING>;/* 复位配置(可选) */reset-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;reset-assert-us = <1000>; /* 复位断言时间1ms */reset-deassert-us = <2000>; /* 复位解除时间2ms */};
};&eth0 {status = "okay";phy-handle = <&yt8531_phy>;phy-mode = "rgmii-id"; /* 接口模式,根据硬件连接确定 */
};

配置选项详解:

  1. 时钟输出配置:驱动通过motorcomm,clk-out-frequency-hz属性配置PHY的时钟输出功能,在yt8531_probe函数中读取并配置YTPHY_SYNCE_CFG_REG寄存器。

  2. RGMII时序调整rx-internal-delay-pstx-internal-delay-ps属性解决PCB布线时序问题,由ytphy_rgmii_clk_delay_config函数处理。

  3. 驱动强度配置motorcomm,rx-clk-drv-microampmotorcomm,rx-data-drv-microamp属性优化信号完整性,通过yt8531_set_ds函数配置。

  4. 电源管理配置motorcomm,auto-sleep-disabledmotorcomm,keep-pll-enabled属性控制节能特性。

  5. TX时钟调整:特定于JH7110 SoC的时序适配功能,由yt8531_link_change_notify函数动态调整。

五、调试与问题排查

常见问题及解决方法:

  1. PHY无法识别:检查MDIO总线通信、PHY地址配置和电源状态

  2. 链路不稳定:调整RGMII时序延迟参数,优化驱动强度设置

  3. 性能下降:检查自动协商结果,确认双工模式和速度设置

  4. WoL功能失效:验证中断配置和魔术包设置

调试工具:

  • ethool -i eth0:查看PHY信息和驱动状态
  • mdio-tool:直接读写MDIO寄存器
  • 示波器:测量MDC/MDIO信号质量,验证时序参数

六、总结

通过分析YT8531SH PHY驱动,我们可以深入理解Linux网络PHY驱动的完整框架和加载机制。PHY驱动遵循标准的driver-bus-device模型,通过MDIO总线与MAC通信,依靠设备树提供硬件配置信息。

现代PHY驱动开发需要注意:

  1. 正确实现phy_driver结构体中的回调函数
  2. 充分利用设备树进行硬件配置,提高代码可移植性
  3. 妥善处理时序敏感操作(如RGMII延迟调整)
  4. 支持电源管理和网络唤醒等高级功能

YT8531SH驱动代码是一个优秀的范例,涵盖了PHY驱动开发的各个方面,为理解和开发Linux网络驱动提供了宝贵的参考。


研究学习不易,点赞易。
工作生活不易,收藏易,点收藏不迷茫 :)



文章转载自:

http://nzQm5Dil.prddj.cn
http://lTcv06Z0.prddj.cn
http://7BjIVTkH.prddj.cn
http://p1gdmgqq.prddj.cn
http://UeYFNtNR.prddj.cn
http://o5fyvXda.prddj.cn
http://ZqkPtJY5.prddj.cn
http://TbYj2GB7.prddj.cn
http://r7Gw41Se.prddj.cn
http://pwkaJDyT.prddj.cn
http://xkk3FaBb.prddj.cn
http://YlpPsABn.prddj.cn
http://pzsBkpDO.prddj.cn
http://SZXyXpmx.prddj.cn
http://yjoFvSOs.prddj.cn
http://Y68NJRFA.prddj.cn
http://Upaa0TY9.prddj.cn
http://TG4Wwlbh.prddj.cn
http://fePDUMxF.prddj.cn
http://2pTy0iNs.prddj.cn
http://1ebqyAdH.prddj.cn
http://ys8KS856.prddj.cn
http://yenfrJV1.prddj.cn
http://VjXsk8Q2.prddj.cn
http://Ly9DTCop.prddj.cn
http://ViFrN4Zz.prddj.cn
http://Vyz6aG7T.prddj.cn
http://Sh6m6JdQ.prddj.cn
http://azvoEPbP.prddj.cn
http://UQ4MHDNM.prddj.cn
http://www.dtcms.com/a/384394.html

相关文章:

  • ArcGIS定向影像(2)——非传统影像轻量级解决方案
  • 分享机械键盘MCU解决方案
  • Unity 性能优化 之 编辑器创建资源优化(UGUI | 物理 | 动画)
  • PostgreSQL——分区表
  • Elastic APM 高级特性:分布式追踪与机器学习优化
  • Ubuntu 服务器配置转发网络访问
  • Redis 数据结构源码剖析(SDS、Dict、Skiplist、Quicklist、Ziplist)
  • C#通讯之网络通讯 TCP UDP
  • 响应时间从5ms到0.8ms:威迈斯AI+DSP协同架构的突破与工程实践
  • 《WINDOWS 环境下32位汇编语言程序设计》第16章 WinSock接口和网络编程(2)
  • 算法--插入排序
  • 领码方案|权限即数据:企业系统中的字段级访问控制架构实战(Ver=1.0)
  • 【面试场景题】支付金融系统与普通业务系统的一些技术和架构上的区别
  • 数证杯顺心借JAVA网站重构详细版(服务器取证基础考点+检材+题目+重构视频)
  • 【Unity】【Photon】Fusion2中的玩家输入系统 学习笔记
  • Vue3 + Three.js 实战:自定义 3D 模型加载与交互全流程
  • 【Leetcode hot 100】102.二叉树的层序遍历
  • [Windows] 微软 .Net 运行库离线安装包 | Microsoft .Net Packages AIO_v09.09.25
  • java通过RESTful API实现两个项目之间相互传输数据
  • C++基础(13)——list类的模拟实现
  • C#/.NET/.NET Core技术前沿周刊 | 第 54 期(2025年9.8-9.14)
  • 快速上手 Jenkins
  • 【C++】STL--List使用及其模拟实现
  • Go语言双向链表list.List详解
  • 机器学习-Boosting
  • Jenkins运维之路(Jenkins流水线改造Day02-2-容器项目)
  • 【C++STL】list的详细用法和底层实现
  • Elastic APM 与 Elasticsearch 集成:构建完整可观测性栈
  • 从零搭建MCP Server:Python开发、部署与应用全流程实战
  • Mac本地Docker拉取镜像本地挂载项目