[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250711034412.17937-1-hau@realtek.com>
Date: Fri, 11 Jul 2025 11:44:12 +0800
From: ChunHao Lin <hau@...ltek.com>
To: <hkallweit1@...il.com>, <nic_swsd@...ltek.com>, <andrew+netdev@...n.ch>,
<davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
<pabeni@...hat.com>
CC: <netdev@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
ChunHao Lin
<hau@...ltek.com>
Subject: [PATCH net-next] r8169: add quirk for RTL8116af SerDes
RTL8116af is a variation of RTL8168fp. It uses SerDes instead of PHY.
But SerDes status will not reflect to PHY. So it needs quirk to help
to reflect SerDes status during PHY read.
Signed-off-by: ChunHao Lin <hau@...ltek.com>
---
drivers/net/ethernet/realtek/r8169_main.c | 40 ++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 9c601f271c02..2f9e9b2e9d49 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -1192,6 +1192,34 @@ static int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
}
+/* The quirk reflects RTL8116af SerDes status. */
+static int r8116af_mdio_read_quirk(struct rtl8169_private *tp, int reg)
+{
+ u8 phyStatus = RTL_R8(tp, PHYstatus);
+
+ if (!(phyStatus & LinkStatus))
+ return 0;
+
+ /* BMSR */
+ if (tp->ocp_base == OCP_STD_PHY_BASE && reg == MII_BMSR)
+ return BMSR_ANEGCOMPLETE | BMSR_LSTATUS;
+
+ /* PHYSR */
+ if (tp->ocp_base == 0xa430 && reg == 0x12)
+ { if (phyStatus & _1000bpsF)
+ return 0x0028;
+ else if (phyStatus & _100bps)
+ return 0x0018;
+ }
+
+ return 0;
+}
+
+static int r8116af_mdio_read(struct rtl8169_private *tp, int reg)
+{
+ return r8168g_mdio_read(tp, reg) | r8116af_mdio_read_quirk(tp, reg);
+}
+
static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
{
if (reg == 0x1f) {
@@ -1285,6 +1313,13 @@ static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
return value;
}
+static bool rtl_is_8116af(struct rtl8169_private *tp)
+{
+ return tp->mac_version == RTL_GIGA_MAC_VER_52 &&
+ (r8168_mac_ocp_read(tp, 0xdc00) & 0x0078) == 0x0030 &&
+ (r8168_mac_ocp_read(tp, 0xd006) & 0x00ff) == 0x0000;
+}
+
static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
{
switch (tp->mac_version) {
@@ -1308,7 +1343,10 @@ static int rtl_readphy(struct rtl8169_private *tp, int location)
case RTL_GIGA_MAC_VER_31:
return r8168dp_2_mdio_read(tp, location);
case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_LAST:
- return r8168g_mdio_read(tp, location);
+ if (rtl_is_8116af(tp))
+ return r8116af_mdio_read(tp, location);
+ else
+ return r8168g_mdio_read(tp, location);
default:
return r8169_mdio_read(tp, location);
}
--
2.43.0
Powered by blists - more mailing lists