rk3566-安卓11-千兆网卡 rtl8211f 调试

rk 3566 安卓11, 千兆网卡 rtl8211 调试记录

一、功能调试

1. 确认原理图

phy 常用的接口有两种 RGMII 和 RMII, 这两种对应的物理接口有 6 中如下所示. 首先需要根据原理图确定是哪种接法, 根据接法对应的 name 在文档 Rockchip_Developer_Guide_Linux_GMAC_Mode_Configuration_CN.pdf 中查找对应的配置.

1.1 RGMII 模式

该模式需要关注的硬件接口

  • mac: GMACX_MCLKINOUT, ETHx_REFCLKO_25M
  • phy: CLKOUT, XTAL_IN, XTAL_OUT
MAC PHY name
GMACX_MCLKINOUT 悬空
ETHx_REFCLKO_25M 悬空
XTAL_IN/XTAL_OUT 由晶体提供时钟 PLL output 125M for TX_CLK, Crystal 25M for PHY
GMACX_MCLKINOUT 悬空
ETHx_REFCLKO_25M 提供时钟给 XTAL_OUT
XTAL_IN 接地
XTAL_OUT ETHx_REFCLKO_25M 提供时钟
PLL output 125M for TX_CLK, PLL 25M for PHY
GMACX_MCLKINOUT 时钟由 CLKOUT 提供
ETHx_REFCLKO_25M 悬空
XTAL_IN/XTAL_OUT 由晶体提供时钟 125M TX_CLK input from PHY, Crystal 25M for PHY
GMACX_MCLKINOUT 时钟由 CLKOUT 提供
ETHx_REFCLKO_25M 提供时钟给 XTAL_OUT
XTAL_IN 接地,
XTAL_OUTETHx_REFCLKO_25M提供时钟
125M TX_CLK input from PHY, PLL 25M for PHY

1.2 RMII 模式

需要关注的引脚

  • mac: GMACX_MCLKINOUT, ETHx_REFCLKO_25M(一直悬空)
  • phy: PHY_TXCLK, XTAL_IN, XTAL_OUT
MAC PHY name
GMACX_MCLKINOUT 提供时钟给 XTAL_OUT
ETHx_REFCLKO_25M 悬空
XTAL_IN 接地
XTAL_OUTGMACX_MCLKINOUT 提供时钟
RMII Clock Output
GMACX_MCLKINOUT 时钟由 PHY_TXCLK 提供
ETHx_REFCLKO_25M 悬空
XTAL_IN/XTAL_OUT 由晶体提供时钟 RMII Clock Input

1.3 确认 name

确认 mac 端接口

根据原理图:

  • GMAC1_MCLKINOUT_M0 悬空 ==> GMACX_MCLKINOUT 悬空
  • ETH1_REFCLKO_25M_M0 悬空 ==> ETHx_REFCLKO_25M 悬空

确认 phy 端接口

根据原理图:

  • XTAL_IN/XTAL_OUT 由晶体提供时钟

根据前面的信息可以推出 name 为 PLL output 125M for TX_CLK, Crystal 25M for PHY 在 rk 提供的文档 Rockchip_Developer_Guide_Linux_GMAC_Mode_Configuration_CN.pdf 查找对应的配置.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
&mdio1 {
rgmii_phy1: phy@0 {
compatible = "ethernet-phy-ieee802.3-c22"; // 协议
reg = <0x0>;
};
};

&gmac1 {
phy-mode = "rgmii"; // 接口类型
clock_in_out = "output"; // 输出时钟

snps,reset-gpio = <&gpio4 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>;
assigned-clock-parents = <&cru SCLK_GMAC1_RMII_SPEED>;
assigned-clock-rates = <0>, <125000000>; // 千兆网卡时钟

pinctrl-names = "default";
pinctrl-0 = <&gmac1m0_miim // 引脚复用
&gmac1m0_tx_bus2
&gmac1m0_rx_bus2
&gmac1m0_rgmii_clk
&gmac1m0_rgmii_bus>;

// tx, rx 延时时间, 需要参考文档 Rockchip_Developer_Guide_Linux_GMAC_RGMII_Delayline_CN.pdf 配置
tx_delay = <0x4d>;
rx_delay = <0x2d>;

phy-handle = <&rgmii_phy1>;
status = "okay";
};

