網卡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 的關係:
在這裏插入圖片描述
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:
講的很清楚,這三個LED PIN 腳,被register 26 和register 28 控制着。 每一個LED 均可配置成10M, 100M , 1000M 時,常亮。 也可以配置對應的active, 表示傳輸數據時,閃爍。具體怎麼配, 看下圖:
Active 爲1 時,對應的LED 在數據傳輸時閃爍。
10M/100M/1000M 對應的bit 置1 時, 其在對應的速率下,會亮起來。
先彆着急, PHY 接的LED 燈在硬件設計上是拉高爲亮, 還是拉低爲亮。這個需要注意。也就是所說的LOW active 還是high active。
這個還需要切一張datasheet 來說明:
在這裏插入圖片描述講的很清楚,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:
在這裏插入圖片描述和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 至此, 希望對此還有疑惑的你有所幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章