网络子系统是 linux 操作系统里很重要的一部分。关于这部分有很多的参考资料。这里主要说明一下 phy
芯片在整个子系统里的位置。从这个结构里看到,PHY 驱动的功能处于链路层。
Linux 网络设备系统包括设备与驱动二大部分。网络设备驱动包括 MAC 层的驱动、MDIO 总结接口驱动
与 phy 驱动。结合 linux 系统设备树定义以及设备管理系统,构成 phy 驱动在开发过程中涉及到的所有
部分。示意如下图:
在 Linux 设备管理系统里,硬件设备对应于在/sys/devices 下有对应的节点。如 MAC 设备:
ls -l /sys/devices/platform/ | grep ethernet
drwxr-xr-x 5 root root 0 2011-01-01 13:00 ff290000.ethernet
同理,硬件的 mdio 总线和 phy 芯片也会对应有一个设备节点:
rk3288:/sys/devices/platform/ff290000.ethernet # ls -l | grep bus
lrwxrwxrwx 1 root root 0 2021-01-23 05:44 driver -> ../../../bus/platform/drivers/rk_gmac-dwmac
drwxr-xr-x 3 root root 0 2011-01-01 13:00 mdio_bus ;mdio 设备节点
lrwxrwxrwx 1 root root 0 2021-01-23 10:37 subsystem -> ../../../bus/platform
rk3288: /sys/devices/platform/ff290000.ethernet/mdio_bus/stmmac-0 # ls -l | grep stmm
drwxr-xr-x 3 root root 0 2011-01-01 13:00 stmmac-0:04 ;地址为 4 的 phy 设备节点
根据上图 linux 模块之间的关系,总结 Phy 驱动的开发流程如下:
MAC 设备的硬件描述在不同的平台里有区别。大多数的系统平台都使用 linux 的.dts 文件。如rk3556的RGMII:
&gmac1 {
phy-mode = "rgmii";
clock_in_out = "input";
snps,reset-gpio = <&gpio0 RK_PC2 GPIO_ACTIVE_LOW>;
snps,reset-active-low;
snps,reset-delays-us = <0 20000 100000>;
assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>, <&cru CLK_MAC1_OUT>;
assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
assigned-clock-rates = <0>, <125000000>, <25000000>;
pinctrl-names = "default";
pinctrl-0 = <&gmac1m1_miim
&gmac1m1_tx_bus2
&gmac1m1_rx_bus2
&gmac1m1_rgmii_clk
&gmac1m1_rgmii_bus
/*ð1m1_pins*/
&gmac1m1_clkinout>;
tx_delay = <0x28>;
rx_delay = <0x0>;
phy-handle = <&rgmii_phy1>;
status = "okay";
};
&mdio1 {
status = "okay";
rgmii_phy1: phy@1 { //phy的地址:001
compatible = "ethernet-phy-ieee802.3-c22";
reg = <0x1>; //phy的地址
clocks = <&cru CLK_MAC1_OUT>;
};
};
这其中phy的地址需要跟硬件确认,我之前调试的时候一直attch不到phy就是phy的地址没有弄正确
对于 RGMII 接口,rx 和 tx delay line 调整的过程如下:
通常 linux 系统的 mac 设备都有一个通用的方法对 phy 寄存器进行读写,不太好用,但不需要额外工作可以直接使用。方法是:
ls -l /sys/devices/platform/ | grep eth
drwxr-xr-x 5 root root 0 2011-01-01 13:00 ff290000.ethernet
上面例子里,找到 mac 设备 ff290000.ethernet,继续找到 phy 设备,如下:
ls -l /sys/devices/platform/ff290000.ethernet/mdio_bus/
total 0
drwxr-xr-x 5 root root 0 2011-01-01 13:00 stmmac-0
ls -l /sys/devices/platform/ff290000.ethernet/mdio_bus/stmmac-0/
total 0
lrwxrwxrwx 1 root root 0 2021-01-23 13:32 device -> ../../../ff290000.ethernet
drwxr-xr-x 2 root root 0 2011-01-01 13:00 power
drwxr-xr-x 3 root root 0 2011-01-01 13:00 stmmac-0:00
drwxr-xr-x 3 root root 0 2011-01-01 13:00 stmmac-0:04
lrwxrwxrwx 1 root root 0 2021-01-23 13:32 subsystem -> ../../../../../class/mdio_bus
-rw-r--r-- 1 root root 4096 2011-01-01 13:00 uevent
找到 phy 设备 stmmac-0:04:
cd /sys/devices/platform/ff290000.ethernet/mdio_bus/stmmac-0/stmmac-0:04
ls -l
total 0
lrwxrwxrwx 1 root root 0 2021-01-23 05:23 driver -> ../../../../../../bus/mdio_bus/drivers/YT8511 Gigabit Ethernet
-r--r--r-- 1 root root 4096 2021-01-23 05:23 phy_has_fixups
-r--r--r-- 1 root root 4096 2021-01-23 05:23 phy_id
-r--r--r-- 1 root root 4096 2021-01-23 05:23 phy_interface
-rw-r--r-- 1 root root 4096 2021-01-23 05:23 phy_registers
drwxr-xr-x 2 root root 0 2011-01-01 13:00 power
lrwxrwxrwx 1 root root 0 2021-01-23 05:23 subsystem -> ../../../../../../bus/mdio_bus
-rw-r--r-- 1 root root 4096 2011-01-01 13:00 uevent
对 phy 寄存器的读写就是操作文件 phy_registers。
2) 读寄存器
cat phy_registers
3) 写 mii 寄存器
例:写 mii reg 0 为 0x9000:
echo 0x0 0x9000> phy_registers
4) 读 ext 寄存器
例:读 ext reg 0xc:
echo 0x1e 0xc> phy_registers && cat phy_registers
30: 0xc
31: 0x8052
返回值在 mii reg 0x1f(31d)里,例中为 0x8052。
5) 写 ext 寄存器
例:写 ext reg 0xc 值为 0x80f6:
echo 0x1e 0xc> phy_registers && echo 0x1f 0x80f6> phy_registers
这个依赖于不同的平台。以下以瑞芯微 rk3399 开发平台为例。
注意 GMAC 的基地址是 0xff730000。GMAC 基地址可以在 DTS 文件中查到。
在定位 phy 收发包问题时,重要的一步是分清是发送问题还是接收问题。所以查看收发包的计数可以帮
忙定位问题。
ifconfig eth0
eth0 Link encap:Ethernet HWaddr 5e:8a:8a:5b:9f:74 Driver rk_gmac-dwmac
inet addr:192.168.1.202 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::d6ea:73da:63fa:8827/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1993 errors:0 dropped:0 overruns:0 frame:0
TX packets:1046 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:142969 TX bytes:128206
Interrupt:41
这里的 RX/TX packets 表示 MAC 成功接收和发出的包数。通过多次读取并对比可以确定哪个方向有问题。
Linux proc 文件系统也提供了网络设备 MAC 层的包统计信息:
cat /proc/net/dev
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
ip6tnl0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
ip6_vti0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
can0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
eth0: 0 0 0 0 0 0 0 0 4644 0 0 0 0 0 0 0
dummy0: 0 0 0 0 0 0 0 0 560 8 0 0 0 0 0 0
ip_vti0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sit0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0