如何使用 gpio 模擬 mdio 通信?
一、前言
實際項目開發中,由於設計原因,會將 phy 的 mdio 引腳連接到 SoC 的 2 個空閒 gpio 上,
這樣就無法通過 Gmac 自有的架構實現修改 phy,
因此只能通過 GPIO 模擬的方式實現 MDIO,
好在 Linux 支持 MDIO via GPIO 功能。
該功能需要用到內核驅動 mdio-bitbang.c 和 mdio-gpio.c。
本例 :
- 平臺:
復旦微
- kernel 版本:
linux 4.14.55-xxxxx
- phy 芯片
yt8521
- phy 連接到
gmac0
- mdio 總線連接到:
gpioc 2
portc 3
二、mdio 基礎概念
1、SMI 接口
SMI 是 MAC 內核訪問 PHY 寄存器接口,它由兩根線組成,雙工:
-
MDC(Management Data Clock) 爲時鐘,
-
MDIO(Management Data Input/Output) 爲雙向數據通信,
原理上跟 I2C 總線很類似,也可以通過總線訪問多個不同的 phy。
MDIO 協議是以太網標準 IEEE802.3 中專門用於 MAC 和 PYH 之間管理的串行接口總線,該接口主要用於 MAC 控制器對 PYH 層的狀態讀取和設置(寄存器操作)、獲取鏈路狀態,控制物理層協商等操作。
MDC/MDIO 基本特性:
-
兩線制 :MDC(時鐘線)和 MDIO(數據線)。分主從設備。
-
時鐘頻率:2.5MHz
-
通信方式:總線制,可同時接入的 PHY 數量爲 32 個
-
通過 SMI 接口,MAC 芯片主動的輪詢 PHY 層芯片,獲得狀態信息,併發出命令信息。
其中主設備稱作 STA,從設備稱作 MDI,一個主設備可以對多個從設備進行命令讀寫操作。
三、mdio 協議波形
1、MDIO 接口數據幀
在 IEEE802.3 協議中,把 MDIO 接口數據幀分爲兩種,一種是 Clause22,另一種是 Clause45。
前者主要用於百兆千兆以太網,後者用於千兆以上的以太網。
2、Clause22
MDIO 接口的讀寫通信協議如下圖所示:
-
Preamble:
32 位前導碼,由 MAC 端發送 32 位邏輯 “1”,用於同步 PHY 芯片。
-
ST(Start of Frame):
2 位幀開始信號,用 01 表示。
-
OP(Operation Code):
2 位操作碼,讀:10 寫:01。
-
PHYAD(PHY Address):
5 位 PHY 地址,用於表示與哪個 PHY 芯片通信,因此一個 MAC 上可以連 接多個 PHY 芯片。
-
REGAD(Register Address):
5 位寄存器地址,可以表示共 32 位寄存器。
-
TA(Turnaround):
2 位轉向,
在讀命令中,MDIO 在此時由 MAC 驅動改爲 PHY 驅動,在第一個 TA 位,MDIO 引腳爲高阻狀態,第二個 TA 位,PHY 將 MDIO 引腳拉低,準備發送數據;
在寫命令中,不需 要 MDIO 方向發生變化,MAC 固定輸出 2’b10,隨後開始寫入數據。
-
DATA:
16 位數據,在讀命令中,PHY 芯片將讀到的對應 PHYAD 的 REGAD 寄存器的數據寫到 DATA 中;在寫命令中,PHY 芯片將接收到的 DATA 寫入 REGAD 寄存器中。需要注意的是,在 DATA 傳 輸的過程中,高位在前,低位在後。
-
IDLE:
空閒狀態,此時 MDIO 爲無源驅動,處於高阻狀態,但一般用上拉電阻使其上拉至高電平。
波形舉例
向phy:3 寄存器0x00 寫入 數據0x4140
3、Clause45
四、YT8521
YT8521S 是一款高度集成的以太網收發器,符合 10BASE-Te、100BASE-TX 和 1000BASE-T IEEE 802.3 標準。
1、引腳
其中與 mdio 相關引腳:
14 MDC Management Data Clock
15 MDIO Input/Output of Management Data.
Pull up 3.3V/2.5V/1.8V for 3.3V/2.5V/1.8V I/O respectively
2、模塊圖
3、MDIO 協議時序 -[重要]
下面 YT8521 的 SMI 時序圖:
上升沿讀數據,下降沿寫數據
五、驅動移植
1、驅動文件及移植
mdio-gpio.c
mdio-bitbang.c
勾選 下面幾項:
│ │ <*> Bitbanged MDIO buses │ │
│ │ <*> GPIO controlled MDIO bus multiplexers │ │
│ │ <*> MMIO device-controlled MDIO bus multiplexers │ │
2、移植設備樹
aliases {
…………
mdio-gpio0 = &mdio0;
};
mdio0: mdio {
compatible = "virtual,mdio-gpio";
gpios = <&portc 2 0 >,<&portc 3 0>;
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@7 {
reg = <0x7>;
yt,phy-delay = <0xfc>;
phy-connection-type = "rgmii-id";
};
};
&gmac0 {
status = "okay";
phy-handle = <&phy0>;
};
由設備樹可知,
-
我們創建了 1 個獨立的 mdio 設備節點,
-
當用命令 mdio 修改 phy 時,就會根據 gmac0 的 phy-handle,
-
找到 mdio0 節點從而調用 mdio-gpio 驅動模塊來配置 phy:8521。
下圖,是 phy 直接連接到 gmac0 的 mdio 接口,mdio 命令執行的通路:
下圖是 phy 連接到 gpio 口,mdio 命令執行的通路:
3、查看 log
開機有以下 log,說明驅動 移植成功:
# dmesg | grep MDIO
[ 3.257270] libphy: GPIO Bitbanged MDIO: probed
[ 3.274202] libphy: Fixed MDIO Bus: probed
# cd /sys/class/mdio_bus/
# ls
fixed-0 gpio-0 stmmac-0 stmmac-1
# cd gpio-0/
# ls
device gpio-0:03 of_node power subsystem uevent
# cd gpio-0\:03/
# ls
attached_dev phy_has_fixups power
driver phy_id subsystem
of_node phy_interface uevent
4、操作
修改 eth0 爲百兆速率,則設置 Speed_Selection 位爲 01,同時自動協商爲 Autoneg_En 要禁用,即設置該寄存器值爲 0x2140:
# mdio eth0 0x00 0x2140
write phy addr: 0x3 reg: 0x0 value : 0x2140
抓取波形如下:
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/TYUAnNLTJuZ7swp2ULDZow