PHY晶片 AR8033 學習筆記

來源:互聯網
上載者:User

標籤:

【晶片簡介】

    AR8033是Atheros公司的第4代10/100/1000Mbps速率乙太網路PHY晶片,可用於家庭網關、企業交換器、移動基站、光模組等裝置。該晶片採用RGMII協議或SGMII協議與MAC晶片進行通訊,只需要單一3.3V電源供電,可自行整流變換出片內電路所需其它電源。AR8033還內建了一個工作頻率為1.25GHz的SerDes介面,可以直接與光纖收發模組串連,將光訊號轉換為適用於1000BASE-X/100 BASE-FX傳輸模式的電訊號或用於與MAC晶片通訊的SGMII協議電訊號。

PHY晶片在OSI協議棧中屬於最底層的物理層,與其它層的關係圖如下:

圖1 PHY晶片的工作位置處於OSI底層

    從硬體上來說,一般PHY晶片為模數混合電路,負責接收電、光這類類比訊號,經過解調和A/D轉換後通過MII介面將訊號交給MAC晶片進行處理。一般MAC晶片為純數字電路。

 

 

【SerDes介面】

    SerDes是SERializer(串列器)/DESerializer(解串器)的簡稱。它是一種主流的時分多工(TDM)、點對點(P2P)的串列通訊技術,即在發送端多路低速並行訊號被轉換成高速串列訊號,經過傳輸媒體(光纜或銅線),最後在接收端高速串列訊號重新轉換成低速並行訊號。

 

 

【RGMII介面】

    RGMII即Reduced GMII,是GMII的簡化版本。它的介面訊號線數量為14根(COL/CRS連接埠狀態指示訊號,這裡沒有畫出),時鐘頻率為125MHz,TX/RX資料寬度為4位,為了保持1000Mbps的傳輸速率不變,RGMII介面在時鐘的上升沿和下降沿都採樣資料。在參考時鐘的上升沿發送GMII介面中的TXD[3:0]/RXD[3:0],在參考時鐘的下降沿發送GMII介面中的TXD[7:4]/RXD[7:4]。RGMII相容100Mbps和10Mbps兩種速率,此時參考時脈速率分別為25MHz和2.5MHz。

圖2 RGMII介面

    TX_EN訊號線上傳送TX_EN和TX_ER兩種資訊,在TX_CLK的上升沿發送TX_EN,下降沿發送TX_ER;同樣的,RX_DV訊號線上也傳送RX_DV和RX_ER兩種資訊,在RX_CLK的上升沿發送RX_DV,下降沿發送RX_ER。

 

 

【SGMII介面】

    SGMII即Serial GMII,是PHY與MAC之間的介面,時鐘頻率625MHz,收發各一對差分訊號線,所以總的資料速率為1.25Gbps = 625Mbps* 2。GMII和RGMII都是並行的,而且需要隨路時鐘,PCB布線相對麻煩,不適於背板應用;而SGMII是串列的,不需要提供另外的時鐘,MAC和PHY使用CDR來恢複時鐘。參考時鐘RX_CLK由PHY提供,是可選的,在時鐘訊號的上升沿和下降沿均發生採樣,主要用於MAC側沒有時鐘的情況,一般情況下,RX_CLK不使用,收發都可以從資料中恢複出時鐘。

圖3 SGMII介面圖

    在TXD發送的串列資料中,每8bits資料會插入TX_EN/TX_ER 的2bits控制資訊,同樣,在RXD接收資料中,每8bits資料會插入RX_DV/RX_ER 的2bits控制資訊,稱作8B/10B編碼。

 

 

【MDC/MDIO介面】

    介面有MDC和MDIO兩條線。其中MDC上是由MAC提供的參考時鐘訊號,MDIO則是可雙向傳輸的配置資料線,配合MDC時鐘進行非同步傳輸。AR8033的MDIO介面是開漏輸出,所以在使用時需要外部上拉1.5k電阻。MDIO資料幀的組成如下:

圖4 MDIO資料幀結構

各欄位的含義如下:

PRE        對MDC時鐘訊號的回複,用於校正非同步傳輸時鐘,內容為32個數字1。

ST          資料幀開始標識。

OP          作業碼,10表示讀資料,01表示寫資料。

PHYAD   PHY晶片的物理地址,共5位,其中3位可以在AR8033內部進行配置。

REGAD  寄存器地址,共5位,用於選中PHY晶片內的32個寄存器之一。

