lede/target/linux/qualcommbe/patches-6.6/103-13-net-pcs-Add-2500BASEX-interface-mode-support-to-IPQ-.patch
John Audia d989a3256a qualcommb/ipq95xx: refresh patches ahead of 6.6.75
Refreshed patches for qualcommb/ipq95xx by running
make target/linux/refresh after creating a .config containing:
CONFIG_TARGET_qualcommbe=y
CONFIG_TARGET_qualcommbe_ipq95xx=y
CONFIG_TARGET_qualcommbe_ipq95xx_DEVICE_qcom_rdp433=y

Signed-off-by: John Audia <therealgraysky@proton.me>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2025-02-18 11:00:26 +08:00

199 lines
5.9 KiB
Diff

From fcd1c53b460aa39cfd15f842126af62b27a4fad5 Mon Sep 17 00:00:00 2001
From: Lei Wei <quic_leiwei@quicinc.com>
Date: Tue, 2 Apr 2024 18:28:42 +0800
Subject: [PATCH 13/50] net: pcs: Add 2500BASEX interface mode support to IPQ
UNIPHY PCS driver
2500BASEX mode is used when PCS connects with QCA8386 switch in a fixed
2500M link. It is also used when PCS connectes with QCA8081 PHY which
works at 2500M link speed. In addition, it can be also used when PCS
connects with a 2.5G SFP module.
Change-Id: I3fe61113c1b3685debc20659736a9488216a029d
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
---
drivers/net/pcs/pcs-qcom-ipq-uniphy.c | 95 +++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
--- a/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
+++ b/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
@@ -25,6 +25,7 @@
#define PCS_MODE_SGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x4)
#define PCS_MODE_QSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x1)
#define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2)
+#define PCS_MODE_SGMII_PLUS FIELD_PREP(PCS_MODE_SEL_MASK, 0x8)
#define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10)
#define PCS_MODE_AN_MODE BIT(0)
@@ -282,6 +283,24 @@ static void ipq_unipcs_get_state_sgmii(s
state->pause |= MLO_PAUSE_RX;
}
+static void ipq_unipcs_get_state_2500basex(struct ipq_uniphy_pcs *qunipcs,
+ int channel,
+ struct phylink_link_state *state)
+{
+ u32 val;
+
+ val = ipq_unipcs_reg_read32(qunipcs, PCS_CHANNEL_STS(channel));
+
+ state->link = !!(val & PCS_CHANNEL_LINK_STS);
+
+ if (!state->link)
+ return;
+
+ state->speed = SPEED_2500;
+ state->duplex = DUPLEX_FULL;
+ state->pause |= MLO_PAUSE_TXRX_MASK;
+}
+
static void ipq_unipcs_get_state_usxgmii(struct ipq_uniphy_pcs *qunipcs,
struct phylink_link_state *state)
{
@@ -373,6 +392,12 @@ static int ipq_unipcs_config_mode(struct
PCS_MODE_SEL_MASK | PCS_MODE_AN_MODE,
PCS_MODE_PSGMII);
break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ rate = 312500000;
+ ipq_unipcs_reg_modify32(qunipcs, PCS_MODE_CTRL,
+ PCS_MODE_SEL_MASK,
+ PCS_MODE_SGMII_PLUS);
+ break;
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_10GBASER:
rate = 312500000;
@@ -450,6 +475,22 @@ err:
return ret;
}
+static int ipq_unipcs_config_2500basex(struct ipq_uniphy_pcs *qunipcs,
+ phy_interface_t interface)
+{
+ int ret;
+
+ if (qunipcs->interface != interface) {
+ ret = ipq_unipcs_config_mode(qunipcs, interface);
+ if (ret)
+ return ret;
+
+ qunipcs->interface = interface;
+ }
+
+ return 0;
+}
+
static int ipq_unipcs_config_usxgmii(struct ipq_uniphy_pcs *qunipcs,
unsigned int neg_mode,
phy_interface_t interface)
@@ -522,6 +563,21 @@ static unsigned long ipq_unipcs_clock_ra
return rate;
}
+static unsigned long ipq_unipcs_clock_rate_get_gmiiplus(int speed)
+{
+ unsigned long rate = 0;
+
+ switch (speed) {
+ case SPEED_2500:
+ rate = 312500000;
+ break;
+ default:
+ break;
+ }
+
+ return rate;
+}
+
static unsigned long ipq_unipcs_clock_rate_get_xgmii(int speed)
{
unsigned long rate = 0;
@@ -566,6 +622,9 @@ ipq_unipcs_link_up_clock_rate_set(struct
case PHY_INTERFACE_MODE_PSGMII:
rate = ipq_unipcs_clock_rate_get_gmii(speed);
break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ rate = ipq_unipcs_clock_rate_get_gmiiplus(speed);
+ break;
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_10GBASER:
rate = ipq_unipcs_clock_rate_get_xgmii(speed);
@@ -627,6 +686,21 @@ pcs_adapter_reset:
PCS_CHANNEL_ADPT_RESET);
}
+static void ipq_unipcs_link_up_config_2500basex(struct ipq_uniphy_pcs *qunipcs,
+ int channel,
+ int speed)
+{
+ /* 2500BASEX do not support autoneg and do not need to
+ * configure PCS speed, only reset PCS adapter here.
+ */
+ ipq_unipcs_reg_modify32(qunipcs, PCS_CHANNEL_CTRL(channel),
+ PCS_CHANNEL_ADPT_RESET,
+ 0);
+ ipq_unipcs_reg_modify32(qunipcs, PCS_CHANNEL_CTRL(channel),
+ PCS_CHANNEL_ADPT_RESET,
+ PCS_CHANNEL_ADPT_RESET);
+}
+
static void ipq_unipcs_link_up_config_usxgmii(struct ipq_uniphy_pcs *qunipcs,
int speed)
{
@@ -669,6 +743,17 @@ static void ipq_unipcs_link_up_config_us
XPCS_USXG_ADPT_RESET);
}
+static int ipq_unipcs_validate(struct phylink_pcs *pcs,
+ unsigned long *supported,
+ const struct phylink_link_state *state)
+{
+ /* In-band autoneg is not supported for 2500BASEX */
+ if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
+ phylink_clear(supported, Autoneg);
+
+ return 0;
+}
+
static void ipq_unipcs_get_state(struct phylink_pcs *pcs,
struct phylink_link_state *state)
{
@@ -682,6 +767,9 @@ static void ipq_unipcs_get_state(struct
case PHY_INTERFACE_MODE_PSGMII:
ipq_unipcs_get_state_sgmii(qunipcs, channel, state);
break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ ipq_unipcs_get_state_2500basex(qunipcs, channel, state);
+ break;
case PHY_INTERFACE_MODE_USXGMII:
ipq_unipcs_get_state_usxgmii(qunipcs, state);
break;
@@ -716,6 +804,8 @@ static int ipq_unipcs_config(struct phyl
case PHY_INTERFACE_MODE_PSGMII:
return ipq_unipcs_config_sgmii(qunipcs, channel,
neg_mode, interface);
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return ipq_unipcs_config_2500basex(qunipcs, interface);
case PHY_INTERFACE_MODE_USXGMII:
return ipq_unipcs_config_usxgmii(qunipcs,
neg_mode, interface);
@@ -748,6 +838,10 @@ static void ipq_unipcs_link_up(struct ph
ipq_unipcs_link_up_config_sgmii(qunipcs, channel,
neg_mode, speed);
break;
+ case PHY_INTERFACE_MODE_2500BASEX:
+ ipq_unipcs_link_up_config_2500basex(qunipcs,
+ channel, speed);
+ break;
case PHY_INTERFACE_MODE_USXGMII:
ipq_unipcs_link_up_config_usxgmii(qunipcs, speed);
break;
@@ -761,6 +855,7 @@ static void ipq_unipcs_link_up(struct ph
}
static const struct phylink_pcs_ops ipq_unipcs_phylink_ops = {
+ .pcs_validate = ipq_unipcs_validate,
.pcs_get_state = ipq_unipcs_get_state,
.pcs_config = ipq_unipcs_config,
.pcs_link_up = ipq_unipcs_link_up,