xref: /linux/drivers/phy/freescale/phy-fsl-lynx-28g.c (revision f124b54b19223c85dabd9421ec622d8256e240de)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021-2022 NXP. */
3 
4 #include <linux/bitfield.h>
5 #include <linux/module.h>
6 #include <linux/of.h>
7 #include <linux/phy.h>
8 #include <linux/phy/phy.h>
9 #include <linux/platform_device.h>
10 #include <linux/workqueue.h>
11 
12 #include "phy-fsl-lynx-core.h"
13 
14 #define LYNX_28G_NUM_LANE			8
15 
16 /* SoC IP wrapper for protocol converters */
17 #define PCC8					0x10a0
18 #define PCC8_SGMIIa_KX				BIT(3)
19 #define PCC8_SGMIIa_CFG				BIT(0)
20 
21 #define PCCC					0x10b0
22 #define PCCC_SXGMIIn_XFI			BIT(3)
23 #define PCCC_SXGMIIn_CFG			BIT(0)
24 
25 #define PCCD					0x10b4
26 #define PCCD_E25Gn_CFG				BIT(0)
27 
28 #define PCCE					0x10b8
29 #define PCCE_E40Gn_LRV				BIT(3)
30 #define PCCE_E40Gn_CFG				BIT(0)
31 #define PCCE_E50Gn_LRV				BIT(3)
32 #define PCCE_E50GnCFG				BIT(0)
33 #define PCCE_E100Gn_LRV				BIT(3)
34 #define PCCE_E100Gn_CFG				BIT(0)
35 
36 #define SGMII_CFG(id)				(28 - (id) * 4) /* Offset into PCC8 */
37 #define SXGMII_CFG(id)				(28 - (id) * 4) /* Offset into PCCC */
38 #define E25G_CFG(id)				(28 - (id) * 4) /* Offset into PCCD */
39 #define E40G_CFG(id)				(28 - (id) * 4) /* Offset into PCCE */
40 #define E50G_CFG(id)				(20 - (id) * 4) /* Offset into PCCE */
41 #define E100G_CFG(id)				(12 - (id) * 4) /* Offset into PCCE */
42 
43 /* Per PLL registers */
44 #define PLLnRSTCTL(pll)				(0x400 + (pll) * 0x100 + 0x0)
45 #define PLLnRSTCTL_DIS				BIT(24)
46 #define PLLnRSTCTL_LOCK				BIT(23)
47 
48 #define PLLnCR0(pll)				(0x400 + (pll) * 0x100 + 0x4)
49 #define PLLnCR0_REFCLK_SEL			GENMASK(20, 16)
50 #define PLLnCR0_REFCLK_SEL_100MHZ		0x0
51 #define PLLnCR0_REFCLK_SEL_125MHZ		0x1
52 #define PLLnCR0_REFCLK_SEL_156MHZ		0x2
53 #define PLLnCR0_REFCLK_SEL_150MHZ		0x3
54 #define PLLnCR0_REFCLK_SEL_161MHZ		0x4
55 
56 #define PLLnCR1(pll)				(0x400 + (pll) * 0x100 + 0x8)
57 #define PLLnCR1_FRATE_SEL			GENMASK(28, 24)
58 #define PLLnCR1_FRATE_5G_10GVCO			0x0
59 #define PLLnCR1_FRATE_5G_25GVCO			0x10
60 #define PLLnCR1_FRATE_10G_20GVCO		0x6
61 #define PLLnCR1_FRATE_12G_25GVCO		0x16
62 
63 /* Per SerDes lane registers */
64 /* Lane a General Control Register */
65 #define LNaGCR0(lane)				(0x800 + (lane) * 0x100 + 0x0)
66 #define LNaGCR0_PROTO_SEL			GENMASK(7, 3)
67 #define LNaGCR0_PROTO_SEL_SGMII			0x1
68 #define LNaGCR0_PROTO_SEL_XFI			0xa
69 #define LNaGCR0_PROTO_SEL_25G			0x1a
70 #define LNaGCR0_IF_WIDTH			GENMASK(2, 0)
71 #define LNaGCR0_IF_WIDTH_10_BIT			0x0
72 #define LNaGCR0_IF_WIDTH_20_BIT			0x2
73 #define LNaGCR0_IF_WIDTH_40_BIT			0x4
74 
75 /* Lane a Tx Reset Control Register */
76 #define LNaTRSTCTL(lane)			(0x800 + (lane) * 0x100 + 0x20)
77 #define LNaTRSTCTL_RST_REQ			BIT(31)
78 #define LNaTRSTCTL_RST_DONE			BIT(30)
79 #define LNaTRSTCTL_HLT_REQ			BIT(27)
80 #define LNaTRSTCTL_STP_REQ			BIT(26)
81 #define LNaTRSTCTL_DIS				BIT(24)
82 
83 /* Lane a Tx General Control Register */
84 #define LNaTGCR0(lane)				(0x800 + (lane) * 0x100 + 0x24)
85 #define LNaTGCR0_USE_PLL			BIT(28)
86 #define LNaTGCR0_USE_PLLF			0x0
87 #define LNaTGCR0_USE_PLLS			0x1
88 #define LNaTGCR0_N_RATE				GENMASK(26, 24)
89 #define LNaTGCR0_N_RATE_FULL			0x0
90 #define LNaTGCR0_N_RATE_HALF			0x1
91 #define LNaTGCR0_N_RATE_QUARTER			0x2
92 #define LNaTGCR0_N_RATE_DOUBLE			0x3
93 
94 #define LNaTECR0(lane)				(0x800 + (lane) * 0x100 + 0x30)
95 #define LNaTECR0_EQ_TYPE			GENMASK(30, 28)
96 #define LNaTECR0_EQ_SGN_PREQ			BIT(23)
97 #define LNaTECR0_EQ_PREQ			GENMASK(19, 16)
98 #define LNaTECR0_EQ_SGN_POST1Q			BIT(15)
99 #define LNaTECR0_EQ_POST1Q			GENMASK(12, 8)
100 #define LNaTECR0_EQ_AMP_RED			GENMASK(5, 0)
101 
102 #define LNaTECR1(lane)				(0x800 + (lane) * 0x100 + 0x34)
103 #define LNaTECR1_EQ_ADPT_EQ_DRVR_DIS		BIT(31)
104 #define LNaTECR1_EQ_ADPT_EQ			GENMASK(29, 24)
105 
106 /* Lane a Rx Reset Control Register */
107 #define LNaRRSTCTL(lane)			(0x800 + (lane) * 0x100 + 0x40)
108 #define LNaRRSTCTL_RST_REQ			BIT(31)
109 #define LNaRRSTCTL_RST_DONE			BIT(30)
110 #define LNaRRSTCTL_HLT_REQ			BIT(27)
111 #define LNaRRSTCTL_STP_REQ			BIT(26)
112 #define LNaRRSTCTL_DIS				BIT(24)
113 #define LNaRRSTCTL_CDR_LOCK			BIT(12)
114 
115 /* Lane a Rx General Control Register */
116 #define LNaRGCR0(lane)				(0x800 + (lane) * 0x100 + 0x44)
117 #define LNaRGCR0_USE_PLL			BIT(28)
118 #define LNaRGCR0_USE_PLLF			0x0
119 #define LNaRGCR0_USE_PLLS			0x1
120 #define LNaRGCR0_N_RATE				GENMASK(26, 24)
121 #define LNaRGCR0_N_RATE_FULL			0x0
122 #define LNaRGCR0_N_RATE_HALF			0x1
123 #define LNaRGCR0_N_RATE_QUARTER			0x2
124 #define LNaRGCR0_N_RATE_DOUBLE			0x3
125 
126 #define LNaRGCR1(lane)				(0x800 + (lane) * 0x100 + 0x48)
127 #define LNaRGCR1_RX_ORD_ELECIDLE		BIT(31)
128 #define LNaRGCR1_DATA_LOST_FLT			BIT(30)
129 #define LNaRGCR1_DATA_LOST			BIT(29)
130 #define LNaRGCR1_IDLE_CONFIG			BIT(28)
131 #define LNaRGCR1_ENTER_IDLE_FLT_SEL		GENMASK(26, 24)
132 #define LNaRGCR1_EXIT_IDLE_FLT_SEL		GENMASK(22, 20)
133 #define LNaRGCR1_DATA_LOST_TH_SEL		GENMASK(18, 16)
134 #define LNaRGCR1_EXT_REC_CLK_SEL		GENMASK(10, 8)
135 #define LNaRGCR1_WAKE_TX_DIS			BIT(5)
136 #define LNaRGCR1_PHY_RDY			BIT(4)
137 #define LNaRGCR1_CHANGE_RX_CLK			BIT(3)
138 #define LNaRGCR1_PWR_MGT			GENMASK(2, 0)
139 
140 #define LNaRECR0(lane)				(0x800 + (lane) * 0x100 + 0x50)
141 #define LNaRECR0_EQ_GAINK2_HF_OV_EN		BIT(31)
142 #define LNaRECR0_EQ_GAINK2_HF_OV		GENMASK(28, 24)
143 #define LNaRECR0_EQ_GAINK3_MF_OV_EN		BIT(23)
144 #define LNaRECR0_EQ_GAINK3_MF_OV		GENMASK(20, 16)
145 #define LNaRECR0_EQ_GAINK4_LF_OV_EN		BIT(7)
146 #define LNaRECR0_EQ_GAINK4_LF_DIS		BIT(6)
147 #define LNaRECR0_EQ_GAINK4_LF_OV		GENMASK(4, 0)
148 
149 #define LNaRECR1(lane)				(0x800 + (lane) * 0x100 + 0x54)
150 #define LNaRECR1_EQ_BLW_OV_EN			BIT(31)
151 #define LNaRECR1_EQ_BLW_OV			GENMASK(28, 24)
152 #define LNaRECR1_EQ_OFFSET_OV_EN		BIT(23)
153 #define LNaRECR1_EQ_OFFSET_OV			GENMASK(21, 16)
154 
155 #define LNaRECR2(lane)				(0x800 + (lane) * 0x100 + 0x58)
156 #define LNaRECR2_EQ_OFFSET_RNG_DBL		BIT(31)
157 #define LNaRECR2_EQ_BOOST			GENMASK(29, 28)
158 #define LNaRECR2_EQ_BLW_SEL			GENMASK(25, 24)
159 #define LNaRECR2_EQ_ZERO			GENMASK(17, 16)
160 #define LNaRECR2_EQ_IND				GENMASK(13, 12)
161 #define LNaRECR2_EQ_BIN_DATA_AVG_TC		GENMASK(5, 4)
162 #define LNaRECR2_SPARE_IN			GENMASK(1, 0)
163 
164 #define LNaRECR3(lane)				(0x800 + (lane) * 0x100 + 0x5c)
165 #define LNaRECR3_EQ_SNAP_START			BIT(31)
166 #define LNaRECR3_EQ_SNAP_DONE			BIT(30)
167 #define LNaRECR3_EQ_GAINK2_HF_STAT		GENMASK(28, 24)
168 #define LNaRECR3_EQ_GAINK3_MF_STAT		GENMASK(20, 16)
169 #define LNaRECR3_SPARE_OUT			GENMASK(13, 12)
170 #define LNaRECR3_EQ_GAINK4_LF_STAT		GENMASK(4, 0)
171 
172 #define LNaRECR4(lane)				(0x800 + (lane) * 0x100 + 0x60)
173 #define LNaRECR4_BLW_STAT			GENMASK(28, 24)
174 #define LNaRECR4_EQ_OFFSET_STAT			GENMASK(21, 16)
175 #define LNaRECR4_EQ_BIN_DATA_SEL		GENMASK(15, 12)
176 #define LNaRECR4_EQ_BIN_DATA			GENMASK(8, 0) /* bit 9 is reserved */
177 #define LNaRECR4_EQ_BIN_DATA_SGN		BIT(8)
178 
179 #define LNaRCCR0(lane)				(0x800 + (lane) * 0x100 + 0x68)
180 #define LNaRCCR0_CAL_EN				BIT(31)
181 #define LNaRCCR0_MEAS_EN			BIT(30)
182 #define LNaRCCR0_CAL_BIN_SEL			BIT(28)
183 #define LNaRCCR0_CAL_DC3_DIS			BIT(27)
184 #define LNaRCCR0_CAL_DC2_DIS			BIT(26)
185 #define LNaRCCR0_CAL_DC1_DIS			BIT(25)
186 #define LNaRCCR0_CAL_DC0_DIS			BIT(24)
187 #define LNaRCCR0_CAL_AC3_OV_EN			BIT(15)
188 #define LNaRCCR0_CAL_AC3_OV			GENMASK(11, 8)
189 #define LNaRCCR0_CAL_AC2_OV_EN			BIT(7)
190 
191 #define LNaRSCCR0(lane)				(0x800 + (lane) * 0x100 + 0x74)
192 #define LNaRSCCR0_SMP_OFF_EN			BIT(31)
193 #define LNaRSCCR0_SMP_OFF_OV_EN			BIT(30)
194 #define LNaRSCCR0_SMP_MAN_OFF_EN		BIT(29)
195 #define LNaRSCCR0_SMP_OFF_RNG_OV_EN		BIT(27)
196 #define LNaRSCCR0_SMP_OFF_RNG_4X_OV		BIT(25)
197 #define LNaRSCCR0_SMP_OFF_RNG_2X_OV		BIT(24)
198 #define LNaRSCCR0_SMP_AUTOZ_PD			BIT(23)
199 #define LNaRSCCR0_SMP_AUTOZ_CTRL		GENMASK(19, 16)
200 #define LNaRSCCR0_SMP_AUTOZ_D1R			GENMASK(13, 12)
201 #define LNaRSCCR0_SMP_AUTOZ_D1F			GENMASK(9, 8)
202 #define LNaRSCCR0_SMP_AUTOZ_EG1R		GENMASK(5, 4)
203 #define LNaRSCCR0_SMP_AUTOZ_EG1F		GENMASK(1, 0)
204 
205 #define LNaTTLCR0(lane)				(0x800 + (lane) * 0x100 + 0x80)
206 #define LNaTTLCR0_TTL_FLT_SEL			GENMASK(29, 24)
207 #define LNaTTLCR0_TTL_SLO_PM_BYP		BIT(22)
208 #define LNaTTLCR0_STALL_DET_DIS			BIT(21)
209 #define LNaTTLCR0_INACT_MON_DIS			BIT(20)
210 #define LNaTTLCR0_CDR_OV			GENMASK(18, 16)
211 #define LNaTTLCR0_DATA_IN_SSC			BIT(15)
212 #define LNaTTLCR0_CDR_MIN_SMP_ON		GENMASK(1, 0)
213 
214 #define LNaTCSR0(lane)				(0x800 + (lane) * 0x100 + 0xa0)
215 #define LNaTCSR0_SD_STAT_OBS_EN			BIT(31)
216 #define LNaTCSR0_SD_LPBK_SEL			GENMASK(29, 28)
217 
218 #define LNaPSS(lane)				(0x1000 + (lane) * 0x4)
219 #define LNaPSS_TYPE				GENMASK(30, 24)
220 #define LNaPSS_TYPE_SGMII			(PROTO_SEL_SGMII_BASEX_KX << 2)
221 #define LNaPSS_TYPE_XFI				(PROTO_SEL_XFI_10GBASER_KR_SXGMII << 2)
222 #define LNaPSS_TYPE_40G				((PROTO_SEL_XFI_10GBASER_KR_SXGMII << 2) | 3)
223 #define LNaPSS_TYPE_25G				(PROTO_SEL_25G_50G_100G << 2)
224 #define LNaPSS_TYPE_100G			((PROTO_SEL_25G_50G_100G << 2) | 2)
225 
226 /* MDEV_PORT is at the same bitfield address for all protocol converters */
227 #define MDEV_PORT				GENMASK(31, 27)
228 
229 #define SGMIIaCR0(lane)				(0x1800 + (lane) * 0x10)
230 #define SGMIIaCR1(lane)				(0x1804 + (lane) * 0x10)
231 #define SGMIIaCR1_SGPCS_EN			BIT(11)
232 
233 #define ANLTaCR0(lane)				(0x1a00 + (lane) * 0x10)
234 #define ANLTaCR1(lane)				(0x1a04 + (lane) * 0x10)
235 
236 #define SXGMIIaCR0(lane)			(0x1a80 + (lane) * 0x10)
237 #define SXGMIIaCR0_RST				BIT(31)
238 #define SXGMIIaCR0_PD				BIT(30)
239 
240 #define SXGMIIaCR1(lane)			(0x1a84 + (lane) * 0x10)
241 
242 #define E25GaCR0(lane)				(0x1b00 + (lane) * 0x10)
243 #define E25GaCR0_RST				BIT(31)
244 #define E25GaCR0_PD				BIT(30)
245 
246 #define E25GaCR1(lane)				(0x1b04 + (lane) * 0x10)
247 
248 #define E25GaCR2(lane)				(0x1b08 + (lane) * 0x10)
249 #define E25GaCR2_FEC_ENA			BIT(23)
250 #define E25GaCR2_FEC_ERR_ENA			BIT(22)
251 #define E25GaCR2_FEC91_ENA			BIT(20)
252 
253 #define E40GaCR0(pcvt)				(0x1b40 + (pcvt) * 0x20)
254 #define E40GaCR1(pcvt)				(0x1b44 + (pcvt) * 0x20)
255 
256 #define E50GaCR1(pcvt)				(0x1b84 + (pcvt) * 0x10)
257 
258 #define E100GaCR1(pcvt)				(0x1c04 + (pcvt) * 0x20)
259 
260 #define CR(x)					((x) * 4)
261 
262 #define LYNX_28G_LANE_HALT_SLEEP_US		100
263 #define LYNX_28G_LANE_HALT_TIMEOUT_US		1000000
264 
265 #define LYNX_28G_LANE_RESET_SLEEP_US		100
266 #define LYNX_28G_LANE_RESET_TIMEOUT_US		1000000
267 
268 #define LYNX_28G_LANE_STOP_SLEEP_US		100
269 #define LYNX_28G_LANE_STOP_TIMEOUT_US		1000000
270 
271 #define lynx_28g_lane_rmw			lynx_lane_rmw
272 #define lynx_28g_lane_read			lynx_lane_read
273 #define lynx_28g_lane_write			lynx_lane_write
274 
275 #define lynx_28g_priv				lynx_priv
276 #define lynx_28g_lane				lynx_lane
277 #define lynx_28g_pll				lynx_pll
278 
279 enum lynx_28g_eq_type {
280 	EQ_TYPE_NO_EQ = 0,
281 	EQ_TYPE_2TAP = 1,
282 	EQ_TYPE_3TAP = 2,
283 };
284 
285 enum lynx_28g_proto_sel {
286 	PROTO_SEL_PCIE = 0,
287 	PROTO_SEL_SGMII_BASEX_KX = 1,
288 	PROTO_SEL_SATA = 2,
289 	PROTO_SEL_XAUI = 4,
290 	PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa,
291 	PROTO_SEL_25G_50G_100G = 0x1a,
292 };
293 
294 struct lynx_28g_proto_conf {
295 	/* LNaGCR0 */
296 	int proto_sel;
297 	int if_width;
298 	/* LNaTECR0 */
299 	int teq_type;
300 	int sgn_preq;
301 	int ratio_preq;
302 	int sgn_post1q;
303 	int ratio_post1q;
304 	int amp_red;
305 	/* LNaTECR1 */
306 	int adpt_eq;
307 	/* LNaRGCR1 */
308 	int enter_idle_flt_sel;
309 	int exit_idle_flt_sel;
310 	int data_lost_th_sel;
311 	/* LNaRECR0 */
312 	int gk2ovd;
313 	int gk3ovd;
314 	int gk4ovd;
315 	int gk2ovd_en;
316 	int gk3ovd_en;
317 	int gk4ovd_en;
318 	/* LNaRECR1 ? */
319 	int eq_offset_ovd;
320 	int eq_offset_ovd_en;
321 	/* LNaRECR2 */
322 	int eq_offset_rng_dbl;
323 	int eq_blw_sel;
324 	int eq_boost;
325 	int spare_in;
326 	/* LNaRSCCR0 */
327 	int smp_autoz_d1r;
328 	int smp_autoz_eg1r;
329 	/* LNaRCCR0 */
330 	int rccr0;
331 	/* LNaTTLCR0 */
332 	int ttlcr0;
333 };
334 
335 static const struct lynx_28g_proto_conf lynx_28g_proto_conf[LANE_MODE_MAX] = {
336 	[LANE_MODE_1000BASEX_SGMII] = {
337 		.proto_sel = LNaGCR0_PROTO_SEL_SGMII,
338 		.if_width = LNaGCR0_IF_WIDTH_10_BIT,
339 		.teq_type = EQ_TYPE_NO_EQ,
340 		.sgn_preq = 1,
341 		.ratio_preq = 0,
342 		.sgn_post1q = 1,
343 		.ratio_post1q = 0,
344 		.amp_red = 6,
345 		.adpt_eq = 48,
346 		.enter_idle_flt_sel = 4,
347 		.exit_idle_flt_sel = 3,
348 		.data_lost_th_sel = 1,
349 		.gk2ovd = 0x1f,
350 		.gk3ovd = 0,
351 		.gk4ovd = 0,
352 		.gk2ovd_en = 1,
353 		.gk3ovd_en = 1,
354 		.gk4ovd_en = 0,
355 		.eq_offset_ovd = 0x1f,
356 		.eq_offset_ovd_en = 0,
357 		.eq_offset_rng_dbl = 0,
358 		.eq_blw_sel = 0,
359 		.eq_boost = 0,
360 		.spare_in = 0,
361 		.smp_autoz_d1r = 0,
362 		.smp_autoz_eg1r = 0,
363 		.rccr0 = LNaRCCR0_CAL_EN,
364 		.ttlcr0 = LNaTTLCR0_TTL_SLO_PM_BYP |
365 			  LNaTTLCR0_DATA_IN_SSC,
366 	},
367 	[LANE_MODE_USXGMII] = {
368 		.proto_sel = LNaGCR0_PROTO_SEL_XFI,
369 		.if_width = LNaGCR0_IF_WIDTH_20_BIT,
370 		.teq_type = EQ_TYPE_2TAP,
371 		.sgn_preq = 1,
372 		.ratio_preq = 0,
373 		.sgn_post1q = 1,
374 		.ratio_post1q = 3,
375 		.amp_red = 7,
376 		.adpt_eq = 48,
377 		.enter_idle_flt_sel = 0,
378 		.exit_idle_flt_sel = 0,
379 		.data_lost_th_sel = 0,
380 		.gk2ovd = 0,
381 		.gk3ovd = 0,
382 		.gk4ovd = 0,
383 		.gk2ovd_en = 0,
384 		.gk3ovd_en = 0,
385 		.gk4ovd_en = 0,
386 		.eq_offset_ovd = 0x1f,
387 		.eq_offset_ovd_en = 0,
388 		.eq_offset_rng_dbl = 1,
389 		.eq_blw_sel = 1,
390 		.eq_boost = 0,
391 		.spare_in = 0,
392 		.smp_autoz_d1r = 2,
393 		.smp_autoz_eg1r = 0,
394 		.rccr0 = LNaRCCR0_CAL_EN,
395 		.ttlcr0 = LNaTTLCR0_TTL_SLO_PM_BYP |
396 			  LNaTTLCR0_DATA_IN_SSC,
397 	},
398 	[LANE_MODE_10GBASER] = {
399 		.proto_sel = LNaGCR0_PROTO_SEL_XFI,
400 		.if_width = LNaGCR0_IF_WIDTH_20_BIT,
401 		.teq_type = EQ_TYPE_2TAP,
402 		.sgn_preq = 1,
403 		.ratio_preq = 0,
404 		.sgn_post1q = 1,
405 		.ratio_post1q = 3,
406 		.amp_red = 7,
407 		.adpt_eq = 48,
408 		.enter_idle_flt_sel = 0,
409 		.exit_idle_flt_sel = 0,
410 		.data_lost_th_sel = 0,
411 		.gk2ovd = 0,
412 		.gk3ovd = 0,
413 		.gk4ovd = 0,
414 		.gk2ovd_en = 0,
415 		.gk3ovd_en = 0,
416 		.gk4ovd_en = 0,
417 		.eq_offset_ovd = 0x1f,
418 		.eq_offset_ovd_en = 0,
419 		.eq_offset_rng_dbl = 1,
420 		.eq_blw_sel = 1,
421 		.eq_boost = 0,
422 		.spare_in = 0,
423 		.smp_autoz_d1r = 2,
424 		.smp_autoz_eg1r = 0,
425 		.rccr0 = LNaRCCR0_CAL_EN,
426 		.ttlcr0 = LNaTTLCR0_TTL_SLO_PM_BYP |
427 			  LNaTTLCR0_DATA_IN_SSC,
428 	},
429 	[LANE_MODE_25GBASER] = {
430 		.proto_sel = LNaGCR0_PROTO_SEL_25G,
431 		.if_width = LNaGCR0_IF_WIDTH_40_BIT,
432 		.teq_type = EQ_TYPE_3TAP,
433 		.sgn_preq = 1,
434 		.ratio_preq = 2,
435 		.sgn_post1q = 1,
436 		.ratio_post1q = 7,
437 		.amp_red = 0,
438 		.adpt_eq = 48,
439 		.enter_idle_flt_sel = 0,
440 		.exit_idle_flt_sel = 0,
441 		.data_lost_th_sel = 0,
442 		.gk2ovd = 0,
443 		.gk3ovd = 0,
444 		.gk4ovd = 5,
445 		.gk2ovd_en = 0,
446 		.gk3ovd_en = 0,
447 		.gk4ovd_en = 1,
448 		.eq_offset_ovd = 0x1f,
449 		.eq_offset_ovd_en = 0,
450 		.eq_offset_rng_dbl = 1,
451 		.eq_blw_sel = 1,
452 		.eq_boost = 2,
453 		.spare_in = 3,
454 		.smp_autoz_d1r = 2,
455 		.smp_autoz_eg1r = 2,
456 		.rccr0 = LNaRCCR0_CAL_EN |
457 			 LNaRCCR0_CAL_DC3_DIS |
458 			 LNaRCCR0_CAL_DC2_DIS |
459 			 LNaRCCR0_CAL_DC1_DIS |
460 			 LNaRCCR0_CAL_DC0_DIS,
461 		.ttlcr0 = LNaTTLCR0_DATA_IN_SSC |
462 			  FIELD_PREP_CONST(LNaTTLCR0_CDR_MIN_SMP_ON, 1),
463 	},
464 };
465 
466 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
467 				    struct lynx_28g_pll *pll,
468 				    enum lynx_lane_mode lane_mode)
469 {
470 	switch (pll->frate_sel) {
471 	case PLLnCR1_FRATE_5G_10GVCO:
472 	case PLLnCR1_FRATE_5G_25GVCO:
473 		switch (lane_mode) {
474 		case LANE_MODE_1000BASEX_SGMII:
475 			lynx_28g_lane_rmw(lane, LNaTGCR0,
476 					  FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_QUARTER),
477 					  LNaTGCR0_N_RATE);
478 			lynx_28g_lane_rmw(lane, LNaRGCR0,
479 					  FIELD_PREP(LNaRGCR0_N_RATE, LNaRGCR0_N_RATE_QUARTER),
480 					  LNaRGCR0_N_RATE);
481 			break;
482 		default:
483 			break;
484 		}
485 		break;
486 	case PLLnCR1_FRATE_10G_20GVCO:
487 		switch (lane_mode) {
488 		case LANE_MODE_10GBASER:
489 		case LANE_MODE_USXGMII:
490 			lynx_28g_lane_rmw(lane, LNaTGCR0,
491 					  FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_FULL),
492 					  LNaTGCR0_N_RATE);
493 			lynx_28g_lane_rmw(lane, LNaRGCR0,
494 					  FIELD_PREP(LNaRGCR0_N_RATE, LNaRGCR0_N_RATE_FULL),
495 					  LNaRGCR0_N_RATE);
496 			break;
497 		default:
498 			break;
499 		}
500 		break;
501 	case PLLnCR1_FRATE_12G_25GVCO:
502 		switch (lane_mode) {
503 		case LANE_MODE_25GBASER:
504 			lynx_28g_lane_rmw(lane, LNaTGCR0,
505 					  FIELD_PREP(LNaTGCR0_N_RATE, LNaTGCR0_N_RATE_DOUBLE),
506 					  LNaTGCR0_N_RATE);
507 			lynx_28g_lane_rmw(lane, LNaRGCR0,
508 					  FIELD_PREP(LNaRGCR0_N_RATE, LNaRGCR0_N_RATE_DOUBLE),
509 					  LNaRGCR0_N_RATE);
510 			break;
511 		default:
512 			break;
513 		}
514 		break;
515 	default:
516 		break;
517 	}
518 }
519 
520 static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane,
521 				  struct lynx_28g_pll *pll)
522 {
523 	if (pll->id == 0) {
524 		lynx_28g_lane_rmw(lane, LNaTGCR0,
525 				  FIELD_PREP(LNaTGCR0_USE_PLL, LNaTGCR0_USE_PLLF),
526 				  LNaTGCR0_USE_PLL);
527 		lynx_28g_lane_rmw(lane, LNaRGCR0,
528 				  FIELD_PREP(LNaRGCR0_USE_PLL, LNaRGCR0_USE_PLLF),
529 				  LNaRGCR0_USE_PLL);
530 	} else {
531 		lynx_28g_lane_rmw(lane, LNaTGCR0,
532 				  FIELD_PREP(LNaTGCR0_USE_PLL, LNaTGCR0_USE_PLLS),
533 				  LNaTGCR0_USE_PLL);
534 		lynx_28g_lane_rmw(lane, LNaRGCR0,
535 				  FIELD_PREP(LNaRGCR0_USE_PLL, LNaRGCR0_USE_PLLS),
536 				  LNaRGCR0_USE_PLL);
537 	}
538 }
539 
540 static bool lynx_28g_lane_halt_done(struct lynx_28g_lane *lane)
541 {
542 	u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
543 	u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
544 
545 	return !(trstctl & LNaTRSTCTL_HLT_REQ) &&
546 	       !(rrstctl & LNaRRSTCTL_HLT_REQ);
547 }
548 
549 static bool lynx_28g_lane_stop_done(struct lynx_28g_lane *lane)
550 {
551 	u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
552 	u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
553 
554 	return !(trstctl & LNaTRSTCTL_STP_REQ) &&
555 	       !(rrstctl & LNaRRSTCTL_STP_REQ);
556 }
557 
558 static bool lynx_28g_lane_reset_done(struct lynx_28g_lane *lane)
559 {
560 	u32 trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
561 	u32 rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
562 
563 	return (trstctl & LNaTRSTCTL_RST_DONE) &&
564 	       (rrstctl & LNaRRSTCTL_RST_DONE);
565 }
566 
567 /* Halting puts the lane in a mode in which it can be reconfigured */
568 static int lynx_28g_lane_halt(struct phy *phy)
569 {
570 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
571 	bool done;
572 	int err;
573 
574 	/* Issue a halt request */
575 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_HLT_REQ,
576 			  LNaTRSTCTL_HLT_REQ);
577 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_HLT_REQ,
578 			  LNaRRSTCTL_HLT_REQ);
579 
580 	/* Wait until the halting process is complete */
581 	err = read_poll_timeout(lynx_28g_lane_halt_done, done, done,
582 				LYNX_28G_LANE_HALT_SLEEP_US,
583 				LYNX_28G_LANE_HALT_TIMEOUT_US,
584 				false, lane);
585 	if (err) {
586 		dev_err(&phy->dev, "Lane %c halt failed: %pe\n",
587 			'A' + lane->id, ERR_PTR(err));
588 	}
589 
590 	return err;
591 }
592 
593 static int lynx_28g_lane_reset(struct phy *phy)
594 {
595 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
596 	bool done;
597 	int err;
598 
599 	/* Issue a reset request on the lane */
600 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_RST_REQ,
601 			  LNaTRSTCTL_RST_REQ);
602 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ,
603 			  LNaRRSTCTL_RST_REQ);
604 
605 	/* Wait until the reset sequence is completed */
606 	err = read_poll_timeout(lynx_28g_lane_reset_done, done, done,
607 				LYNX_28G_LANE_RESET_SLEEP_US,
608 				LYNX_28G_LANE_RESET_TIMEOUT_US,
609 				false, lane);
610 	if (err) {
611 		dev_err(&phy->dev, "Lane %c reset failed: %pe\n",
612 			'A' + lane->id, ERR_PTR(err));
613 	}
614 
615 	return err;
616 }
617 
618 static int lynx_28g_power_off(struct phy *phy)
619 {
620 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
621 	bool done;
622 	int err;
623 
624 	if (!lane->powered_up)
625 		return 0;
626 
627 	/* Issue a stop request */
628 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_STP_REQ,
629 			  LNaTRSTCTL_STP_REQ);
630 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_STP_REQ,
631 			  LNaRRSTCTL_STP_REQ);
632 
633 	/* Wait until the stop process is complete */
634 	err = read_poll_timeout(lynx_28g_lane_stop_done, done, done,
635 				LYNX_28G_LANE_STOP_SLEEP_US,
636 				LYNX_28G_LANE_STOP_TIMEOUT_US,
637 				false, lane);
638 	if (err) {
639 		dev_err(&phy->dev, "Lane %c stop failed: %pe\n",
640 			'A' + lane->id, ERR_PTR(err));
641 	}
642 
643 	/* Power down the RX and TX portions of the lane */
644 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_DIS,
645 			  LNaRRSTCTL_DIS);
646 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, LNaTRSTCTL_DIS,
647 			  LNaTRSTCTL_DIS);
648 
649 	lane->powered_up = false;
650 
651 	return 0;
652 }
653 
654 static int lynx_28g_power_on(struct phy *phy)
655 {
656 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
657 	int err;
658 
659 	if (lane->powered_up)
660 		return 0;
661 
662 	/* Power up the RX and TX portions of the lane */
663 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, 0, LNaRRSTCTL_DIS);
664 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, 0, LNaTRSTCTL_DIS);
665 
666 	err = lynx_28g_lane_reset(phy);
667 	if (err)
668 		return err;
669 
670 	lane->powered_up = true;
671 
672 	return 0;
673 }
674 
675 static int lynx_28g_e25g_pcvt(int lane)
676 {
677 	return 7 - lane;
678 }
679 
680 static int lynx_28g_get_pccr(enum lynx_lane_mode lane_mode, int lane,
681 			     struct lynx_pccr *pccr)
682 {
683 	switch (lane_mode) {
684 	case LANE_MODE_1000BASEX_SGMII:
685 		pccr->offset = PCC8;
686 		pccr->width = 4;
687 		pccr->shift = SGMII_CFG(lane);
688 		break;
689 	case LANE_MODE_USXGMII:
690 	case LANE_MODE_10GBASER:
691 		pccr->offset = PCCC;
692 		pccr->width = 4;
693 		pccr->shift = SXGMII_CFG(lane);
694 		break;
695 	case LANE_MODE_25GBASER:
696 		pccr->offset = PCCD;
697 		pccr->width = 4;
698 		pccr->shift = E25G_CFG(lynx_28g_e25g_pcvt(lane));
699 		break;
700 	default:
701 		return -EOPNOTSUPP;
702 	}
703 
704 	return 0;
705 }
706 
707 static int lynx_28g_get_pcvt_offset(int lane, enum lynx_lane_mode lane_mode)
708 {
709 	switch (lane_mode) {
710 	case LANE_MODE_1000BASEX_SGMII:
711 		return SGMIIaCR0(lane);
712 	case LANE_MODE_USXGMII:
713 	case LANE_MODE_10GBASER:
714 		return SXGMIIaCR0(lane);
715 	case LANE_MODE_25GBASER:
716 		return E25GaCR0(lynx_28g_e25g_pcvt(lane));
717 	default:
718 		return -EOPNOTSUPP;
719 	}
720 }
721 
722 static bool lx2160a_serdes1_lane_supports_mode(int lane,
723 					       enum lynx_lane_mode mode)
724 {
725 	switch (mode) {
726 	case LANE_MODE_25GBASER:
727 		return lane != 2 && lane != 3;
728 	default:
729 		return true;
730 	}
731 }
732 
733 static bool lx2160a_serdes2_lane_supports_mode(int lane,
734 					       enum lynx_lane_mode mode)
735 {
736 	switch (mode) {
737 	case LANE_MODE_1000BASEX_SGMII:
738 		return true;
739 	case LANE_MODE_USXGMII:
740 	case LANE_MODE_10GBASER:
741 		return lane == 6 || lane == 7;
742 	default:
743 		return false;
744 	}
745 }
746 
747 static bool lx2160a_serdes3_lane_supports_mode(int lane,
748 					       enum lynx_lane_mode mode)
749 {
750 	/*
751 	 * Non-networking SerDes, and this driver supports only
752 	 * networking protocols
753 	 */
754 	return false;
755 }
756 
757 static bool lx2162a_serdes1_lane_supports_mode(int lane,
758 					       enum lynx_lane_mode mode)
759 {
760 	return true;
761 }
762 
763 static bool lx2162a_serdes2_lane_supports_mode(int lane,
764 					       enum lynx_lane_mode mode)
765 {
766 	return lx2160a_serdes2_lane_supports_mode(lane, mode);
767 }
768 
769 /* Feature set is not expected to grow for the deprecated compatible string */
770 static bool lynx_28g_compat_lane_supports_mode(int lane,
771 					       enum lynx_lane_mode mode)
772 {
773 	switch (mode) {
774 	case LANE_MODE_1000BASEX_SGMII:
775 	case LANE_MODE_USXGMII:
776 	case LANE_MODE_10GBASER:
777 		return true;
778 	default:
779 		return false;
780 	}
781 }
782 
783 static void lynx_28g_cdr_lock_check(struct lynx_lane *lane)
784 {
785 	u32 rrstctl;
786 	int err;
787 
788 	rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
789 	if (!!(rrstctl & LNaRRSTCTL_CDR_LOCK))
790 		return;
791 
792 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, LNaRRSTCTL_RST_REQ,
793 			  LNaRRSTCTL_RST_REQ);
794 
795 	err = read_poll_timeout(lynx_28g_lane_read, rrstctl,
796 				!!(rrstctl & LNaRRSTCTL_RST_DONE),
797 				LYNX_28G_LANE_RESET_SLEEP_US,
798 				LYNX_28G_LANE_RESET_TIMEOUT_US,
799 				false, lane, LNaRRSTCTL);
800 	if (err) {
801 		dev_warn_once(&lane->phy->dev,
802 			      "Lane %c receiver reset failed: %pe\n",
803 			      'A' + lane->id, ERR_PTR(err));
804 	}
805 }
806 
807 static void lynx_28g_lane_remap_pll(struct lynx_lane *lane,
808 				    enum lynx_lane_mode lane_mode)
809 {
810 	struct lynx_priv *priv = lane->priv;
811 	struct lynx_pll *pll;
812 
813 	/* Switch to the PLL that works with this interface type */
814 	pll = lynx_pll_get(priv, lane_mode);
815 	if (unlikely(!pll))
816 		return;
817 
818 	lynx_28g_lane_set_pll(lane, pll);
819 
820 	/* Choose the portion of clock net to be used on this lane */
821 	lynx_28g_lane_set_nrate(lane, pll, lane_mode);
822 }
823 
824 static void lynx_28g_lane_change_proto_conf(struct lynx_28g_lane *lane,
825 					    enum lynx_lane_mode lane_mode)
826 {
827 	const struct lynx_28g_proto_conf *conf = &lynx_28g_proto_conf[lane_mode];
828 
829 	lynx_28g_lane_rmw(lane, LNaGCR0,
830 			  FIELD_PREP(LNaGCR0_PROTO_SEL, conf->proto_sel) |
831 			  FIELD_PREP(LNaGCR0_IF_WIDTH, conf->if_width),
832 			  LNaGCR0_PROTO_SEL | LNaGCR0_IF_WIDTH);
833 
834 	lynx_28g_lane_rmw(lane, LNaTECR0,
835 			  FIELD_PREP(LNaTECR0_EQ_TYPE, conf->teq_type) |
836 			  FIELD_PREP(LNaTECR0_EQ_SGN_PREQ, conf->sgn_preq) |
837 			  FIELD_PREP(LNaTECR0_EQ_PREQ, conf->ratio_preq) |
838 			  FIELD_PREP(LNaTECR0_EQ_SGN_POST1Q, conf->sgn_post1q) |
839 			  FIELD_PREP(LNaTECR0_EQ_POST1Q, conf->ratio_post1q) |
840 			  FIELD_PREP(LNaTECR0_EQ_AMP_RED, conf->amp_red),
841 			  LNaTECR0_EQ_TYPE |
842 			  LNaTECR0_EQ_SGN_PREQ |
843 			  LNaTECR0_EQ_PREQ |
844 			  LNaTECR0_EQ_SGN_POST1Q |
845 			  LNaTECR0_EQ_POST1Q |
846 			  LNaTECR0_EQ_AMP_RED);
847 
848 	lynx_28g_lane_rmw(lane, LNaTECR1,
849 			  FIELD_PREP(LNaTECR1_EQ_ADPT_EQ, conf->adpt_eq),
850 			  LNaTECR1_EQ_ADPT_EQ);
851 
852 	lynx_28g_lane_rmw(lane, LNaRGCR1,
853 			  FIELD_PREP(LNaRGCR1_ENTER_IDLE_FLT_SEL, conf->enter_idle_flt_sel) |
854 			  FIELD_PREP(LNaRGCR1_EXIT_IDLE_FLT_SEL, conf->exit_idle_flt_sel) |
855 			  FIELD_PREP(LNaRGCR1_DATA_LOST_TH_SEL, conf->data_lost_th_sel),
856 			  LNaRGCR1_ENTER_IDLE_FLT_SEL |
857 			  LNaRGCR1_EXIT_IDLE_FLT_SEL |
858 			  LNaRGCR1_DATA_LOST_TH_SEL);
859 
860 	lynx_28g_lane_rmw(lane, LNaRECR0,
861 			  FIELD_PREP(LNaRECR0_EQ_GAINK2_HF_OV_EN, conf->gk2ovd_en) |
862 			  FIELD_PREP(LNaRECR0_EQ_GAINK3_MF_OV_EN, conf->gk3ovd_en) |
863 			  FIELD_PREP(LNaRECR0_EQ_GAINK4_LF_OV_EN, conf->gk4ovd_en) |
864 			  FIELD_PREP(LNaRECR0_EQ_GAINK2_HF_OV, conf->gk2ovd) |
865 			  FIELD_PREP(LNaRECR0_EQ_GAINK3_MF_OV, conf->gk3ovd) |
866 			  FIELD_PREP(LNaRECR0_EQ_GAINK4_LF_OV, conf->gk4ovd),
867 			  LNaRECR0_EQ_GAINK2_HF_OV |
868 			  LNaRECR0_EQ_GAINK3_MF_OV |
869 			  LNaRECR0_EQ_GAINK4_LF_OV |
870 			  LNaRECR0_EQ_GAINK2_HF_OV_EN |
871 			  LNaRECR0_EQ_GAINK3_MF_OV_EN |
872 			  LNaRECR0_EQ_GAINK4_LF_OV_EN);
873 
874 	lynx_28g_lane_rmw(lane, LNaRECR1,
875 			  FIELD_PREP(LNaRECR1_EQ_OFFSET_OV, conf->eq_offset_ovd) |
876 			  FIELD_PREP(LNaRECR1_EQ_OFFSET_OV_EN, conf->eq_offset_ovd_en),
877 			  LNaRECR1_EQ_OFFSET_OV |
878 			  LNaRECR1_EQ_OFFSET_OV_EN);
879 
880 	lynx_28g_lane_rmw(lane, LNaRECR2,
881 			  FIELD_PREP(LNaRECR2_EQ_OFFSET_RNG_DBL, conf->eq_offset_rng_dbl) |
882 			  FIELD_PREP(LNaRECR2_EQ_BLW_SEL, conf->eq_blw_sel) |
883 			  FIELD_PREP(LNaRECR2_EQ_BOOST, conf->eq_boost) |
884 			  FIELD_PREP(LNaRECR2_SPARE_IN, conf->spare_in),
885 			  LNaRECR2_EQ_OFFSET_RNG_DBL |
886 			  LNaRECR2_EQ_BLW_SEL |
887 			  LNaRECR2_EQ_BOOST |
888 			  LNaRECR2_SPARE_IN);
889 
890 	lynx_28g_lane_rmw(lane, LNaRSCCR0,
891 			  FIELD_PREP(LNaRSCCR0_SMP_AUTOZ_D1R, conf->smp_autoz_d1r) |
892 			  FIELD_PREP(LNaRSCCR0_SMP_AUTOZ_EG1R, conf->smp_autoz_eg1r),
893 			  LNaRSCCR0_SMP_AUTOZ_D1R |
894 			  LNaRSCCR0_SMP_AUTOZ_EG1R);
895 
896 	lynx_28g_lane_write(lane, LNaRCCR0, conf->rccr0);
897 	lynx_28g_lane_write(lane, LNaTTLCR0, conf->ttlcr0);
898 }
899 
900 static int lynx_28g_lane_disable_pcvt(struct lynx_28g_lane *lane,
901 				      enum lynx_lane_mode lane_mode)
902 {
903 	struct lynx_28g_priv *priv = lane->priv;
904 	int err;
905 
906 	spin_lock(&priv->pcc_lock);
907 
908 	err = lynx_pccr_write(lane, lane_mode, 0);
909 	if (err)
910 		goto out;
911 
912 	switch (lane_mode) {
913 	case LANE_MODE_1000BASEX_SGMII:
914 		err = lynx_pcvt_rmw(lane, lane_mode, CR(1), 0,
915 				    SGMIIaCR1_SGPCS_EN);
916 		break;
917 	default:
918 		err = 0;
919 	}
920 
921 out:
922 	spin_unlock(&priv->pcc_lock);
923 
924 	return err;
925 }
926 
927 static int lynx_28g_lane_enable_pcvt(struct lynx_28g_lane *lane,
928 				     enum lynx_lane_mode lane_mode)
929 {
930 	struct lynx_28g_priv *priv = lane->priv;
931 	u32 val;
932 	int err;
933 
934 	spin_lock(&priv->pcc_lock);
935 
936 	switch (lane_mode) {
937 	case LANE_MODE_1000BASEX_SGMII:
938 		err = lynx_pcvt_rmw(lane, lane_mode, CR(1), SGMIIaCR1_SGPCS_EN,
939 				    SGMIIaCR1_SGPCS_EN);
940 		break;
941 	default:
942 		err = 0;
943 	}
944 
945 	val = 0;
946 
947 	switch (lane_mode) {
948 	case LANE_MODE_1000BASEX_SGMII:
949 		val |= PCC8_SGMIIa_CFG;
950 		break;
951 	case LANE_MODE_10GBASER:
952 		val |= PCCC_SXGMIIn_XFI;
953 		fallthrough;
954 	case LANE_MODE_USXGMII:
955 		val |= PCCC_SXGMIIn_CFG;
956 		break;
957 	case LANE_MODE_25GBASER:
958 		val |= PCCD_E25Gn_CFG;
959 		break;
960 	default:
961 		break;
962 	}
963 
964 	err = lynx_pccr_write(lane, lane_mode, val);
965 
966 	spin_unlock(&priv->pcc_lock);
967 
968 	return err;
969 }
970 
971 static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
972 			     union phy_configure_opts *opts)
973 {
974 	return lynx_phy_mode_to_lane_mode(phy, mode, submode, NULL);
975 }
976 
977 static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
978 {
979 	struct lynx_lane *lane = phy_get_drvdata(phy);
980 	int powered_up = lane->powered_up;
981 	enum lynx_lane_mode lane_mode;
982 	int err;
983 
984 	err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
985 	if (err)
986 		return err;
987 
988 	if (lane_mode == lane->mode)
989 		return 0;
990 
991 	/* If the lane is powered up, put the lane into the halt state while
992 	 * the reconfiguration is being done.
993 	 */
994 	if (powered_up) {
995 		err = lynx_28g_lane_halt(phy);
996 		if (err)
997 			goto out;
998 	}
999 
1000 	err = lynx_28g_lane_disable_pcvt(lane, lane->mode);
1001 	if (err)
1002 		goto out;
1003 
1004 	lynx_28g_lane_change_proto_conf(lane, lane_mode);
1005 	lynx_28g_lane_remap_pll(lane, lane_mode);
1006 	WARN_ON(lynx_28g_lane_enable_pcvt(lane, lane_mode));
1007 
1008 	lane->mode = lane_mode;
1009 
1010 out:
1011 	if (powered_up)
1012 		lynx_28g_lane_reset(phy);
1013 
1014 	return err;
1015 }
1016 
1017 static int lynx_28g_init(struct phy *phy)
1018 {
1019 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
1020 
1021 	/* Mark the fact that the lane was init */
1022 	lane->init = true;
1023 
1024 	/* SerDes lanes are powered on at boot time.  Any lane that is managed
1025 	 * by this driver will get powered down at init time aka at dpaa2-eth
1026 	 * probe time.
1027 	 */
1028 	lane->powered_up = true;
1029 	lynx_28g_power_off(phy);
1030 
1031 	return 0;
1032 }
1033 
1034 static int lynx_28g_exit(struct phy *phy)
1035 {
1036 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
1037 
1038 	/* The lane returns to the state where it isn't managed by the
1039 	 * consumer, so we must treat is as if it isn't initialized, and
1040 	 * always powered on.
1041 	 */
1042 	lane->init = false;
1043 	lane->powered_up = false;
1044 
1045 	lynx_28g_power_on(phy);
1046 
1047 	return 0;
1048 }
1049 
1050 static const struct phy_ops lynx_28g_ops = {
1051 	.init		= lynx_28g_init,
1052 	.exit		= lynx_28g_exit,
1053 	.power_on	= lynx_28g_power_on,
1054 	.power_off	= lynx_28g_power_off,
1055 	.set_mode	= lynx_28g_set_mode,
1056 	.validate	= lynx_28g_validate,
1057 	.owner		= THIS_MODULE,
1058 };
1059 
1060 static void lynx_28g_pll_read_configuration(struct lynx_pll *pll)
1061 {
1062 	u32 val;
1063 
1064 	val = lynx_pll_read(pll, PLLnRSTCTL);
1065 	pll->enabled = !(val & PLLnRSTCTL_DIS);
1066 	pll->locked = !!(val & PLLnRSTCTL_LOCK);
1067 
1068 	val = lynx_pll_read(pll, PLLnCR0);
1069 	pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val);
1070 
1071 	val = lynx_pll_read(pll, PLLnCR1);
1072 	pll->frate_sel = FIELD_GET(PLLnCR1_FRATE_SEL, val);
1073 
1074 	if (!pll->enabled)
1075 		return;
1076 
1077 	switch (pll->frate_sel) {
1078 	case PLLnCR1_FRATE_5G_10GVCO:
1079 	case PLLnCR1_FRATE_5G_25GVCO:
1080 		/* 5GHz clock net */
1081 		__set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
1082 		break;
1083 	case PLLnCR1_FRATE_10G_20GVCO:
1084 		/* 10.3125GHz clock net */
1085 		__set_bit(LANE_MODE_10GBASER, pll->supported);
1086 		__set_bit(LANE_MODE_USXGMII, pll->supported);
1087 		break;
1088 	case PLLnCR1_FRATE_12G_25GVCO:
1089 		/* 12.890625GHz clock net */
1090 		__set_bit(LANE_MODE_25GBASER, pll->supported);
1091 		break;
1092 	default:
1093 		/* 6GHz, 8GHz */
1094 		break;
1095 	}
1096 }
1097 
1098 static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
1099 {
1100 	u32 pccr, pss, protocol;
1101 
1102 	pss = lynx_28g_lane_read(lane, LNaPSS);
1103 	protocol = FIELD_GET(LNaPSS_TYPE, pss);
1104 	switch (protocol) {
1105 	case LNaPSS_TYPE_SGMII:
1106 		lane->mode = LANE_MODE_1000BASEX_SGMII;
1107 		break;
1108 	case LNaPSS_TYPE_XFI:
1109 		lynx_pccr_read(lane, LANE_MODE_10GBASER, &pccr);
1110 		if (pccr & PCCC_SXGMIIn_XFI)
1111 			lane->mode = LANE_MODE_10GBASER;
1112 		else
1113 			lane->mode = LANE_MODE_USXGMII;
1114 		break;
1115 	case LNaPSS_TYPE_25G:
1116 		lane->mode = LANE_MODE_25GBASER;
1117 		break;
1118 	default:
1119 		lane->mode = LANE_MODE_UNKNOWN;
1120 	}
1121 }
1122 
1123 static const struct lynx_info lynx_info_compat = {
1124 	.get_pccr = lynx_28g_get_pccr,
1125 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1126 	.lane_supports_mode = lynx_28g_compat_lane_supports_mode,
1127 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1128 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1129 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1130 	.num_lanes = LYNX_28G_NUM_LANE,
1131 };
1132 
1133 static const struct lynx_info lynx_info_lx2160a_serdes1 = {
1134 	.get_pccr = lynx_28g_get_pccr,
1135 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1136 	.lane_supports_mode = lx2160a_serdes1_lane_supports_mode,
1137 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1138 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1139 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1140 	.num_lanes = LYNX_28G_NUM_LANE,
1141 };
1142 
1143 static const struct lynx_info lynx_info_lx2160a_serdes2 = {
1144 	.get_pccr = lynx_28g_get_pccr,
1145 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1146 	.lane_supports_mode = lx2160a_serdes2_lane_supports_mode,
1147 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1148 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1149 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1150 	.num_lanes = LYNX_28G_NUM_LANE,
1151 };
1152 
1153 static const struct lynx_info lynx_info_lx2160a_serdes3 = {
1154 	.get_pccr = lynx_28g_get_pccr,
1155 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1156 	.lane_supports_mode = lx2160a_serdes3_lane_supports_mode,
1157 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1158 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1159 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1160 	.num_lanes = LYNX_28G_NUM_LANE,
1161 };
1162 
1163 static const struct lynx_info lynx_info_lx2162a_serdes1 = {
1164 	.get_pccr = lynx_28g_get_pccr,
1165 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1166 	.lane_supports_mode = lx2162a_serdes1_lane_supports_mode,
1167 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1168 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1169 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1170 	.first_lane = 4,
1171 	.num_lanes = LYNX_28G_NUM_LANE,
1172 };
1173 
1174 static const struct lynx_info lynx_info_lx2162a_serdes2 = {
1175 	.get_pccr = lynx_28g_get_pccr,
1176 	.get_pcvt_offset = lynx_28g_get_pcvt_offset,
1177 	.lane_supports_mode = lx2162a_serdes2_lane_supports_mode,
1178 	.pll_read_configuration = lynx_28g_pll_read_configuration,
1179 	.lane_read_configuration = lynx_28g_lane_read_configuration,
1180 	.cdr_lock_check = lynx_28g_cdr_lock_check,
1181 	.num_lanes = LYNX_28G_NUM_LANE,
1182 };
1183 
1184 static int lynx_28g_probe(struct platform_device *pdev)
1185 {
1186 	struct device *dev = &pdev->dev;
1187 	const struct lynx_info *info;
1188 
1189 	/*
1190 	 * If we get here it means we probed on a device tree where
1191 	 * "fsl,lynx-28g" wasn't the fallback, but the sole compatible string.
1192 	 */
1193 	info = of_device_get_match_data(dev);
1194 	if (info == &lynx_info_compat)
1195 		dev_warn(dev, "Please update device tree to use per-device compatible strings\n");
1196 
1197 	return lynx_probe(pdev, info, &lynx_28g_ops);
1198 }
1199 
1200 static const struct of_device_id lynx_28g_of_match_table[] = {
1201 	{ .compatible = "fsl,lx2160a-serdes1", .data = &lynx_info_lx2160a_serdes1 },
1202 	{ .compatible = "fsl,lx2160a-serdes2", .data = &lynx_info_lx2160a_serdes2 },
1203 	{ .compatible = "fsl,lx2160a-serdes3", .data = &lynx_info_lx2160a_serdes3 },
1204 	{ .compatible = "fsl,lx2162a-serdes1", .data = &lynx_info_lx2162a_serdes1 },
1205 	{ .compatible = "fsl,lx2162a-serdes2", .data = &lynx_info_lx2162a_serdes2 },
1206 	{ .compatible = "fsl,lynx-28g", .data = &lynx_info_compat }, /* fallback, keep last */
1207 	{ },
1208 };
1209 MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
1210 
1211 static struct platform_driver lynx_28g_driver = {
1212 	.probe = lynx_28g_probe,
1213 	.remove = lynx_remove,
1214 	.driver = {
1215 		.name = "lynx-28g",
1216 		.of_match_table = lynx_28g_of_match_table,
1217 	},
1218 };
1219 module_platform_driver(lynx_28g_driver);
1220 
1221 MODULE_IMPORT_NS("PHY_FSL_LYNX");
1222 MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
1223 MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");
1224 MODULE_LICENSE("GPL v2");
1225