From 23f3550c387246025ed2971989b747a5936bf080 Mon Sep 17 00:00:00 2001
From: Lei Wei <quic_leiwei@quicinc.com>
Date: Tue, 9 Apr 2024 01:07:22 +0800
Subject: [PATCH 14/50] net:pcs: Add 1000BASEX interface mode support to IPQ
 UNIPHY PCS driver

1000BASEX is used when PCS connects with a 1G SFP module.

Change-Id: Ied7298de3c1ecba74e6457a07fdd6b3ceab79728
Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
---
 drivers/net/pcs/pcs-qcom-ipq-uniphy.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

--- a/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
+++ b/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
@@ -27,6 +27,9 @@
 #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_SGMII_CTRL_MASK	GENMASK(6, 4)
+#define PCS_MODE_SGMII_CTRL_1000BASEX	FIELD_PREP(PCS_MODE_SGMII_CTRL_MASK, \
+						   0x0)
 #define PCS_MODE_AN_MODE		BIT(0)
 
 #define PCS_CHANNEL_CTRL(x)		(0x480 + 0x18 * (x))
@@ -392,6 +395,13 @@ static int ipq_unipcs_config_mode(struct
 					PCS_MODE_SEL_MASK | PCS_MODE_AN_MODE,
 					PCS_MODE_PSGMII);
 		break;
+	case PHY_INTERFACE_MODE_1000BASEX:
+		ipq_unipcs_reg_modify32(qunipcs, PCS_MODE_CTRL,
+					PCS_MODE_SEL_MASK |
+					PCS_MODE_SGMII_CTRL_MASK,
+					PCS_MODE_SGMII |
+					PCS_MODE_SGMII_CTRL_1000BASEX);
+		break;
 	case PHY_INTERFACE_MODE_2500BASEX:
 		rate = 312500000;
 		ipq_unipcs_reg_modify32(qunipcs, PCS_MODE_CTRL,
@@ -620,6 +630,7 @@ ipq_unipcs_link_up_clock_rate_set(struct
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_QSGMII:
 	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
 		rate = ipq_unipcs_clock_rate_get_gmii(speed);
 		break;
 	case PHY_INTERFACE_MODE_2500BASEX:
@@ -765,6 +776,10 @@ static void ipq_unipcs_get_state(struct
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_QSGMII:
 	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
+		/* SGMII and 1000BASEX in-band autoneg word format are decoded
+		 * by PCS hardware and both placed to the same status register.
+		 */
 		ipq_unipcs_get_state_sgmii(qunipcs, channel, state);
 		break;
 	case PHY_INTERFACE_MODE_2500BASEX:
@@ -802,6 +817,7 @@ static int ipq_unipcs_config(struct phyl
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_QSGMII:
 	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
 		return ipq_unipcs_config_sgmii(qunipcs, channel,
 					       neg_mode, interface);
 	case PHY_INTERFACE_MODE_2500BASEX:
@@ -818,6 +834,11 @@ static int ipq_unipcs_config(struct phyl
 	};
 }
 
+static void qcom_ipq_unipcs_an_restart(struct phylink_pcs *pcs)
+{
+	/* Currently not used */
+}
+
 static void ipq_unipcs_link_up(struct phylink_pcs *pcs,
 			       unsigned int neg_mode,
 			       phy_interface_t interface,
@@ -835,6 +856,7 @@ static void ipq_unipcs_link_up(struct ph
 	case PHY_INTERFACE_MODE_SGMII:
 	case PHY_INTERFACE_MODE_QSGMII:
 	case PHY_INTERFACE_MODE_PSGMII:
+	case PHY_INTERFACE_MODE_1000BASEX:
 		ipq_unipcs_link_up_config_sgmii(qunipcs, channel,
 						neg_mode, speed);
 		break;
@@ -858,6 +880,7 @@ static const struct phylink_pcs_ops ipq_
 	.pcs_validate = ipq_unipcs_validate,
 	.pcs_get_state = ipq_unipcs_get_state,
 	.pcs_config = ipq_unipcs_config,
+	.pcs_an_restart = qcom_ipq_unipcs_an_restart,
 	.pcs_link_up = ipq_unipcs_link_up,
 };
 
