Files
openwrt_mitrastar/target/linux/qualcommbe/patches-6.12/0361-net-pcs-Add-10GBASER-interface-mode-support-to-IPQ-U.patch
Alexandru Gagniuc 22dc34e8c1 qualcommbe: v6.12: enable 2.5G and 10G phylink modes in pcs-qcom-ipq9574
The PCS driver in the 6.12 patchset is the v5 submission (see link
below). It solves a number of issues and crashes with teh pcs driver
from the 6.6 patchset. However, this new driver is missing support for
"10gbase-r", "10g-qxgmii", and 1000/2500base-x modes.

Port these modes to the 6.12 patchset. "2500base-x" in particular seems
to be needed to establish a 2.5G link on phy-mode="usxgmii";

Link: https://lore.kernel.org/lkml/20250207-ipq_pcs_6-14_rc1-v5-0-be2ebec32921@quicinc.com/
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/18796
Signed-off-by: Robert Marko <robimarko@gmail.com>
2025-05-31 12:25:49 +02:00

128 lines
3.6 KiB
Diff

From e770b36f0353fd11c4628360fe412acb7f02f346 Mon Sep 17 00:00:00 2001
From: Lei Wei <quic_leiwei@quicinc.com>
Date: Wed, 6 Mar 2024 17:40:52 +0800
Subject: [PATCH] net: pcs: Add 10GBASER interface mode support to IPQ UNIPHY
PCS driver
10GBASER mode is used when PCS connects with a 10G SFP module.
Change-Id: Ifc3c3bb23811807a9b34e88771aab2c830c2327c
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
Alex G: Use regmap to read/write registers
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
---
drivers/net/pcs/pcs-qcom-ipq9574.c | 53 ++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
--- a/drivers/net/pcs/pcs-qcom-ipq9574.c
+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c
@@ -60,6 +60,9 @@
FIELD_PREP(GENMASK(9, 2), \
FIELD_GET(XPCS_INDIRECT_ADDR_L, reg)))
+#define XPCS_10GBASER_STS 0x30020
+#define XPCS_10GBASER_LINK_STS BIT(12)
+
#define XPCS_DIG_CTRL 0x38000
#define XPCS_USXG_ADPT_RESET BIT(10)
#define XPCS_USXG_EN BIT(9)
@@ -229,6 +232,28 @@ static void ipq_pcs_get_state_usxgmii(st
state->duplex = DUPLEX_FULL;
}
+static void ipq_unipcs_get_state_10gbaser(struct ipq_pcs *qpcs,
+ struct phylink_link_state *state)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(qpcs->regmap, XPCS_10GBASER_STS, &val);
+ if (ret) {
+ state->link = 0;
+ return;
+ }
+
+ state->link = !!(val & XPCS_10GBASER_LINK_STS);
+
+ if (!state->link)
+ return;
+
+ state->speed = SPEED_10000;
+ state->duplex = DUPLEX_FULL;
+ state->pause |= MLO_PAUSE_TXRX_MASK;
+}
+
static int ipq_pcs_config_mode(struct ipq_pcs *qpcs,
phy_interface_t interface)
{
@@ -251,6 +276,7 @@ static int ipq_pcs_config_mode(struct ip
val = PCS_MODE_PSGMII;
break;
case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GBASER:
val = PCS_MODE_XPCS;
rate = 312500000;
break;
@@ -355,6 +381,25 @@ static int ipq_pcs_config_usxgmii(struct
return regmap_set_bits(qpcs->regmap, XPCS_MII_CTRL, XPCS_MII_AN_EN);
}
+static int ipq_unipcs_config_10gbaser(struct ipq_pcs *qpcs,
+ phy_interface_t interface)
+{
+ int ret;
+
+ if (qpcs->interface != interface) {
+ ret = ipq_pcs_config_mode(qpcs, interface);
+ if (ret)
+ return ret;
+
+ /* Deassert XPCS */
+ reset_control_deassert(qpcs->reset[XPCS_RESET]);
+
+ qpcs->interface = interface;
+ }
+
+ return 0;
+}
+
static unsigned long ipq_unipcs_clock_rate_get_gmii(int speed)
{
unsigned long rate = 0;
@@ -421,6 +466,7 @@ ipq_unipcs_link_up_clock_rate_set(struct
rate = ipq_unipcs_clock_rate_get_gmii(speed);
break;
case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_10GBASER:
rate = ipq_unipcs_clock_rate_get_xgmii(speed);
break;
default:
@@ -602,6 +648,9 @@ static void ipq_pcs_get_state(struct phy
case PHY_INTERFACE_MODE_USXGMII:
ipq_pcs_get_state_usxgmii(qpcs, state);
break;
+ case PHY_INTERFACE_MODE_10GBASER:
+ ipq_unipcs_get_state_10gbaser(qpcs, state);
+ break;
default:
break;
}
@@ -631,6 +680,8 @@ static int ipq_pcs_config(struct phylink
return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface);
case PHY_INTERFACE_MODE_USXGMII:
return ipq_pcs_config_usxgmii(qpcs);
+ case PHY_INTERFACE_MODE_10GBASER:
+ return ipq_unipcs_config_10gbaser(qpcs, interface);
default:
dev_err(qpcs->dev,
"interface %s not supported\n", phy_modes(interface));
@@ -662,6 +713,8 @@ static void ipq_pcs_link_up(struct phyli
case PHY_INTERFACE_MODE_USXGMII:
ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed);
break;
+ case PHY_INTERFACE_MODE_10GBASER:
+ break;
default:
dev_err(qpcs->dev,
"interface %s not supported\n", phy_modes(interface));