TA                 用於防止在資料轉送期間建立新的串連,共2位。讀操作期間第1位為高阻態,第2位為0;寫操作期間第1位為1,第2位為0.

DATA     表示 從寄存器讀到的資料 或 向寄存器寫入的資料,共16位。從高位開始傳輸。

IDLE      幀間空閑訊號,呈高阻態。相鄰兩個資料幀之間至少要有1個時鐘的空閑訊號。

 

 

【工作模式配置】

    AR8033可以工作在3種模式類別下:電口模式、光口模式、光電轉換器模式。根據4根模式選擇引腳上電平的不同可以將AR8033配置到不同的工作模式。官方文檔描述如下:

圖5 模式選擇引腳


圖6 光口模式的引腳電平情況

    從文檔中可以看到,當我們希望AR8033工作在1000Mbps光口模式時,應該把RX_DV、RXD2、RX_CLK、RXD3這4個引腳的電平下拉和上拉為0010的情況。同理,要工作在100Mbps光口模式則可以將電平設定為0110或1110。

 

 

【應用樣本】

    我們可以使用AR8033對光口進行管理。根據官方資料手冊描述,可以採用如下結構:

圖7 AR8033光纖模組系統框圖

    從框圖中可以看出,當AR8033晶片用於光纖模組管理時,需要配置成100BASE-FX模式或1000BASE-X模式,與交換器晶片之間的資料轉送採用RGMII協議。實際應用時,AR8033的工作模式直接由主控晶片通過MDC/MDIO匯流排進行配置;資料轉送路徑是AR8033傳遞給交換晶片,再由交換晶片傳遞給主控晶片。如下:

圖8 AR8033應用

    在中可以看到,光模組晶片AR8033與交換晶片之間的資料轉送使用RGMII協議,交換晶片與主控晶片之間的資料轉送使用SGMII協議。

 

 

【程式碼分析】

    想要在Linux上使用AR8033需要做2部分工作,一是編寫裝置驅動並將裝置驅動註冊到核心,二是建立裝置通訊要使用的mdio匯流排並將裝置註冊到匯流排上。

a)  驅動註冊流程:

    檔案mdio_gpio.c 是 mdio_gpio 模組的代碼所在。在模組載入函數 mdio_gpio_init() 中通過語句 ret = platform_driver_register(&mdio_gpio_driver) 將mdio 驅動註冊為“平台裝置驅動”,其中mdio_gpio_driver 是一個 platform_driver 結構體,初始化代碼如下:

static struct platform_driver mdio_gpio_driver= {

       .probe= mdio_gpio_probe,    // 關聯裝置的probe函數

       .remove= __devexit_p(mdio_gpio_remove),    // 關聯裝置的remove函數

       .driver            = {

              .name      = "mdio-gpio",    // 驅動名

              .owner    = THIS_MODULE,

       },

};

    而在 platform_driver_register() 這個函數中,則進一步將驅動匯流排類型設定為 platform_bus_type,以及關聯驅動的probe()函數、remove()函數和shutdown()函數。其代碼細節如下:

int platform_driver_register(structplatform_driver *drv)

{

       drv->driver.bus= &platform_bus_type;

       if(drv->probe)

              drv->driver.probe = platform_drv_probe;    //注意,這是drv->driver.probe

       if(drv->remove)

              drv->driver.remove= platform_drv_remove;    // 關聯drv->driver.remove

       if(drv->shutdown)

              drv->driver.shutdown= platform_drv_shutdown;    // 關聯drv->driver.shutdown

       returndriver_register(&drv->driver);

}

    可以看到,對於所有驅動而言初始化到這一步時都會指向probe()、remove()、shutdown()這3個函數,這3個函數分別用來返回“平台裝置驅動”的probe()、remove()、shutdown()函數。代碼如下:

static int platform_drv_probe(struct device*_dev)

{

       structplatform_driver *drv = to_platform_driver(_dev->driver);

       structplatform_device *dev = to_platform_device(_dev);

       returndrv->probe(dev);

}

    而在platform_driver_register()函數結尾的 return 語句中,再調用driver_register(&drv->driver) 進一步對驅動進行註冊。通過語句driver_find(drv->name, drv->bus)尋找匯流排上是否已經註冊過該驅動,若沒有則使用語句bus_add_driver(drv) 將驅動添加到匯流排中。至此,驅動註冊流程結束。代碼如下:

int driver_register(struct device_driver*drv)

