]> git.ipfire.org Git - thirdparty/openwrt.git/blob
77029b6faa4ca92d07a3e01df943a17bfca2906d
[thirdparty/openwrt.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 --- a/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
16 +++ b/drivers/net/pcs/pcs-qcom-ipq-uniphy.c
17 @@ -57,6 +57,9 @@
18 FIELD_PREP(GENMASK(9, 2), \
19 FIELD_GET(XPCS_INDIRECT_ADDR_L, reg)))
20
21 +#define XPCS_10GBASER_STS 0x30020
22 +#define XPCS_10GBASER_LINK_STS BIT(12)
23 +
24 #define XPCS_DIG_CTRL 0x38000
25 #define XPCS_USXG_ADPT_RESET BIT(10)
26 #define XPCS_USXG_EN BIT(9)
27 @@ -320,6 +323,23 @@ static void ipq_unipcs_get_state_usxgmii
28 state->duplex = DUPLEX_HALF;
29 }
30
31 +static void ipq_unipcs_get_state_10gbaser(struct ipq_uniphy_pcs *qunipcs,
32 + struct phylink_link_state *state)
33 +{
34 + u32 val;
35 +
36 + val = ipq_unipcs_reg_read32(qunipcs, XPCS_10GBASER_STS);
37 +
38 + state->link = !!(val & XPCS_10GBASER_LINK_STS);
39 +
40 + if (!state->link)
41 + return;
42 +
43 + state->speed = SPEED_10000;
44 + state->duplex = DUPLEX_FULL;
45 + state->pause |= MLO_PAUSE_TXRX_MASK;
46 +}
47 +
48 static int ipq_unipcs_config_mode(struct ipq_uniphy_pcs *qunipcs,
49 phy_interface_t interface)
50 {
51 @@ -354,6 +374,7 @@ static int ipq_unipcs_config_mode(struct
52 PCS_MODE_PSGMII);
53 break;
54 case PHY_INTERFACE_MODE_USXGMII:
55 + case PHY_INTERFACE_MODE_10GBASER:
56 rate = 312500000;
57 ipq_unipcs_reg_modify32(qunipcs, PCS_MODE_CTRL,
58 PCS_MODE_SEL_MASK,
59 @@ -461,6 +482,25 @@ static int ipq_unipcs_config_usxgmii(str
60 return 0;
61 }
62
63 +static int ipq_unipcs_config_10gbaser(struct ipq_uniphy_pcs *qunipcs,
64 + phy_interface_t interface)
65 +{
66 + int ret;
67 +
68 + if (qunipcs->interface != interface) {
69 + ret = ipq_unipcs_config_mode(qunipcs, interface);
70 + if (ret)
71 + return ret;
72 +
73 + /* Deassert XPCS */
74 + reset_control_deassert(qunipcs->reset[XPCS_RESET]);
75 +
76 + qunipcs->interface = interface;
77 + }
78 +
79 + return 0;
80 +}
81 +
82 static unsigned long ipq_unipcs_clock_rate_get_gmii(int speed)
83 {
84 unsigned long rate = 0;
85 @@ -527,6 +567,7 @@ ipq_unipcs_link_up_clock_rate_set(struct
86 rate = ipq_unipcs_clock_rate_get_gmii(speed);
87 break;
88 case PHY_INTERFACE_MODE_USXGMII:
89 + case PHY_INTERFACE_MODE_10GBASER:
90 rate = ipq_unipcs_clock_rate_get_xgmii(speed);
91 break;
92 default:
93 @@ -644,6 +685,9 @@ static void ipq_unipcs_get_state(struct
94 case PHY_INTERFACE_MODE_USXGMII:
95 ipq_unipcs_get_state_usxgmii(qunipcs, state);
96 break;
97 + case PHY_INTERFACE_MODE_10GBASER:
98 + ipq_unipcs_get_state_10gbaser(qunipcs, state);
99 + break;
100 default:
101 break;
102 }
103 @@ -675,6 +719,8 @@ static int ipq_unipcs_config(struct phyl
104 case PHY_INTERFACE_MODE_USXGMII:
105 return ipq_unipcs_config_usxgmii(qunipcs,
106 neg_mode, interface);
107 + case PHY_INTERFACE_MODE_10GBASER:
108 + return ipq_unipcs_config_10gbaser(qunipcs, interface);
109 default:
110 dev_err(qunipcs->dev,
111 "interface %s not supported\n", phy_modes(interface));
112 @@ -705,6 +751,8 @@ static void ipq_unipcs_link_up(struct ph
113 case PHY_INTERFACE_MODE_USXGMII:
114 ipq_unipcs_link_up_config_usxgmii(qunipcs, speed);
115 break;
116 + case PHY_INTERFACE_MODE_10GBASER:
117 + break;
118 default:
119 dev_err(qunipcs->dev,
120 "interface %s not supported\n", phy_modes(interface));