网卡PHY 移植注意事项

1. MAC 和PHY 的关系

MAC 就是以太网控制器,属于OSI的数字链路层。 phy 属于OSI的物理层(Physical layer),所以叫phy. MAC主要处理的数字信号,PHY负责把MAC的数字信号进行编码,串行化等操作后,转化为模拟信号进行发送。PHY在数据接受时, 进行如上所述的逆操作,将模拟信号转化为数字信号,解码,并行化后,传给MAC。

PHY 有一个重要的功能就是 自协商。 什么是自协商? 就是PHY一旦连入网络,PHY 会和它相连接的端口的PHY进行协商,当前通信使用的速率是 1000M, 100M 还是10M? 他们相互沟通后,会确定一个 两个端口都支持的最大网络速率。

PHY还有个重要的功能就是实现CSMA/CD的部分功能.它可以检测到网络上是否有数据在传送,如果有数据在传送中就等待,一旦检测到网络空闲,再等待一个随机时间后将送数据出去。

PHY 还提供了自动控制LED 等的功能。根据当前网络的传输速率,是否有数据传输,来自动控制LED 灯的行为。至于如何控制LED,可以根据PHY的datasheet 进行相关配置。

下图是一个MAC 和PHY 的关系:
网卡PHY 移植注意事项_第1张图片
RGMII/RMII/GMII/MII 均是用于网络数据的传输;
MAC 和PHY 之间需要一个同步时钟。
MDC& MDIO 用于控制PHY的管理总线mdio。

2. 识别PHY的address

想IIC 一样, MAC 通过MDIO 总线要找到指定的PHY, 每一个PHY 都需要有一个PHY address。这个PHY address 一般都是由HW pull up/down 对应的地址pin 脚, PHY 在上电后,读到的这个初始状态的输入值, 就是PHY 的地址。

例如ADDR0 = pullup
ADDR1 = pullup
ADDR2 = pulldown
此时地址就为011 =3.

在移植时, 较新的kernel 中, 一般不需要指定PHY 的地址, 由kernel 自动探测到。 但在uboot 中, 一般需要配置对应的PHY address 才能工作。

3. PHY LED 灯的客制化

在网卡正常工作后,有时候需要客制化PHY LED灯的情况, 今天我们就以一个PHY(rtl8211e) 和一个集成网卡(rtl8111g)为例进行说明。

3.1 rtl8211e phy led 灯的定制

首先看需求, 1G 时, LED 绿色灯亮, 100M 时褐色灯亮, 10 M 为黑, 当网络有数据时, 有一个另外的LED 等进行闪烁。(总共三个灯)。
上datasheet:
网卡PHY 移植注意事项_第2张图片讲的很清楚,这三个LED PIN 脚,被register 26 和register 28 控制着。 每一个LED 均可配置成10M, 100M , 1000M 时,常亮。 也可以配置对应的active, 表示传输数据时,闪烁。具体怎么配, 看下图:
网卡PHY 移植注意事项_第3张图片Active 为1 时,对应的LED 在数据传输时闪烁。
10M/100M/1000M 对应的bit 置1 时, 其在对应的速率下,会亮起来。
先别着急, PHY 接的LED 灯在硬件设计上是拉高为亮, 还是拉低为亮。这个需要注意。也就是所说的LOW active 还是high active。
这个还需要切一张datasheet 来说明:
网卡PHY 移植注意事项_第4张图片讲的很清楚,Led 是high active 还是low active, 依赖于LED pin 的上拉还是下拉, 如果是上拉,就是low active, 如果下拉, 就是 high active。你看这多智能。硬件自动控制high/low active。

下面直接看下arm linux 中如何修改:

/* drivers/net/phy/phy_device.c*/
+static int rtl8211e_phy_fixup(struct phy_device *dev)
+{
+       int len=0;
+       u32 value1,value2;
+
+       value1 = 0x0240;
+       value2 = 0x10;
+      
+       /*PHY LED OK*/
+       phy_write(dev, 0x1f, 0x0007);
+       phy_write(dev, 0x1e, 0x002c);
+       phy_write(dev, 0x1c, value1);
+       phy_write(dev, 0x1a, value2);
+       phy_write(dev, 0x1f, 0x0000);
+ 
+       return 0;
+}
+
 static int __init phy_init(void)
 {
        int rc;
@@ -1482,6 +1513,8 @@ static int __init phy_init(void)
        if (rc)
                mdio_bus_exit();
 
+       phy_register_fixup_for_uid(0x001cc915, 0xffffffff,
+                               rtl8211e_phy_fixup);
        return rc;
 }

phy_register_fixup_for_uid 是一个linux中通用的修正指定的PHY的函数。当linux系统启动PHY后,会探测这个PHY是否注册了一个fixup函数,如果有,就调用这个函数进行PHY的一些额外设定。PHY LED 当然可以放在里面进行设定。

3.2 rtl8111g led 灯的定制

需求和3.1 一样。, 1G 时, LED 绿色灯亮, 100M 时褐色灯亮, 10 M 为黑, 当网络有数据时, 有一个另外的LED 等进行闪烁。(总共三个灯)。
这个更简单,直接上datasheet:
网卡PHY 移植注意事项_第5张图片和3.1 相似, 不过他这个LED Pin 是通过配置位进行极性翻转的(high/low active)。详细参考datasheet。

直接上代码:

--- a/drivers/net/ethernet/realtek/r8168/r8168_n.c
+++ b/drivers/net/ethernet/realtek/r8168/r8168_n.c
@@ -24364,6 +24364,7 @@ rtl8168_init_software_variable(struct net_device *dev)
                 tp->NotWrMcuPatchCode = TRUE;
         }
 
+        RTL_W16(tp, CustomLED, 0x284);
         tp->NicCustLedValue = RTL_R16(tp, CustomLED);
 
         rtl8168_get_hw_wol(dev);

0x284 的含义:
2: LED2 在100M 时常亮;
8: LED1 在仍何速率下, 只有有数据传输,就blanking。
4: LED0 在1000M 时常亮;

LED 灯的定制,就demo 至此, 希望对此还有疑惑的你有所帮助。

你可能感兴趣的:(嵌入式移植专栏,armlinux,ARM)