I generate patches form git, so maintaining an old numbering scheme does not integrate well with my workflow. renumber the pacthes here so that the commit shows only the changes to the patches. Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com> Link: https://github.com/openwrt/openwrt/pull/21506 Signed-off-by: Robert Marko <robimarko@gmail.com>
167 lines
5.3 KiB
Diff
167 lines
5.3 KiB
Diff
From 0d3a93e3a5544daec59d8f10ac5ccab39849536e 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] 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>
|
|
Alex G: use regmap to read/write registers
|
|
's/ipq_unipcs/ipq_pcs/' in function names as suggested by Luo Jie
|
|
Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
|
---
|
|
drivers/net/pcs/pcs-qcom-ipq9574.c | 67 ++++++++++++++++++++++++++++++
|
|
1 file changed, 67 insertions(+)
|
|
|
|
--- a/drivers/net/pcs/pcs-qcom-ipq9574.c
|
|
+++ b/drivers/net/pcs/pcs-qcom-ipq9574.c
|
|
@@ -26,6 +26,7 @@
|
|
#define PCS_MODE_SEL_MASK GENMASK(12, 8)
|
|
#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_2500BASEX FIELD_PREP(PCS_MODE_SEL_MASK, 0x8)
|
|
#define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10)
|
|
|
|
#define PCS_MII_CTRL(x) (0x480 + 0x18 * (x))
|
|
@@ -155,6 +156,29 @@ static void ipq_pcs_get_state_sgmii(stru
|
|
state->duplex = DUPLEX_HALF;
|
|
}
|
|
|
|
+static void ipq_pcs_get_state_2500basex(struct ipq_pcs *qpcs,
|
|
+ struct phylink_link_state *state)
|
|
+{
|
|
+ unsigned int val;
|
|
+ int ret;
|
|
+
|
|
+ ret = regmap_read(qpcs->regmap, PCS_MII_STS(0), &val);
|
|
+ if (ret) {
|
|
+ state->link = 0;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+
|
|
+ state->link = !!(val & PCS_MII_LINK_STS);
|
|
+
|
|
+ if (!state->link)
|
|
+ return;
|
|
+
|
|
+ state->speed = SPEED_2500;
|
|
+ state->duplex = DUPLEX_FULL;
|
|
+ state->pause |= MLO_PAUSE_TXRX_MASK;
|
|
+}
|
|
+
|
|
static void ipq_pcs_get_state_usxgmii(struct ipq_pcs *qpcs,
|
|
struct phylink_link_state *state)
|
|
{
|
|
@@ -236,6 +260,10 @@ static int ipq_pcs_config_mode(struct ip
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
val = PCS_MODE_QSGMII;
|
|
break;
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ val = PCS_MODE_2500BASEX;
|
|
+ rate = 312500000;
|
|
+ break;
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
val = PCS_MODE_XPCS;
|
|
@@ -314,6 +342,15 @@ static int ipq_pcs_config_sgmii(struct i
|
|
PCS_MII_CTRL(index), PCS_MII_FORCE_MODE);
|
|
}
|
|
|
|
+static int ipq_pcs_config_2500basex(struct ipq_pcs *qpcs)
|
|
+{
|
|
+ /* Configure PCS for 2500BASEX mode if required */
|
|
+ if (qpcs->interface == PHY_INTERFACE_MODE_2500BASEX)
|
|
+ return 0;
|
|
+
|
|
+ return ipq_pcs_config_mode(qpcs, PHY_INTERFACE_MODE_2500BASEX);
|
|
+}
|
|
+
|
|
static int ipq_pcs_config_usxgmii(struct ipq_pcs *qpcs)
|
|
{
|
|
int ret;
|
|
@@ -388,6 +425,22 @@ static int ipq_pcs_link_up_config_sgmii(
|
|
PCS_MII_CTRL(index), PCS_MII_ADPT_RESET);
|
|
}
|
|
|
|
+static int ipq_pcs_link_up_config_2500basex(struct ipq_pcs *qpcs, int speed)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ /* 2500BASEX does not support autoneg and does not need to
|
|
+ * configure PCS speed. Only reset PCS adapter here.
|
|
+ */
|
|
+ ret = regmap_clear_bits(qpcs->regmap,
|
|
+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+ return regmap_set_bits(qpcs->regmap,
|
|
+ PCS_MII_CTRL(0), PCS_MII_ADPT_RESET);
|
|
+}
|
|
+
|
|
static int ipq_pcs_link_up_config_usxgmii(struct ipq_pcs *qpcs, int speed)
|
|
{
|
|
unsigned int val;
|
|
@@ -436,6 +489,10 @@ static int ipq_pcs_validate(struct phyli
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
return 0;
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ /* In-band autoneg is not supported for 2500BASEX */
|
|
+ phylink_clear(supported, Autoneg);
|
|
+ return 0;
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
/* USXGMII only supports full duplex mode */
|
|
phylink_clear(supported, 100baseT_Half);
|
|
@@ -454,6 +511,7 @@ static unsigned int ipq_pcs_inband_caps(
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
return LINK_INBAND_DISABLE;
|
|
default:
|
|
@@ -507,6 +565,9 @@ static void ipq_pcs_get_state(struct phy
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
ipq_pcs_get_state_sgmii(qpcs, index, state);
|
|
break;
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ ipq_pcs_get_state_2500basex(qpcs, state);
|
|
+ break;
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
ipq_pcs_get_state_usxgmii(qpcs, state);
|
|
break;
|
|
@@ -539,6 +600,8 @@ static int ipq_pcs_config(struct phylink
|
|
case PHY_INTERFACE_MODE_SGMII:
|
|
case PHY_INTERFACE_MODE_QSGMII:
|
|
return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface);
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ return ipq_pcs_config_2500basex(qpcs);
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
return ipq_pcs_config_usxgmii(qpcs);
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
@@ -564,6 +627,9 @@ static void ipq_pcs_link_up(struct phyli
|
|
ret = ipq_pcs_link_up_config_sgmii(qpcs, index,
|
|
neg_mode, speed);
|
|
break;
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
+ ret = ipq_pcs_link_up_config_2500basex(qpcs, speed);
|
|
+ break;
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
ret = ipq_pcs_link_up_config_usxgmii(qpcs, speed);
|
|
break;
|
|
@@ -648,6 +714,7 @@ static int ipq_pcs_create_miis(struct ip
|
|
static unsigned long ipq_pcs_clk_rate_get(struct ipq_pcs *qpcs)
|
|
{
|
|
switch (qpcs->interface) {
|
|
+ case PHY_INTERFACE_MODE_2500BASEX:
|
|
case PHY_INTERFACE_MODE_USXGMII:
|
|
case PHY_INTERFACE_MODE_10GBASER:
|
|
return 312500000;
|