{

       intret;

       structdevice_driver *other;

       BUG_ON(!drv->bus->p);    // 開啟調試

   // 做一些檢測

       if((drv->bus->probe && drv->probe) ||

           (drv->bus->remove &&drv->remove) ||

           (drv->bus->shutdown &&drv->shutdown))

              printk(KERN_WARNING"Driver ‘%s‘ needs updating - please use "

                     "bus_typemethods\n", drv->name);

 

       other = driver_find(drv->name, drv->bus);    //在匯流排中尋找是否已經註冊該驅動

       if(other) {

              printk(KERN_ERR"Error: Driver ‘%s‘ is already registered, "

                     "aborting...\n",drv->name);

              return-EBUSY;

       }

       ret = bus_add_driver(drv);   // 將驅動添加到匯流排

       if(ret)

              returnret;

       ret= driver_add_groups(drv, drv->groups);

       if(ret)

              bus_remove_driver(drv);

       returnret;

}

 

b)  裝置註冊流程:

    驅動註冊流程的末尾會調用驅動的 probe() 函數,即 mdio_gpio_probe() 函數。在該函數中,通過語句new_bus = mdio_gpio_bus_init(&pdev->dev, pdata,pdev->id) 初始化一個 mdio 匯流排裝置,在使用語句 mdiobus_register(new_bus)對該裝置匯流排進行註冊。代碼如下:

static int __devinit mdio_gpio_probe(structplatform_device *pdev)

{

       structmdio_gpio_platform_data *pdata = pdev->dev.platform_data;

       structmii_bus *new_bus;

       intret;

       if(!pdata)

              return-ENODEV;

       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata,pdev->id);

       if(!new_bus)

              return-ENODEV;

       ret = mdiobus_register(new_bus);

       if(ret)

              mdio_gpio_bus_deinit(&pdev->dev);

       returnret;

}

    進入函數 mdiobus_register() 查看代碼,內容可以分為2部分。一是對 mdio 匯流排裝置進行真正的註冊,二是註冊成功後,在匯流排上根據 phy_mask搜尋 PHY 裝置。代碼如下:

 

int mdiobus_register(struct mii_bus *bus)

{

       inti, err;

       if(NULL == bus || NULL == bus->name ||

                     NULL== bus->read ||

                     NULL== bus->write)

              return-EINVAL;

       BUG_ON(bus->state!= MDIOBUS_ALLOCATED &&

              bus->state != MDIOBUS_UNREGISTERED);

       bus->dev.parent= bus->parent;

       bus->dev.class= &mdio_bus_class;

       bus->dev.groups= NULL;

       dev_set_name(&bus->dev,"%s", bus->id);

       err = device_register(&bus->dev);    // 註冊 mdio匯流排裝置

       if(err) {

              printk(KERN_ERR"mii_bus %s failed to register\n", bus->id);

              return-EINVAL;

       }

       mutex_init(&bus->mdio_lock);

       if(bus->reset)

              bus->reset(bus);

       for(i = 0; i < PHY_MAX_ADDR; i++) {

              if((bus->phy_mask & (1 << i)) == 0) {

                     structphy_device *phydev;

                     phydev = mdiobus_scan(bus, i);    //在匯流排上搜尋 phy 裝置

                     if(IS_ERR(phydev)) {

                            err= PTR_ERR(phydev);

                            gotoerror;

                     }

              }

       }

       bus->state= MDIOBUS_REGISTERED;

…   // 以下省略

}

    進入函數 mdiobus_scan() 查看代碼,可以看到在該函數中使用 phydev = get_phy_device(bus, addr) 語句從匯流排裝置上擷取到 phy 裝置,然後通過語句phy_device_register(phydev) 對phy 裝置進行註冊。至此,裝置註冊流程結束。代碼如下:

struct phy_device *mdiobus_scan(structmii_bus *bus, int addr)

{

       structphy_device *phydev;

       structmdio_board_entry *be;

       interr;

 

       phydev = get_phy_device(bus, addr);    // 從匯流排裝置上擷取 phy 裝置

       if(IS_ERR(phydev) || phydev == NULL)

              returnphydev;

       mutex_lock(&__mdio_board_lock);

       list_for_each_entry(be,&__mdio_board_list, list)

              mdiobus_setup_phydev_from_boardinfo(bus,phydev,

                                              &be->board_info);

       mutex_unlock(&__mdio_board_lock);

       err = phy_device_register(phydev);    // 將 phy 裝置註冊到核心

       if(err) {

              phy_device_free(phydev);

              returnNULL;

       }

       returnphydev;

}

PHY晶片 AR8033 學習筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.