[PATCH net-next] r8169: add quirk for RTL8116af SerDes

ChunHao Lin posted 1 patch 2 months, 4 weeks ago
drivers/net/ethernet/realtek/r8169_main.c | 40 ++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
[PATCH net-next] r8169: add quirk for RTL8116af SerDes
Posted by ChunHao Lin 2 months, 4 weeks ago
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@realtek.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
Re: [PATCH net-next] r8169: add quirk for RTL8116af SerDes
Posted by Andrew Lunn 2 months, 3 weeks ago
On Fri, Jul 11, 2025 at 11:44:12AM +0800, ChunHao Lin wrote:
> 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.

Can you give us a few more details. What is on the other end of the
SERDES? An SGMII PHY? An SFP cage? An Ethernet switch chip?

A quick search suggests it is used with an SFP cage. How is the I2C
bus connected? What about GPIOs? Does the RTL8116af itself have GPIOs
and an I2C bus?

	Andrew
RE: [PATCH net-next] r8169: add quirk for RTL8116af SerDes
Posted by Hau 2 months, 3 weeks ago
> 
> Can you give us a few more details. What is on the other end of the SERDES?
> An SGMII PHY? An SFP cage? An Ethernet switch chip?
> 
> A quick search suggests it is used with an SFP cage. How is the I2C bus
> connected? What about GPIOs? Does the RTL8116af itself have GPIOs and an
> I2C bus?
> 
RTL8116af 's SERDES will connect to a SFP cage. It has GPIO and a I2C bus. But driver did not use it to access SFP cage.
Driver depends on mac io 0x6c (LinkStatus) to check link status.
Re: [PATCH net-next] r8169: add quirk for RTL8116af SerDes
Posted by Andrew Lunn 2 months, 3 weeks ago
On Mon, Jul 14, 2025 at 03:28:37PM +0000, Hau wrote:
> > 
> > Can you give us a few more details. What is on the other end of the SERDES?
> > An SGMII PHY? An SFP cage? An Ethernet switch chip?
> > 
> > A quick search suggests it is used with an SFP cage. How is the I2C bus
> > connected? What about GPIOs? Does the RTL8116af itself have GPIOs and an
> > I2C bus?
> > 

> RTL8116af 's SERDES will connect to a SFP cage. It has GPIO and a
> I2C bus. But driver did not use it to access SFP cage.  Driver
> depends on mac io 0x6c (LinkStatus) to check link status.

You cannot correctly use an SFP cage without using the I2C bus and the
GPIOs. e.g. A copper SFP module likely needs SGMII, where as a fibre
module needs 1000BaseX. You need to reprogram the PCS depending on
what the SFP EEPROM says.

The kernel has all the code needed to coordinate this, phylink. All
you need to do is write a standard Linux I2C bus driver, a standard
Linux GPIO driver, and turn your PCS into a Linux PCS. You can then
instantiate an SFP device. The txgbe driver does this, you can
probably copy the code from there.

Have you licensed these parts? The txgbe hardware uses synopsys I2C
and PCS. So all that was needed was a wrapper around the existing
drivers.

	Andrew
RE: [PATCH net-next] r8169: add quirk for RTL8116af SerDes
Posted by Hau 2 months, 3 weeks ago
> On Mon, Jul 14, 2025 at 03:28:37PM +0000, Hau wrote:
> > >
> > > Can you give us a few more details. What is on the other end of the
> SERDES?
> > > An SGMII PHY? An SFP cage? An Ethernet switch chip?
> > >
> > > A quick search suggests it is used with an SFP cage. How is the I2C
> > > bus connected? What about GPIOs? Does the RTL8116af itself have
> > > GPIOs and an I2C bus?
> > >
> 
> > RTL8116af 's SERDES will connect to a SFP cage. It has GPIO and a I2C
> > bus. But driver did not use it to access SFP cage.  Driver depends on
> > mac io 0x6c (LinkStatus) to check link status.
> 
> You cannot correctly use an SFP cage without using the I2C bus and the
> GPIOs. e.g. A copper SFP module likely needs SGMII, where as a fibre
> module needs 1000BaseX. You need to reprogram the PCS depending on
> what the SFP EEPROM says.
> 
> The kernel has all the code needed to coordinate this, phylink. All you need
> to do is write a standard Linux I2C bus driver, a standard Linux GPIO driver,
> and turn your PCS into a Linux PCS. You can then instantiate an SFP device.
> The txgbe driver does this, you can probably copy the code from there.
> 
> Have you licensed these parts? The txgbe hardware uses synopsys I2C and
> PCS. So all that was needed was a wrapper around the existing drivers.
> 
Thanks for your advice. I will check this internally to see if we can do this on device.

Thanks.