在修改 tx_delay , rx_delay 需要在dts 中配置,每次都要重新再烧写过! 所以在调试时需要耗费很多气力。只要修改一下原本的驱动,就可以无需另外的工具,就可以进行的调试

驱动位置 lichee/linux-5.4/drivers/net/ethernet/allwinner/sunxi-gmac.c

原代码

static ssize_t mii_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct net_device *ndev = NULL; struct geth_priv *priv = NULL; int ret = 0; u16 reg, addr, val; char *ptr; ptr = (char *)buf; if (dev == NULL) { pr_err("Argment is invalid\n"); return count; } ndev = dev_get_drvdata(dev); if (ndev == NULL) { pr_err("Net device is null\n"); return count; } priv = netdev_priv(ndev); if (priv == NULL) { pr_err("geth_priv is null\n"); return count; } if (!netif_running(ndev)) { pr_warn("eth is down!\n"); return count; } ret = sunxi_parse_write_str(ptr, &addr, &reg, &val); if (ret) return ret; priv->mii_reg.reg = reg; priv->mii_reg.addr = addr; priv->mii_reg.value = val; return count; }

攸改过后

static ssize_t mii_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct net_device *ndev = NULL; struct geth_priv *priv = NULL; int ret = 0; u16 reg, addr, val; char *ptr; ptr = (char *)buf; if (dev == NULL) { pr_err("Argment is invalid\n"); return count; } ndev = dev_get_drvdata(dev); if (ndev == NULL) { pr_err("Net device is null\n"); return count; } priv = netdev_priv(ndev); if (priv == NULL) { pr_err("geth_priv is null\n"); return count; } if (!netif_running(ndev)) { pr_warn("eth is down!\n"); return count; } ret = sunxi_parse_write_str(ptr, &addr, &reg, &val); if (ret) return ret; if((2 == reg) || (3 == reg)) { u32 clk_value; u8 tdelay; u8 rdelay; clk_value = readl(priv->base_phy); tdelay = (clk_value >> 10) & 0x07; rdelay = (clk_value >> 5) & 0x1f; printk("gmac delay read tx--> %x , rx--> %x \n", tdelay, rdelay); if(2 == reg) { tdelay = (val & 0x07); } else { rdelay = (val & 0x1f); } printk("gmac delay write tx--> %x , rx--> %x \n", tdelay, rdelay); clk_value &= ~((0x07 << 10)| (0x1F << 5)); clk_value |= ((tdelay << 10) | (rdelay << 5)); writel(clk_value, priv->base_phy); } priv->mii_reg.reg = reg; priv->mii_reg.addr = addr; priv->mii_reg.value = val; return count; }

使用方式如下:

先使用 ifconfig eth0 192.168.1.100 ,啟动 gmac 驱动

使用下面命令,进行 tx_delay 修改,3 个参数 , 第一个随便设,第二个需设置 2 , 第三个為 tx_delay 设置值,范围 0x0 ~ 0x7

root@TinaLinux:/# echo 0 2 3 > /sys/devices/platform/soc@3000000/4500000.eth/mii_write [ 66.901376] gmac delay read tx--> 2 , rx--> d [ 66.911086] gmac delay write tx--> 3 , rx--> d root@TinaLinux:/# echo 0 2 5 > /sys/devices/platform/soc@3000000/4500000.eth/mii_write [ 92.944996] gmac delay read tx--> 3 , rx--> d [ 92.954582] gmac delay write tx--> 5 , rx--> d 使用下面命令,进行 rx_delay 修改,3 个参数 , 第一个随便设,第二个需设置 3 , 第三个為 rx_delay 设置值,范围 0x0 ~ 0x1f , 输入需要使用 16 进位 root@TinaLinux:/# echo 0 3 a > /sys/devices/platform/soc@3000000/4500000.eth/mi_write [ 108.317230] gmac delay read tx--> 5 , rx--> d [ 108.327034] gmac delay write tx--> 5 , rx--> a root@TinaLinux:/# echo 0 3 1c > /sys/devices/platform/soc@3000000/4500000.eth/mii_write [ 120.347615] gmac delay read tx--> 5 , rx--> a [ 120.357371] gmac delay write tx--> 5 , rx--> 1c root@TinaLinux:/# echo 0 3 1c > /sys/devices/platform/soc@3000000/4500000.eth/mii_write [ 126.976849] gmac delay read tx--> 5 , rx--> 1c [ 126.986301] gmac delay write tx--> 5 , rx--> 1c

测试时先使用外机 ping d1s ,调整 rx_delay 值后,使用 ifconfig 查看 rx_byte 及 crc 值,看是否有正常接收,并且无 crc 。 找出某一区间都正常,例如 4 ~ c 都是正常的! 此时将 rx_delay 设置在 8 。

rx_delay 设置后,在用 d1s ping 外机,调整 tx_delay 值,看在什么区间可以正常 ping 不丢包, 一样取中间值