RK3568 Android12 RJ45 网口led状态修改(一)

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寄存器值。
RK3568 Android12 RJ45 网口led状态修改(一)_第1张图片
RK3568 Android12 RJ45 网口led状态修改(一)_第2张图片

串口调试

可以用命令 cat /sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers 来读取寄存器值
可以看到目前默认的31寄存器值为:
31: 0xa42

  1. 切换page
    第一步需要切换到page 0xd04 ,用命令 echo 0x1f 0xd04 > /sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
    此时读到的寄存器值为
    …………
    16: 0x6251
    …………
    31: 0xd04
    其中16寄存器的值0x6251 符合下图寄存器表的default状态。

  2. 设置寄存器。
    根据我们的需求,主要修改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

  3. 恢复page为默认
    最后再将page恢复为默认的0xa42
    echo 0x1f 0xa42 >/sys/bus/mdio_bus/devices/stmmac-0:00/phy_registers
    RK3568 Android12 RJ45 网口led状态修改(一)_第3张图片

驱动修改

串口直接写寄存器验证了方法有效,需在驱动中修改,具体见上文实现方法
实现主要参考了博客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显示状态基本可以满足需求。


如有谬误欢迎指正,感谢阅读~

参考资料


  1. RTL8211F在uboot下使用mii工具配置RJ45网口灯详解 ↩︎

  2. 网卡PHY 移植注意事项 ↩︎

  3. 《PHY LinkActive LED 灯异常补丁》 ↩︎

你可能感兴趣的:(RockChip,#,kernel,phy,ethernet,驱动程序)