9c6bfabc45592d29318ed1c55d398001cbd29daf
[openwrt/staging/xback.git] /
1 From 07f9bb8eb006e9664d651089a1f422d045e093e3 Mon Sep 17 00:00:00 2001
2 From: Lei Wei <quic_leiwei@quicinc.com>
3 Date: Tue, 9 Apr 2024 01:07:22 +0800
4 Subject: [PATCH] net: pcs: Add 1000BASEX interface mode support to IPQ UNIPHY
5 PCS driver
6
7 1000BASEX is used when PCS connects with a 1G SFP module.
8
9 Change-Id: Ied7298de3c1ecba74e6457a07fdd6b3ceab79728
10 Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
11 Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
12 ---
13 drivers/net/pcs/pcs-qcom-ipq9574.c | 19 +++++++++++++++++--
14 1 file changed, 17 insertions(+), 2 deletions(-)
15
16 --- a/drivers/net/pcs/pcs-qcom-ipq9574.c
17 +++ b/drivers/net/pcs/pcs-qcom-ipq9574.c
18 @@ -31,6 +31,9 @@
19 #define PCS_MODE_PSGMII FIELD_PREP(PCS_MODE_SEL_MASK, 0x2)
20 #define PCS_MODE_SGMII_PLUS FIELD_PREP(PCS_MODE_SEL_MASK, 0x8)
21 #define PCS_MODE_XPCS FIELD_PREP(PCS_MODE_SEL_MASK, 0x10)
22 +#define PCS_MODE_SGMII_CTRL_MASK GENMASK(6, 4)
23 +#define PCS_MODE_SGMII_CTRL_1000BASEX FIELD_PREP(PCS_MODE_SGMII_CTRL_MASK, \
24 + 0x0)
25
26 #define PCS_MII_CTRL(x) (0x480 + 0x18 * (x))
27 #define PCS_MII_ADPT_RESET BIT(11)
28 @@ -283,7 +286,7 @@ static int ipq_pcs_config_mode(struct ip
29 phy_interface_t interface)
30 {
31 unsigned long rate = 125000000;
32 - unsigned int val;
33 + unsigned int val, mask = PCS_MODE_SEL_MASK;
34 int ret;
35
36 /* Assert XPCS reset */
37 @@ -297,6 +300,10 @@ static int ipq_pcs_config_mode(struct ip
38 case PHY_INTERFACE_MODE_QSGMII:
39 val = PCS_MODE_QSGMII;
40 break;
41 + case PHY_INTERFACE_MODE_1000BASEX:
42 + mask |= PCS_MODE_SGMII_CTRL_MASK;
43 + val = PCS_MODE_SGMII | PCS_MODE_SGMII_CTRL_1000BASEX;
44 + break;
45 case PHY_INTERFACE_MODE_2500BASEX:
46 val = PCS_MODE_SGMII_PLUS;
47 rate = 312500000;
48 @@ -316,7 +323,7 @@ static int ipq_pcs_config_mode(struct ip
49 }
50
51 ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL,
52 - PCS_MODE_SEL_MASK, val);
53 + mask, val);
54 if (ret)
55 return ret;
56
57 @@ -523,6 +530,7 @@ ipq_unipcs_link_up_clock_rate_set(struct
58 case PHY_INTERFACE_MODE_SGMII:
59 case PHY_INTERFACE_MODE_QSGMII:
60 case PHY_INTERFACE_MODE_PSGMII:
61 + case PHY_INTERFACE_MODE_1000BASEX:
62 rate = ipq_unipcs_clock_rate_get_gmii(speed);
63 break;
64 case PHY_INTERFACE_MODE_2500BASEX:
65 @@ -657,6 +665,7 @@ static int ipq_pcs_validate(struct phyli
66 case PHY_INTERFACE_MODE_SGMII:
67 case PHY_INTERFACE_MODE_QSGMII:
68 case PHY_INTERFACE_MODE_10GBASER:
69 + case PHY_INTERFACE_MODE_1000BASEX:
70 return 0;
71 case PHY_INTERFACE_MODE_2500BASEX:
72 /* In-band autoneg is not supported for 2500BASEX */
73 @@ -731,6 +740,10 @@ static void ipq_pcs_get_state(struct phy
74 case PHY_INTERFACE_MODE_SGMII:
75 case PHY_INTERFACE_MODE_QSGMII:
76 case PHY_INTERFACE_MODE_PSGMII:
77 + case PHY_INTERFACE_MODE_1000BASEX:
78 + /* SGMII and 1000BASEX in-band autoneg word format are decoded
79 + * by PCS hardware and both placed to the same status register.
80 + */
81 ipq_pcs_get_state_sgmii(qpcs, index, state);
82 break;
83 case PHY_INTERFACE_MODE_2500BASEX:
84 @@ -768,6 +781,7 @@ static int ipq_pcs_config(struct phylink
85 case PHY_INTERFACE_MODE_SGMII:
86 case PHY_INTERFACE_MODE_QSGMII:
87 case PHY_INTERFACE_MODE_PSGMII:
88 + case PHY_INTERFACE_MODE_1000BASEX:
89 return ipq_pcs_config_sgmii(qpcs, index, neg_mode, interface);
90 case PHY_INTERFACE_MODE_2500BASEX:
91 return ipq_unipcs_config_2500basex(qpcs, interface);
92 @@ -800,6 +814,7 @@ static void ipq_pcs_link_up(struct phyli
93 case PHY_INTERFACE_MODE_SGMII:
94 case PHY_INTERFACE_MODE_QSGMII:
95 case PHY_INTERFACE_MODE_PSGMII:
96 + case PHY_INTERFACE_MODE_1000BASEX:
97 ret = ipq_pcs_link_up_config_sgmii(qpcs, index,
98 neg_mode, speed);
99 break;