4. PHY寄存器地址映射

PHY芯片的寄存器空间,说白了就是一张地址表。你通过 mdio-tool 写入地址,然后读出或写入数据。这个地址怎么映射?里面有什么坑?我来聊聊我的经验。

我们知道,PHY寄存器地址通常分为三类:

  • 基本寄存器(MII寄存器,地址0~31)
  • 扩展寄存器(如Clause 45的MMD空间,地址可到更大范围)
  • 厂商特定寄存器(各个芯片厂自己定义的)

这三类在调试时都很常见,但用法和技巧完全不同。

4.1 基本寄存器:MII寄存器0~31

最早的标准是IEEE 802.3定义的MII管理接口。每个PHY有32个16位寄存器,地址0到31。我用 mdio-tool 直接访问,比如 mdio-tool -p eth0 read 0x01 0x00 可以读出PHY ID。

常用寄存器地址和功能,我整理了一张表,方便你对照:

地址 名称 读/写 说明
0x00 BMCR R/W 基本控制寄存器(复位、速度、双工、自协商等)
0x01 BMSR R 基本状态寄存器(链接状态、能力等)
0x02 PHYIDR1 R PHY标识符高16位
0x03 PHYIDR2 R PHY标识符低16位
0x04 ANAR R/W 自协商通告寄存器
0x05 ANLPAR R 自协商链路伙伴能力寄存器
0x06 ANER R 自协商扩展状态寄存器
0x10~0x1F 厂家专用 R/W 部分标准预留,实际多被厂商扩展使用
小提示: 我在调试PHY时,习惯先读 0x02 和 0x03 确认PHY型号。如果读出全是0或0xFFFF,那大概率通信有问题。

注意,如果你用的PHY只支持Clause 22(MII管理),那地址空间就只有这32个。但很多新PHY已经支持Clause 45了,地址空间就大了好几倍。

4.2 扩展寄存器:Clause 45 与 MMD

Clause 45引入了MMD(Management Data Model)概念。每个PHY可以有多达32个MMD(地址0~31),每个MMD内部又有64K个16位寄存器。总空间接近2M位,当然实际芯片不会全用。

对于Clause 45访问,mdio-tool 需要指定端口、设备地址、MMD地址和寄存器地址。比如:

# 读MMD 7(AN状态机)的寄存器0x0001
mdio-tool -p eth0 -v45 read 0x00 0x07 0x0001

这时你写错了地址,读回来可能就是零或者乱码。我曾经在调试Marvell PHY时,把MMD和寄存器地址搞反了,折腾了半小时才发现……后面记住了:mdio-tool -v45 的第一个地址是PHY设备地址,第二个是MMD,最后是寄存器偏移。

常见MMD编号和用途:

  • MMD 0: 保留
  • MMD 1: PMA/PMD(物理介质连接层)
  • MMD 2: WIS(广域接口子层)
  • MMD 3: PCS(物理编码子层)
  • MMD 7: 自协商状态机
  • MMD 31: 厂商特定

为什么要分这么多MMD?说白了就是为了支持更复杂的高速以太网标准(10GBASE-T、25GBASE-T等)。每个子层都独立管理自己的寄存器。

4.3 厂商特定寄存器

基本寄存器和扩展寄存器都是标准定义的,但每家PHY厂商都会把自己的扩展功能塞进“厂商特定寄存器”。这些地址一般位于MMD的特定范围(比如MMD 31),或者Clause 22的0x10~0x1F,或者Clause 45的MMD 3中自己定义的偏移。

调试这些寄存器,你首先得去翻PHY的datasheet或者寄存器手册。比如Marvell 88E1510的“LED控制寄存器”就在地址0x10(MMD 0下)。

注意: 厂商特定寄存器往往不公开或需要NDA。我曾经遇到一个Broadcom PHY,想改一个EEE(节能以太网)的触发阈值,翻遍公开资料也没找到,最后只好找FAE支持。所以如果你发现某个地址写进去没反应,别急着怀疑工具,也许它根本就是保留的。

另外,有些厂商会采用“页切换”机制:在同一地址写不同的“页号”来访问不同的寄存器组。比如RTL8211系列的“扩展寄存器”就需要先写页寄存器(0x1F),再写目标地址。这个技巧如果不看手册,光靠猜会抓狂。

我画了一张图,把三类寄存器地址映射的关系展示出来。你可以看出基本寄存器在Clause 22的0~31,Clause 45的MMD把空间延展了,而厂商特定寄存器则像“彩蛋”一样散落在各处。

PHY寄存器地址映射结构图 Clause 22 基本寄存器 MII寄存器0~31 0x00 BMCR(控制) 0x01 BMSR(状态) 0x02-0x03 PHY ID 0x04-0x05 自协商 ... 0x10-0x1F 厂商保留 (实际多被扩展) Clause 45 扩展寄存器 MMD 0~31 × 64K MMD 1: PMA/PMD MMD 3: PCS MMD 7: 自协商 ... MMD 31: 厂商特定 厂商特定寄存器 无固定标准 页切换机制 MMD 31 空间 部分厂家: Marvell、Broadcom、 Realtek、TI等 需手册查阅 调试建议 1. 优先读基本寄存器0x02-0x03确认PHY型号。 2. 使用 -v45 时注意参数顺序:PHY地址 + MMD + 寄存器。

4.4 什么时候用哪种映射?

你可能会问:我怎么知道这个PHY支不支持Clause 45?最简单的方法是读基本寄存器0x02和0x03,如果读到的是标准厂商ID(比如0x0141对应Marvell),然后尝试用Clause 45方式读MMD 0的寄存器0x0000,如果返回非0值,那就是支持的。

我个人的习惯是:

  • 老PHY(百兆/千兆基础型): 只用Clause 22基本寄存器调试就够了。
  • 新PHY(2.5G/5G/10G): 必须用Clause 45,甚至厂商特定页切换。

4.5 避坑:地址冲突与调试陷阱

调试时,我遇到过几个典型问题,分享给你。

  • 读回全0或0xFFFF: 一般是地址写错了,或者PHY没有响应。检查PLL(电源)和复位引脚。
  • 写0x10寄存器没反应: 可能这个寄存器属于MMD 3下的子空间,需要在写之前先设置MMD地址。有些PHY要求先写MMD地址到特定寄存器(如0x1D/0x1E),再通过标准地址读写。
  • 寄存器值不变: 可能该位是只读的,或者需要先解除锁定。我曾经被一个“影子寄存器”坑过——写入后需要再读一次才会生效。

核心经验: 调试任何PHY寄存器前,先花10分钟读datasheet的“Register Map”章节。哪怕只看一下地址范围,也能省去至少30分钟的猜测试错时间。我自己的笔记本里,专门为常用PHY(88E1510、RTL8211、BCM5461)画了简易地址简表。调试时直接对照,效率翻倍。