Platform: RK3568
OS: Android 12
Kernel: v4.19.206
SDK Version:android-12.0-mid-rkr1
Module :RTL8211F-CG
以太网已经配置成功,测试发现插上网线时 RJ45 网口只有一个黄色led在闪烁,而需要的效果是一个led闪烁表示active状态,一个led常亮表示link状态。
注:该方法经详细测试还有些bug,进一步优化方法可见下一篇文章 RK3568 Android12 RJ45 网口led状态修改(二) ,但是基本框架和分析思路还是一致的。
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 921edea1ee66..fa3928a6e291 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -57,6 +57,10 @@
#define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
#define TSO_MAX_BUFF_SIZE (SZ_16K - 1)
+#define RTL_8211F_PHY_ID 0x001cc916
+#define RTL_8211F_PHY_ID_MASK 0x001fffff
+#define RTL_8211F_PAGE_SELECT 0x1f
+#define RTL_8211F_LCR_ADDR 0x10
/* Module parameters */
#define TX_TIMEO 5000
@@ -4266,6 +4270,28 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
return 0;
}
+static int phy_rtl8211f_led_fixup(struct phy_device *phydev)
+{
+ u32 val;
+ val = 0x6171;
+
+ pr_info("terry in : %s\n", __func__);
+
+ /*switch to page0xd04*/
+ phy_write(phydev, RTL_8211F_PAGE_SELECT, 0xd04);
+
+ /*set led1(green) Link 10/100/1000M*/
+ phy_write(phydev, RTL_8211F_LCR_ADDR, val);
+
+ /*switch back to page0*/
+ phy_write(phydev,RTL_8211F_PAGE_SELECT, 0xa42);
+
+ return 0;
+}
+
/**
* stmmac_dvr_probe
* @device: device pointer
@@ -4458,7 +4484,11 @@ int stmmac_dvr_probe(struct device *device,
netdev_warn(priv->dev, "%s: failed debugFS registration\n",
__func__);
#endif
-
+ /* register the PHY board fixup */
+ ret = phy_register_fixup_for_uid(RTL_8211F_PHY_ID, RTL_8211F_PHY_ID_MASK, phy_rtl8211f_led_fixup);
+ if (ret) {
+ dev_warn(priv->device, "Cannot register PHY board fixup, terry in :%s.\n", __func__);
+ }
return ret;
error_netdev_register:
查阅RTL8211F-CG规格书和相关参考资料1可知其实目前只有一个黄灯闪烁的状态是正常的,不是bug,而是phy 的默认配置。黄灯连接的是phy的led2,表示1000M Link and Active,即只用一个led就表示了link和active的状态。
如果要设置为客户需求的状态,需要对应修改page 0xd04 的register 16寄存器值。
可以用命令 cat /sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers 来读取寄存器值
可以看到目前默认的31寄存器值为:
31: 0xa42
切换page
第一步需要切换到page 0xd04 ,用命令 echo 0x1f 0xd04 > /sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
此时读到的寄存器值为
…………
16: 0x6251
…………
31: 0xd04
其中16寄存器的值0x6251 符合下图寄存器表的default状态。
设置寄存器。
根据我们的需求,主要修改led1(绿灯),需要显示link状态。根据下图的说明,把bit5,bit8设为1,bit9设为0,这样led1就表示Link 10/100/1000M的状态了。
将对应的16进制值 0x6171写入,,可以看到绿灯亮起。
echo 0x10 0x6171 >/sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
恢复page为默认
最后再将page恢复为默认的0xa42
echo 0x1f 0xa42 >/sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
串口直接写寄存器验证了方法有效,需在驱动中修改,具体见上文实现方法
实现主要参考了博客2和rk在kernel 3.10 的补丁3,主要用到了phy_register_fixup_for_uid 函数,这是一个linux 中的通用函数,用于修正设置指定uid的PHY。当linux系统启动PHY后,会探测这个PHY是否注册了一个fixup函数,如果有,就调用这个函数进行PHY的一些额外设定。该函数需要phy_uid和phy_uid_mask两个参数,可以在realtek相关代码中找到模组对应的uid值。
drivers/net/phy/phy_device.c
/**
* phy_register_fixup - creates a new phy_fixup and adds it to the list
* @bus_id: A string which matches phydev->mdio.dev.bus_id (or PHY_ANY_ID)
* @phy_uid: Used to match against phydev->phy_id (the UID of the PHY)
* It can also be PHY_ANY_UID
* @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before
* comparison
* @run: The actual code to be run when a matching PHY is found
*/
int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *))
{
struct phy_fixup *fixup = kzalloc(sizeof(*fixup), GFP_KERNEL);
if (!fixup)
return -ENOMEM;
strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
fixup->phy_uid = phy_uid;
fixup->phy_uid_mask = phy_uid_mask;
fixup->run = run;
mutex_lock(&phy_fixup_lock);
list_add_tail(&fixup->list, &phy_fixup_list);
mutex_unlock(&phy_fixup_lock);
return 0;
}
EXPORT_SYMBOL(phy_register_fixup);
/* Registers a fixup to be run on any PHY with the UID in phy_uid */
int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask,
int (*run)(struct phy_device *))
{
return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run);
}
EXPORT_SYMBOL(phy_register_fixup_for_uid);
写寄存器我们用的是phy_write函数,这是linux中写PHY寄存器的函数,同理还有读函数phy_read。
写寄存器的步骤跟上文串口调试的一样,也是分3步走,这里就不再赘述。
编译测试led显示状态基本可以满足需求。
如有谬误欢迎指正,感谢阅读~
RTL8211F在uboot下使用mii工具配置RJ45网口灯详解 ↩︎
网卡PHY 移植注意事项 ↩︎
《PHY LinkActive LED 灯异常补丁》 ↩︎