ea1567590bc7a737c3953db8768f85410e302def
[openwrt/staging/stintel.git] /
1 From f23eb497c891985126a065f950bc61e9c404bb12 Mon Sep 17 00:00:00 2001
2 From: Lei Wei <quic_leiwei@quicinc.com>
3 Date: Wed, 6 Mar 2024 17:40:52 +0800
4 Subject: [PATCH 12/50] net: pcs: Add 10GBASER interface mode support to IPQ
5 UNIPHY PCS driver
6
7 10GBASER mode is used when PCS connects with a 10G SFP module.
8
9 Change-Id: Ifc3c3bb23811807a9b34e88771aab2c830c2327c
10 Signed-off-by: Lei Wei <quic_leiwei@quicinc.com>
11 ---
12 drivers/net/pcs/pcs-qcom-ipq-uniphy.c | 48 +++++++++++++++++++++++++++
13 1 file changed, 48 insertions(+)
14
15 diff --git a/drivers/net/pcs/pcs-qcom-ipq-uniphy.c b/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
16 index 837de629d0b2..68a1715531ef 100644
17 --- a/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
18 +++ b/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
19 @@ -57,6 +57,9 @@
20 FIELD_PREP(GENMASK(9, 2), \
21 FIELD_GET(XPCS_INDIRECT_ADDR_L, reg)))
22
23 +#define XPCS_10GBASER_STS 0x30020
24 +#define XPCS_10GBASER_LINK_STS BIT(12)
25 +
26 #define XPCS_DIG_CTRL 0x38000
27 #define XPCS_USXG_ADPT_RESET BIT(10)
28 #define XPCS_USXG_EN BIT(9)
29 @@ -320,6 +323,23 @@ static void ipq_unipcs_get_state_usxgmii(struct ipq_uniphy_pcs *qunipcs,
30 state->duplex = DUPLEX_HALF;
31 }
32
33 +static void ipq_unipcs_get_state_10gbaser(struct ipq_uniphy_pcs *qunipcs,
34 + struct phylink_link_state *state)
35 +{
36 + u32 val;
37 +
38 + val = ipq_unipcs_reg_read32(qunipcs, XPCS_10GBASER_STS);
39 +
40 + state->link = !!(val & XPCS_10GBASER_LINK_STS);
41 +
42 + if (!state->link)
43 + return;
44 +
45 + state->speed = SPEED_10000;
46 + state->duplex = DUPLEX_FULL;
47 + state->pause |= MLO_PAUSE_TXRX_MASK;
48 +}
49 +
50 static int ipq_unipcs_config_mode(struct ipq_uniphy_pcs *qunipcs,
51 phy_interface_t interface)
52 {
53 @@ -354,6 +374,7 @@ static int ipq_unipcs_config_mode(struct ipq_uniphy_pcs *qunipcs,
54 PCS_MODE_PSGMII);
55 break;
56 case PHY_INTERFACE_MODE_USXGMII:
57 + case PHY_INTERFACE_MODE_10GBASER:
58 rate = 312500000;
59 ipq_unipcs_reg_modify32(qunipcs, PCS_MODE_CTRL,
60 PCS_MODE_SEL_MASK,
61 @@ -461,6 +482,25 @@ static int ipq_unipcs_config_usxgmii(struct ipq_uniphy_pcs *qunipcs,
62 return 0;
63 }
64
65 +static int ipq_unipcs_config_10gbaser(struct ipq_uniphy_pcs *qunipcs,
66 + phy_interface_t interface)
67 +{
68 + int ret;
69 +
70 + if (qunipcs->interface != interface) {
71 + ret = ipq_unipcs_config_mode(qunipcs, interface);
72 + if (ret)
73 + return ret;
74 +
75 + /* Deassert XPCS */
76 + reset_control_deassert(qunipcs->reset[XPCS_RESET]);
77 +
78 + qunipcs->interface = interface;
79 + }
80 +
81 + return 0;
82 +}
83 +
84 static unsigned long ipq_unipcs_clock_rate_get_gmii(int speed)
85 {
86 unsigned long rate = 0;
87 @@ -527,6 +567,7 @@ ipq_unipcs_link_up_clock_rate_set(struct ipq_uniphy_pcs_ch *qunipcs_ch,
88 rate = ipq_unipcs_clock_rate_get_gmii(speed);
89 break;
90 case PHY_INTERFACE_MODE_USXGMII:
91 + case PHY_INTERFACE_MODE_10GBASER:
92 rate = ipq_unipcs_clock_rate_get_xgmii(speed);
93 break;
94 default:
95 @@ -644,6 +685,9 @@ static void ipq_unipcs_get_state(struct phylink_pcs *pcs,
96 case PHY_INTERFACE_MODE_USXGMII:
97 ipq_unipcs_get_state_usxgmii(qunipcs, state);
98 break;
99 + case PHY_INTERFACE_MODE_10GBASER:
100 + ipq_unipcs_get_state_10gbaser(qunipcs, state);
101 + break;
102 default:
103 break;
104 }
105 @@ -675,6 +719,8 @@ static int ipq_unipcs_config(struct phylink_pcs *pcs,
106 case PHY_INTERFACE_MODE_USXGMII:
107 return ipq_unipcs_config_usxgmii(qunipcs,
108 neg_mode, interface);
109 + case PHY_INTERFACE_MODE_10GBASER:
110 + return ipq_unipcs_config_10gbaser(qunipcs, interface);
111 default:
112 dev_err(qunipcs->dev,
113 "interface %s not supported\n", phy_modes(interface));
114 @@ -705,6 +751,8 @@ static void ipq_unipcs_link_up(struct phylink_pcs *pcs,
115 case PHY_INTERFACE_MODE_USXGMII:
116 ipq_unipcs_link_up_config_usxgmii(qunipcs, speed);
117 break;
118 + case PHY_INTERFACE_MODE_10GBASER:
119 + break;
120 default:
121 dev_err(qunipcs->dev,
122 "interface %s not supported\n", phy_modes(interface));
123 --
124 2.45.2
125