第2章 PHY寄存器体系:地址空间与分类
搞PHY驱动,第一件事就是摸清它的寄存器地图。
说白了,PHY芯片内部就是一排排寄存器,你通过MDIO/MDC这根串行总线去读写它们。但寄存器不是乱放的,IEEE 802.3规定了一套标准布局,厂家又在上面加了自己的私货。
我个人习惯先把地址空间画成三个区:0~15是必修课,16~31是选修课,再往后就是厂商的“黑盒”。
2.1 地址空间总览
每个PHY设备用5位地址线(ADDR[4:0]),最多32个寄存器地址(0x00~0x1F)。但这32个地址并非都归你自由使用:
- 0x00~0x0F(0~15):MII标准寄存器。所有符合IEEE 802.3的PHY都必须实现,内容统一,读出来直接解析就是状态。
- 0x10~0x1F(16~31):扩展寄存器。部分标准功能(如千兆协商、EEE)放在这里,但不是强制。
- >0x1F(地址超过31):厂商自定义寄存器。一般通过“页”(Page)或“子地址”方式访问,每个厂家都不一样。
2.2 MII标准寄存器(0x00~0x0F)
这部分是每个PHY工程师的必修课。你想想看,无论你用的PHY是哪家产的,0x00控制寄存器、0x01状态寄存器、0x02/0x03 PHY ID、0x04自协商能力……这些读出来的值,格式完全一致。
| 地址 | 名称 | 关键位/作用 |
|---|---|---|
| 0x00 | 控制寄存器 (BMCR) | 位15: Reset, 位13: Speed(1000), 位12: 双工, 位8: 自协商使能 |
| 0x01 | 状态寄存器 (BMSR) | 位2: Link状态, 位5: 自协商完成, 位6: 远端故障 |
| 0x02~0x03 | PHY ID 寄存器 | OUI + 型号 + 版本,识别芯片的唯一凭据 |
| 0x04 | 自协商能力 (ANAR) | 速率/双工能力通告,用于与对端协商 |
| 0x05 | 自协商伙伴能力 (ANLPAR) | 对端发过来的能力,看它支持什么 |
| 0x06 | 自协商扩展 (ANER) | LP自协商完成、LP页能力等 |
| 0x0C~0x0D | MDI/MDI-X 状态/控制 | 自动翻转状态,有的PHY用自定义寄存器代替 |
2.3 扩展寄存器(0x10~0x1F)
这些寄存器不是必实现的,但大部分千兆PHY都会用到。比如0x10(千兆控制寄存器)用来指示1000Base-T的Master/Slave配置,0x11(千兆状态寄存器)告诉你本地和远端是否支持1000M。
嗯,这里要特别注意:有些PHY把中断使能、错误计数器等也映射在16~31区间,但不同厂家安排的位置不一样。比如我的一个项目用Broadcom BCM54616S,它的中断寄存器在0x1C,但换成Marvell 88E1512就在0x1B了。所以不能死记硬背,要勤查datasheet。
2.4 厂商自定义寄存器
这部分是最让人头大的。每个厂家都有一堆私有的控制/状态/调试寄存器,通过“页”(Page)机制扩展。比如Marvell PHY的0x1E是“页控制寄存器”,你要先往0x1E写页码,然后才能读写其他地址。
- Marvell:使用0x1E作为页选择,0x1D作为数据端口,部分型号还有0x1F做额外扩展。
- Broadcom:常用0x1C、0x1D、0x1E组合,甚至用“影子寄存器”(Shadow Registers)方式,需要连续写特定幻数才能解锁。
- Realtek:有些型号没有页机制,所有功能都挤在0~31里,但地址复用,需要先配置0x1F的“选择位”来切换功能。
说白了,厂商自定义寄存器就是厂家留给自己做魔改的地方。比如LED指示灯控制、信号检测、环回测试、功耗管理……你产品上每个LED亮灭逻辑,往往都在这些寄存器里配。
最后提一句:PHY寄存器体系虽然分层,但实际项目中标准区和扩展区经常混用。比如某些Realtek芯片的0x0A(MII标准区)被用来放自定义温度传感器读数,你如果严格按照手册读状态,可能会被坑。记住一个原则:datasheet比你经验更可靠,但经验能帮你少踩坑。