如果 dts 配置的不对会出现 dma 相关的报错, 出现这个报错, 按照前面的步骤确认硬件接法对应的name 然后查找对应的配置.

2. 配置驱动

这一步比较简单, rk 默认提供了该驱动的支持, 对应的路径 kernel/drivers/net/phy/realtek.c, 只需要打开宏 CONFIG_REALTEK_PHY 即可.

3. 配置电源

如果原理图上的 mac 的 io 供电由 vcc_1v8 提供, 软件需要配置打开这个 vcc_1v8 供电.

软件上对于 gmac1 的电源控制为 vccio5-supply , 因此需要做对应的映射

1
2
3
4
5
6
7
8
9
10
11
12
&pmu_io_domains {
status = "okay";
pmuio1-supply = <&vcc3v3_pmu>;
pmuio2-supply = <&vcca1v8_pmu>;
vccio1-supply = <&vccio_acodec>;
vccio3-supply = <&vccio_sd>;
vccio4-supply = <&vcca1v8_pmu>;
- vccio5-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_1v8>;
vccio6-supply = <&vcc1v8_dvp>;
vccio7-supply = <&vcc_3v3>;
};

这里如果没有配置正确的现象就是, 软件看起来一切正常, 可以读取 phy 信息, 能够 link up, 没有报错, 但是 ifconfig 读取不到 ip 地址 =_=.

参考文档(文档找rk的fae要):
Rockchip_Developer_Guide_Linux_GMAC_CN.pdf
Rockchip_Developer_Guide_Linux_GMAC_RGMII_Delayline_CN.pdf
以太网常见问题处理方法排查手册.pdf

二、吞吐量测试

pc 使用 iperf3 测试在 iperf3官网 下载安装, 下载后将 iperf3.exe 和 cygwin1.dll 复制粘贴到 C:\Windows\System32.

安卓 sdk 自带了这个工具, 在 external/iperf3 运行 mmm ./ 编译,
编译之后生成 out/target/product/rk3566_rgo/system/bin/, push 到机器里面使用.

1. 发送测试

  • pc端: 运行 iperf3.exe -s 后等待
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
PS D:\project\pg1000\wifi固件\bcdm> iperf3.exe -s
-----------------------------------------------------------
Server listening on 5201
-----------------------------------------------------------
Accepted connection from 192.168.3.41, port 43542
[ 5] local 192.168.3.20 port 5201 connected to 192.168.*.* port 43544
[ ID] Interval Transfer Bandwidth
[ 5] 0.00-1.00 sec 104 MBytes 872 Mbits/sec
[ 5] 1.00-2.00 sec 104 MBytes 873 Mbits/sec
[ 5] 2.00-3.00 sec 105 MBytes 881 Mbits/sec
[ 5] 3.00-4.00 sec 106 MBytes 886 Mbits/sec
[ 5] 4.00-5.00 sec 107 MBytes 900 Mbits/sec
[ 5] 5.00-6.00 sec 107 MBytes 900 Mbits/sec
[ 5] 6.00-7.00 sec 107 MBytes 895 Mbits/sec
[ 5] 7.00-8.00 sec 108 MBytes 902 Mbits/sec
[ 5] 8.00-9.00 sec 106 MBytes 892 Mbits/sec
[ 5] 9.00-10.00 sec 107 MBytes 897 Mbits/sec
[ 5] 10.00-10.02 sec 2.60 MBytes 884 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth
[ 5] 0.00-10.02 sec 0.00 Bytes 0.00 bits/sec sender
[ 5] 0.00-10.02 sec 1.04 GBytes 890 Mbits/sec receiver
-----------------------------------------------------------

*安卓端: 运行 ./iperf3 -c 192.168.*.* -i 1 -w 1M -t 10 -l 16000, 其中192.168.*.*: 为 pc 端的 ip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
rk3566_rgo:/cache # ./iperf3 -c 192.168.*.* -i 1 -w 1M -t 10 -l 16000
Connecting to host 192.168.3.20, port 5201
[ 5] local 192.168.3.41 port 43544 connected to 192.168.3.20 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 108 MBytes 904 Mbits/sec 6 395 KBytes
[ 5] 1.00-2.00 sec 104 MBytes 872 Mbits/sec 9 361 KBytes
[ 5] 2.00-3.00 sec 105 MBytes 883 Mbits/sec 15 276 KBytes
[ 5] 3.00-4.00 sec 106 MBytes 886 Mbits/sec 12 218 KBytes
[ 5] 4.00-5.00 sec 107 MBytes 899 Mbits/sec 9 168 KBytes
[ 5] 5.00-6.00 sec 107 MBytes 901 Mbits/sec 0 436 KBytes
[ 5] 6.00-7.00 sec 107 MBytes 896 Mbits/sec 12 341 KBytes
[ 5] 7.00-8.00 sec 107 MBytes 901 Mbits/sec 9 331 KBytes
[ 5] 8.00-9.00 sec 106 MBytes 892 Mbits/sec 15 253 KBytes
[ 5] 9.00-10.00 sec 107 MBytes 896 Mbits/sec 12 188 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 1.04 GBytes 893 Mbits/sec 99 sender
[ 5] 0.00-10.00 sec 1.04 GBytes 892 Mbits/sec receiver

2. 接收测试

发送测试反过来操作即可。

三、打开 led 灯

默认情况只亮一颗黄灯, 需要将另一颗绿灯点亮. 查看芯片手册, RTL8211F 的寄存器读写, 首先需要将要操作的 Address 对应的 page 写入 Page Select Register, 再对该寄存器进行读写.

要点亮灯对应检测到千兆网卡是亮灯需要将 bit8(绿灯), bit13(黄灯) 设置为 1. 首先往Page Select Register中写入对应的 page 0xd04, 然后再操作 0x10 寄存器. Page Select Register 如下所示.

编写代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define PHY_ID_RTL8211F                   0x001cc916
#define PAGE_SELECT_ADDR 0x1f
#define LED_PAGE_REG 0xd04
#define LED_CONTORL_REG 0X10

static int phy_rtl8211f_led_fixup(struct phy_device *phydev)
{
int value = 0;

if (phydev->phy_id != PHY_ID_RTL8211F)
return 0;

/* select page to 0xd04 */
phy_write(phydev, PAGE_SELECT_ADDR, LED_PAGE_REG);

/* When the network card is 1000m, open led1(bit8) and led2(bit13) */
value = phy_read(phydev, LED_CONTORL_REG);
value |= (1 << 8) | (1 << 13);
phy_write(phydev, LED_CONTORL_REG, value);

return 0;
}

完整修改如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
-- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -121,11 +121,10 @@ static void stmmac_exit_fs(struct net_device *dev);

#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))

+#define PHY_ID_RTL8211F 0x001cc916
+#define PAGE_SELECT_ADDR 0x1f
+#define LED_PAGE_REG 0xd04
+#define LED_CONTORL_REG 0X10

/**
* stmmac_verify_args - verify the driver parameters.
@@ -2485,27 +2484,24 @@ static void stmmac_safety_feat_configuration(struct stmmac_priv *priv)
}
}

+static int phy_rtl8211f_led_fixup(struct phy_device *phydev)
{
+ int value = 0;

+ if (phydev->phy_id != PHY_ID_RTL8211F)
return 0;

+ /* select page to 0xd04 */
+ phy_write(phydev, PAGE_SELECT_ADDR, LED_PAGE_REG);

+ /* When the network card is 1000m, open led1(bit8) and led2(bit13) */
+ value = phy_read(phydev, LED_CONTORL_REG);
+ value |= (1 << 8) | (1 << 13);
+ phy_write(phydev, LED_CONTORL_REG, value);

return 0;
}

/**
* stmmac_hw_setup - setup mac in a usable state.
* @dev : pointer to the device structure.
@@ -4482,7 +4478,7 @@ int stmmac_dvr_probe(struct device *device,
__func__);
#endif

+ ret = phy_register_fixup_for_uid(PHY_ID_RTL8211F,0xffffffff, phy_rtl8211f_led_fixup);
if (ret)
pr_warn("Cannot register PHY board fixup.\n");

@@ -4685,7 +4681,7 @@ int stmmac_resume(struct device *dev)

mutex_unlock(&priv->lock);

+ phy_rtl8211f_led_fixup(ndev->phydev);

if (ndev->phydev)
phy_start(ndev->phydev);