xref: /linux/drivers/phy/freescale/phy-fsl-lynx-10g.c (revision 62cf248de32f061d99cf7cd1675419d739031c5e)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright 2021-2026 NXP */
3 
4 #include <linux/delay.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 /* SoC IP wrapper for protocol converters */
15 #define PCCR8				0x220
16 #define PCCR8_SGMIIa_KX			BIT(3)
17 #define PCCR8_SGMIIa_CFG		GENMASK(2, 0)
18 
19 #define PCCR9				0x224
20 #define PCCR9_QSGMIIa_CFG		GENMASK(2, 0)
21 #define PCCR9_QXGMIIa_CFG		GENMASK(2, 0)
22 
23 #define PCCRB				0x22c
24 #define PCCRB_XFIa_CFG			GENMASK(2, 0)
25 #define PCCRB_SXGMIIa_CFG		GENMASK(2, 0)
26 
27 #define SGMII_CFG(id)			(28 - (id) * 4)
28 #define QSGMII_CFG(id)			(28 - (id) * 4)
29 #define SXGMII_CFG(id)			(28 - (id) * 4)
30 #define QXGMII_CFG(id)			(12 - (id) * 4)
31 #define XFI_CFG(id)			(28 - (id) * 4)
32 
33 #define CR(x)				((x) * 4)
34 
35 #define A				0
36 #define B				1
37 #define C				2
38 #define D				3
39 #define E				4
40 #define F				5
41 #define G				6
42 #define H				7
43 
44 #define SGMIIaCR0(id)			(0x1800 + (id) * 0x10)
45 #define QSGMIIaCR0(id)			(0x1880 + (id) * 0x10)
46 #define XAUIaCR0(id)			(0x1900 + (id) * 0x10)
47 #define XFIaCR0(id)			(0x1980 + (id) * 0x10)
48 #define SXGMIIaCR0(id)			(0x1a80 + (id) * 0x10)
49 #define QXGMIIaCR0(id)			(0x1b00 + (id) * 0x20)
50 
51 #define SGMIIaCR0_RST_SGM		BIT(31)
52 #define SGMIIaCR0_RST_SGM_OFF		SGMIIaCR0_RST_SGM
53 #define SGMIIaCR0_RST_SGM_ON		0
54 #define SGMIIaCR0_PD_SGM		BIT(30)
55 #define SGMIIaCR1_SGPCS_EN		BIT(11)
56 #define SGMIIaCR1_SGPCS_DIS		0x0
57 
58 #define QSGMIIaCR0_RST_QSGM		BIT(31)
59 #define QSGMIIaCR0_RST_QSGM_OFF		QSGMIIaCR0_RST_QSGM
60 #define QSGMIIaCR0_RST_QSGM_ON		0
61 #define QSGMIIaCR0_PD_QSGM		BIT(30)
62 
63 /* Per PLL registers */
64 #define PLLnCR0(pll)			((pll) * 0x20 + 0x4)
65 
66 #define PLLnCR0_POFF			BIT(31)
67 
68 #define PLLnCR0_REFCLK_SEL		GENMASK(30, 28)
69 #define PLLnCR0_REFCLK_SEL_100MHZ	0x0
70 #define PLLnCR0_REFCLK_SEL_125MHZ	0x1
71 #define PLLnCR0_REFCLK_SEL_156MHZ	0x2
72 #define PLLnCR0_REFCLK_SEL_150MHZ	0x3
73 #define PLLnCR0_REFCLK_SEL_161MHZ	0x4
74 #define PLLnCR0_PLL_LCK			BIT(23)
75 #define PLLnCR0_FRATE_SEL		GENMASK(19, 16)
76 #define PLLnCR0_FRATE_5G		0x0
77 #define PLLnCR0_FRATE_5_15625G		0x6
78 #define PLLnCR0_FRATE_4G		0x7
79 #define PLLnCR0_FRATE_3_125G		0x9
80 #define PLLnCR0_FRATE_3G		0xa
81 
82 /* Per SerDes lane registers */
83 
84 /* Lane a Protocol Select status register */
85 #define LNaPSSR0(lane)			(0x100 + (lane) * 0x20)
86 #define LNaPSSR0_TYPE			GENMASK(30, 26)
87 #define LNaPSSR0_IS_QUAD		GENMASK(25, 24)
88 #define LNaPSSR0_MAC			GENMASK(19, 16)
89 #define LNaPSSR0_PCS			GENMASK(10, 8)
90 #define LNaPSSR0_LANE			GENMASK(2, 0)
91 
92 /* Lane a General Control Register */
93 #define LNaGCR0(lane)			(0x800 + (lane) * 0x40 + 0x0)
94 #define LNaGCR0_RPLL_PLLF		BIT(31)
95 #define LNaGCR0_RPLL_PLLS		0x0
96 #define LNaGCR0_RPLL_MSK		BIT(31)
97 #define LNaGCR0_RRAT_SEL		GENMASK(29, 28)
98 #define LNaGCR0_TRAT_SEL		GENMASK(25, 24)
99 #define LNaGCR0_TPLL_PLLF		BIT(27)
100 #define LNaGCR0_TPLL_PLLS		0x0
101 #define LNaGCR0_TPLL_MSK		BIT(27)
102 #define LNaGCR0_RRST_OFF		LNaGCR0_RRST
103 #define LNaGCR0_TRST_OFF		LNaGCR0_TRST
104 #define LNaGCR0_RRST_ON			0x0
105 #define LNaGCR0_TRST_ON			0x0
106 #define LNaGCR0_RRST			BIT(22)
107 #define LNaGCR0_TRST			BIT(21)
108 #define LNaGCR0_RX_PD			BIT(20)
109 #define LNaGCR0_TX_PD			BIT(19)
110 #define LNaGCR0_IF20BIT_EN		BIT(18)
111 #define LNaGCR0_PROTS			GENMASK(11, 7)
112 
113 #define LNaGCR1(lane)			(0x800 + (lane) * 0x40 + 0x4)
114 #define LNaGCR1_RDAT_INV		BIT(31)
115 #define LNaGCR1_TDAT_INV		BIT(30)
116 #define LNaGCR1_OPAD_CTL		BIT(26)
117 #define LNaGCR1_REIDL_TH		GENMASK(22, 20)
118 #define LNaGCR1_REIDL_EX_SEL		GENMASK(19, 18)
119 #define LNaGCR1_REIDL_ET_SEL		GENMASK(17, 16)
120 #define LNaGCR1_REIDL_EX_MSB		BIT(15)
121 #define LNaGCR1_REIDL_ET_MSB		BIT(14)
122 #define LNaGCR1_REQ_CTL_SNP		BIT(13)
123 #define LNaGCR1_REQ_CDR_SNP		BIT(12)
124 #define LNaGCR1_TRSTDIR			BIT(7)
125 #define LNaGCR1_REQ_BIN_SNP		BIT(6)
126 #define LNaGCR1_ISLEW_RCTL		GENMASK(5, 4)
127 #define LNaGCR1_OSLEW_RCTL		GENMASK(1, 0)
128 
129 #define LNaRECR0(lane)			(0x800 + (lane) * 0x40 + 0x10)
130 #define LNaRECR0_RXEQ_BST		BIT(28)
131 #define LNaRECR0_GK2OVD			GENMASK(27, 24)
132 #define LNaRECR0_GK3OVD			GENMASK(19, 16)
133 #define LNaRECR0_GK2OVD_EN		BIT(15)
134 #define LNaRECR0_GK3OVD_EN		BIT(14)
135 #define LNaRECR0_OSETOVD_EN		BIT(13)
136 #define LNaRECR0_BASE_WAND		GENMASK(11, 10)
137 #define LNaRECR0_OSETOVD		GENMASK(6, 0)
138 
139 #define LNaTECR0(lane)			(0x800 + (lane) * 0x40 + 0x18)
140 #define LNaTECR0_TEQ_TYPE		GENMASK(29, 28)
141 #define LNaTECR0_SGN_PREQ		BIT(26)
142 #define LNaTECR0_RATIO_PREQ		GENMASK(25, 22)
143 #define LNaTECR0_SGN_POST1Q		BIT(21)
144 #define LNaTECR0_RATIO_PST1Q		GENMASK(20, 16)
145 #define LNaTECR0_ADPT_EQ		GENMASK(13, 8)
146 #define LNaTECR0_AMP_RED		GENMASK(5, 0)
147 
148 #define LNaTTLCR0(lane)			(0x800 + (lane) * 0x40 + 0x20)
149 #define LNaTTLCR1(lane)			(0x800 + (lane) * 0x40 + 0x24)
150 #define LNaTTLCR2(lane)			(0x800 + (lane) * 0x40 + 0x28)
151 
152 #define LNaTCSR3(lane)			(0x800 + (lane) * 0x40 + 0x3C)
153 #define LNaTCSR3_CDR_LCK		BIT(27)
154 
155 enum lynx_10g_rat_sel {
156 	RAT_SEL_FULL = 0x0,
157 	RAT_SEL_HALF = 0x1,
158 	RAT_SEL_QUARTER = 0x2,
159 	RAT_SEL_DOUBLE = 0x3,
160 };
161 
162 enum lynx_10g_eq_type {
163 	EQ_TYPE_NO_EQ = 0,
164 	EQ_TYPE_2TAP = 1,
165 	EQ_TYPE_3TAP = 2,
166 };
167 
168 enum lynx_10g_proto_sel {
169 	PROTO_SEL_PCIE = 0,
170 	PROTO_SEL_SGMII_BASEX_KX_QSGMII = 1,
171 	PROTO_SEL_SATA = 2,
172 	PROTO_SEL_XAUI = 4,
173 	PROTO_SEL_XFI_10GBASER_KR_SXGMII = 0xa,
174 };
175 
176 struct lynx_10g_proto_conf {
177 	int proto_sel;
178 	int if20bit_en;
179 	int reidl_th;
180 	int reidl_et_msb;
181 	int reidl_et_sel;
182 	int reidl_ex_msb;
183 	int reidl_ex_sel;
184 	int islew_rctl;
185 	int oslew_rctl;
186 	int rxeq_bst;
187 	int gk2ovd;
188 	int gk3ovd;
189 	int gk2ovd_en;
190 	int gk3ovd_en;
191 	int base_wand;
192 	int teq_type;
193 	int sgn_preq;
194 	int ratio_preq;
195 	int sgn_post1q;
196 	int ratio_post1q;
197 	int adpt_eq;
198 	int amp_red;
199 	int ttlcr0;
200 };
201 
202 static const struct lynx_10g_proto_conf lynx_10g_proto_conf[LANE_MODE_MAX] = {
203 	[LANE_MODE_1000BASEX_SGMII] = {
204 		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
205 		.reidl_th = 1,
206 		.reidl_ex_sel = 3,
207 		.reidl_et_msb = 1,
208 		.islew_rctl = 1,
209 		.oslew_rctl = 1,
210 		.gk2ovd = 15,
211 		.gk3ovd = 15,
212 		.gk2ovd_en = 1,
213 		.gk3ovd_en = 1,
214 		.teq_type = EQ_TYPE_NO_EQ,
215 		.adpt_eq = 48,
216 		.amp_red = 6,
217 		.ttlcr0 = 0x39000400,
218 	},
219 	[LANE_MODE_2500BASEX] = {
220 		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
221 		.islew_rctl = 2,
222 		.oslew_rctl = 2,
223 		.teq_type = EQ_TYPE_2TAP,
224 		.sgn_post1q = 1,
225 		.ratio_post1q = 6,
226 		.adpt_eq = 48,
227 		.ttlcr0 = 0x00000400,
228 	},
229 	[LANE_MODE_QSGMII] = {
230 		.proto_sel = PROTO_SEL_SGMII_BASEX_KX_QSGMII,
231 		.islew_rctl = 1,
232 		.oslew_rctl = 1,
233 		.teq_type = EQ_TYPE_2TAP,
234 		.sgn_post1q = 1,
235 		.ratio_post1q = 6,
236 		.adpt_eq = 48,
237 		.amp_red = 2,
238 		.ttlcr0 = 0x00000400,
239 	},
240 	[LANE_MODE_10G_QXGMII] = {
241 		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
242 		.if20bit_en = 1,
243 		.islew_rctl = 1,
244 		.oslew_rctl = 1,
245 		.base_wand = 1,
246 		.teq_type = EQ_TYPE_NO_EQ,
247 		.adpt_eq = 48,
248 		.ttlcr0 = 0x00000400,
249 	},
250 	[LANE_MODE_USXGMII] = {
251 		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
252 		.if20bit_en = 1,
253 		.islew_rctl = 1,
254 		.oslew_rctl = 1,
255 		.base_wand = 1,
256 		.teq_type = EQ_TYPE_NO_EQ,
257 		.sgn_post1q = 1,
258 		.adpt_eq = 48,
259 		.ttlcr0 = 0x00000400,
260 	},
261 	[LANE_MODE_10GBASER] = {
262 		.proto_sel = PROTO_SEL_XFI_10GBASER_KR_SXGMII,
263 		.if20bit_en = 1,
264 		.islew_rctl = 2,
265 		.oslew_rctl = 2,
266 		.rxeq_bst = 1,
267 		.base_wand = 1,
268 		.teq_type = EQ_TYPE_2TAP,
269 		.sgn_post1q = 1,
270 		.ratio_post1q = 3,
271 		.adpt_eq = 48,
272 		.amp_red = 7,
273 		.ttlcr0 = 0x00000400,
274 	},
275 };
276 
277 static void lynx_10g_cdr_lock_check(struct lynx_lane *lane)
278 {
279 	u32 tcsr3 = lynx_lane_read(lane, LNaTCSR3);
280 
281 	if (tcsr3 & LNaTCSR3_CDR_LCK)
282 		return;
283 
284 	dev_dbg(&lane->phy->dev,
285 		"Lane %c CDR unlocked, resetting receiver...\n",
286 		'A' + lane->id);
287 
288 	lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_ON, LNaGCR0_RRST);
289 	usleep_range(1, 2);
290 	lynx_lane_rmw(lane, LNaGCR0, LNaGCR0_RRST_OFF, LNaGCR0_RRST);
291 
292 	usleep_range(1, 2);
293 }
294 
295 static void lynx_10g_pll_read_configuration(struct lynx_pll *pll)
296 {
297 	u32 val;
298 
299 	val = lynx_pll_read(pll, PLLnCR0);
300 	pll->frate_sel = FIELD_GET(PLLnCR0_FRATE_SEL, val);
301 	pll->refclk_sel = FIELD_GET(PLLnCR0_REFCLK_SEL, val);
302 	pll->enabled = !(val & PLLnCR0_POFF);
303 	pll->locked = !!(val & PLLnCR0_PLL_LCK);
304 
305 	if (!pll->enabled)
306 		return;
307 
308 	switch (pll->frate_sel) {
309 	case PLLnCR0_FRATE_5G:
310 		/* 5GHz clock net */
311 		__set_bit(LANE_MODE_1000BASEX_SGMII, pll->supported);
312 		__set_bit(LANE_MODE_QSGMII, pll->supported);
313 		break;
314 	case PLLnCR0_FRATE_3_125G:
315 		__set_bit(LANE_MODE_2500BASEX, pll->supported);
316 		break;
317 	case PLLnCR0_FRATE_5_15625G:
318 		/* 10.3125GHz clock net */
319 		__set_bit(LANE_MODE_10GBASER, pll->supported);
320 		__set_bit(LANE_MODE_USXGMII, pll->supported);
321 		__set_bit(LANE_MODE_10G_QXGMII, pll->supported);
322 		break;
323 	default:
324 		break;
325 	}
326 }
327 
328 /* On LS1028A, SGMIIA_CFG, SGMIIB_CFG, and SGMIIC_CFG from PCCR8 have the
329  * ability to map either an ENETC PCS (PCCR8_SGMIIa_CFG=2) or a Felix switch
330  * PCS (PCCR8_SGMIIa_CFG=1) to the same lane.
331  *
332  * On LS1088A, the same QSGMII PCS B can be connected to SerDes lane 1
333  * (PCCR9_QSGMIIa_CFG=1) or to lane 3 (PCCR9_QSGMIIa_CFG=2).
334  *
335  * The PHY API lacks the capability to distinguish anything about the consumer,
336  * so we don't support changing the initial muxing done by the RCW.
337  *
338  * However, after disabling a PCS through PCCR8, we need to properly restore
339  * the original value to keep the same muxing, and for that we need to back
340  * it up (here).
341  */
342 static void lynx_10g_backup_pccr_val(struct lynx_lane *lane)
343 {
344 	u32 val;
345 	int err;
346 
347 	if (lane->mode == LANE_MODE_UNKNOWN)
348 		return;
349 
350 	err = lynx_pccr_read(lane, lane->mode, &val);
351 	if (err) {
352 		dev_warn(&lane->phy->dev,
353 			 "The driver doesn't know how to access the PCCR for lane mode %s\n",
354 			 lynx_lane_mode_str(lane->mode));
355 		lane->mode = LANE_MODE_UNKNOWN;
356 		return;
357 	}
358 
359 	lane->default_pccr[lane->mode] = val;
360 
361 	/* 1000Base-X, 1000Base-KX, 2500Base-KX and SGMII use the same PCCR8.
362 	 * Only the KX bit differs (set for 1000Base-KX). Since we back up PCCR
363 	 * values per lane mode, make sure to not back up the PCCR8 value with
364 	 * the KX bit set for the non-KX modes, if the lane was in KX mode at
365 	 * boot time. Just preserve bits 2:0, which tell whether the (and
366 	 * which) 1G PCS was enabled.
367 	 */
368 	switch (lane->mode) {
369 	case LANE_MODE_1000BASEX_SGMII:
370 	case LANE_MODE_2500BASEX:
371 		lane->default_pccr[LANE_MODE_1000BASEX_SGMII] = val & ~PCCR8_SGMIIa_KX;
372 		lane->default_pccr[LANE_MODE_2500BASEX] = val & ~PCCR8_SGMIIa_KX;
373 		break;
374 	default:
375 		break;
376 	}
377 }
378 
379 /* Is the PCS enabled, according to the value backed up from the PCCR register
380  * for this lane mode?
381  *
382  * Normally we'd need to ask "what lane mode are we talking about?", but the
383  * answer is invariably the same regardless - PCCR8_SGMIIa_CFG has the same
384  * layout as PCCR9_QSGMIIa_CFG, PCCRB_XFIa_CFG etc etc, and the value 0
385  * universally means "PCS disabled". So this is just a shorthand answer.
386  */
387 static bool lynx_10g_pccr_val_enabled(u32 pccr)
388 {
389 	return FIELD_PREP(PCCR8_SGMIIa_CFG, pccr) != 0;
390 }
391 
392 static bool lynx_10g_lane_is_3_125g(struct lynx_lane *lane)
393 {
394 	struct lynx_priv *priv = lane->priv;
395 	struct lynx_pll *pll;
396 	u32 gcr0;
397 
398 	gcr0 = lynx_lane_read(lane, LNaGCR0);
399 
400 	if (gcr0 & LNaGCR0_TPLL_PLLF)
401 		pll = &priv->pll[0];
402 	else
403 		pll = &priv->pll[1];
404 
405 	if (pll->frate_sel != PLLnCR0_FRATE_3_125G)
406 		return false;
407 
408 	if (FIELD_GET(LNaGCR0_TRAT_SEL, gcr0) != RAT_SEL_FULL ||
409 	    FIELD_GET(LNaGCR0_RRAT_SEL, gcr0) != RAT_SEL_FULL)
410 		return false;
411 
412 	return true;
413 }
414 
415 static void lynx_10g_lane_read_configuration(struct lynx_lane *lane)
416 {
417 	u32 pssr0 = lynx_lane_read(lane, LNaPSSR0);
418 	struct lynx_priv *priv = lane->priv;
419 	int proto;
420 
421 	proto = FIELD_GET(LNaPSSR0_TYPE, pssr0);
422 	switch (proto) {
423 	case PROTO_SEL_SGMII_BASEX_KX_QSGMII:
424 		if (lynx_10g_lane_is_3_125g(lane))
425 			lane->mode = LANE_MODE_2500BASEX;
426 		else if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
427 			lane->mode = LANE_MODE_QSGMII;
428 		else
429 			lane->mode = LANE_MODE_1000BASEX_SGMII;
430 		break;
431 	case PROTO_SEL_XFI_10GBASER_KR_SXGMII:
432 		if (FIELD_GET(LNaPSSR0_IS_QUAD, pssr0))
433 			lane->mode = LANE_MODE_10G_QXGMII;
434 		else if (priv->info->quirks & LYNX_QUIRK_HAS_HARDCODED_USXGMII)
435 			lane->mode = LANE_MODE_USXGMII;
436 		else
437 			lane->mode = LANE_MODE_10GBASER;
438 		break;
439 	case PROTO_SEL_PCIE:
440 	case PROTO_SEL_SATA:
441 	case PROTO_SEL_XAUI:
442 		break;
443 	default:
444 		dev_warn(&lane->phy->dev, "Unknown lane protocol 0x%x\n",
445 			 proto);
446 	}
447 
448 	lynx_10g_backup_pccr_val(lane);
449 }
450 
451 static int ls1028a_get_pccr(enum lynx_lane_mode lane_mode, int lane,
452 			    struct lynx_pccr *pccr)
453 {
454 	switch (lane_mode) {
455 	case LANE_MODE_1000BASEX_SGMII:
456 	case LANE_MODE_2500BASEX:
457 		pccr->offset = PCCR8;
458 		pccr->width = 4;
459 		pccr->shift = SGMII_CFG(lane);
460 		break;
461 	case LANE_MODE_QSGMII:
462 		if (lane != 1)
463 			return -EINVAL;
464 
465 		pccr->offset = PCCR9;
466 		pccr->width = 3;
467 		pccr->shift = QSGMII_CFG(A);
468 		break;
469 	case LANE_MODE_10G_QXGMII:
470 		if (lane != 1)
471 			return -EINVAL;
472 
473 		pccr->offset = PCCR9;
474 		pccr->width = 3;
475 		pccr->shift = QXGMII_CFG(A);
476 		break;
477 	case LANE_MODE_USXGMII:
478 		if (lane != 0)
479 			return -EINVAL;
480 
481 		pccr->offset = PCCRB;
482 		pccr->width = 3;
483 		pccr->shift = SXGMII_CFG(A);
484 		break;
485 	default:
486 		return -EINVAL;
487 	}
488 
489 	return 0;
490 }
491 
492 static int ls1028a_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
493 {
494 	switch (mode) {
495 	case LANE_MODE_1000BASEX_SGMII:
496 	case LANE_MODE_2500BASEX:
497 		return SGMIIaCR0(lane);
498 	case LANE_MODE_QSGMII:
499 		return lane == 1 ? QSGMIIaCR0(A) : -EINVAL;
500 	case LANE_MODE_USXGMII:
501 		return lane == 0 ? SXGMIIaCR0(A) : -EINVAL;
502 	case LANE_MODE_10G_QXGMII:
503 		return lane == 1 ? QXGMIIaCR0(A) : -EINVAL;
504 	default:
505 		return -EINVAL;
506 	}
507 }
508 
509 static const struct lynx_info lynx_info_ls1028a = {
510 	.get_pccr = ls1028a_get_pccr,
511 	.get_pcvt_offset = ls1028a_get_pcvt_offset,
512 	.pll_read_configuration = lynx_10g_pll_read_configuration,
513 	.lane_read_configuration = lynx_10g_lane_read_configuration,
514 	.cdr_lock_check = lynx_10g_cdr_lock_check,
515 	.num_lanes = 4,
516 	.index = 1,
517 	.quirks = LYNX_QUIRK_HAS_HARDCODED_USXGMII,
518 };
519 
520 static int ls1046a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
521 				    struct lynx_pccr *pccr)
522 {
523 	switch (lane_mode) {
524 	case LANE_MODE_1000BASEX_SGMII:
525 	case LANE_MODE_2500BASEX:
526 		pccr->offset = PCCR8;
527 		pccr->width = 4;
528 		pccr->shift = SGMII_CFG(lane);
529 		break;
530 	case LANE_MODE_QSGMII:
531 		if (lane != 1)
532 			return -EINVAL;
533 
534 		pccr->offset = PCCR9;
535 		pccr->width = 3;
536 		pccr->shift = QSGMII_CFG(B);
537 		break;
538 	case LANE_MODE_10GBASER:
539 		switch (lane) {
540 		case 2:
541 			pccr->shift = XFI_CFG(A);
542 			break;
543 		case 3:
544 			pccr->shift = XFI_CFG(B);
545 			break;
546 		default:
547 			return -EINVAL;
548 		}
549 
550 		pccr->offset = PCCRB;
551 		pccr->width = 3;
552 		break;
553 	default:
554 		return -EINVAL;
555 	}
556 
557 	return 0;
558 }
559 
560 static int ls1046a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
561 {
562 	switch (mode) {
563 	case LANE_MODE_1000BASEX_SGMII:
564 	case LANE_MODE_2500BASEX:
565 		return SGMIIaCR0(lane);
566 	case LANE_MODE_QSGMII:
567 		if (lane != 1)
568 			return -EINVAL;
569 
570 		return QSGMIIaCR0(B);
571 	case LANE_MODE_10GBASER:
572 		switch (lane) {
573 		case 2:
574 			return XFIaCR0(A);
575 		case 3:
576 			return XFIaCR0(B);
577 		default:
578 			return -EINVAL;
579 		}
580 	default:
581 		return -EINVAL;
582 	}
583 }
584 
585 static const struct lynx_info lynx_info_ls1046a_serdes1 = {
586 	.get_pccr = ls1046a_serdes1_get_pccr,
587 	.get_pcvt_offset = ls1046a_serdes1_get_pcvt_offset,
588 	.pll_read_configuration = lynx_10g_pll_read_configuration,
589 	.lane_read_configuration = lynx_10g_lane_read_configuration,
590 	.cdr_lock_check = lynx_10g_cdr_lock_check,
591 	.num_lanes = 4,
592 	.index = 1,
593 };
594 
595 static int ls1046a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
596 				    struct lynx_pccr *pccr)
597 {
598 	switch (lane_mode) {
599 	case LANE_MODE_1000BASEX_SGMII:
600 	case LANE_MODE_2500BASEX:
601 		if (lane != 1)
602 			return -EINVAL;
603 
604 		pccr->offset = PCCR8;
605 		pccr->width = 4;
606 		pccr->shift = SGMII_CFG(B);
607 		break;
608 	default:
609 		return -EINVAL;
610 	}
611 
612 	return 0;
613 }
614 
615 static int ls1046a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
616 {
617 	switch (mode) {
618 	case LANE_MODE_1000BASEX_SGMII:
619 	case LANE_MODE_2500BASEX:
620 		if (lane != 1)
621 			return -EINVAL;
622 
623 		return SGMIIaCR0(B);
624 	default:
625 		return -EINVAL;
626 	}
627 }
628 
629 static const struct lynx_info lynx_info_ls1046a_serdes2 = {
630 	.get_pccr = ls1046a_serdes2_get_pccr,
631 	.get_pcvt_offset = ls1046a_serdes2_get_pcvt_offset,
632 	.pll_read_configuration = lynx_10g_pll_read_configuration,
633 	.lane_read_configuration = lynx_10g_lane_read_configuration,
634 	.cdr_lock_check = lynx_10g_cdr_lock_check,
635 	.num_lanes = 4,
636 	.index = 2,
637 };
638 
639 static int ls1088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
640 				    struct lynx_pccr *pccr)
641 {
642 	switch (lane_mode) {
643 	case LANE_MODE_1000BASEX_SGMII:
644 		pccr->offset = PCCR8;
645 		pccr->width = 4;
646 		pccr->shift = SGMII_CFG(lane);
647 		break;
648 	case LANE_MODE_QSGMII:
649 		switch (lane) {
650 		case 0:
651 			pccr->shift = QSGMII_CFG(A);
652 			break;
653 		case 1:
654 		case 3:
655 			pccr->shift = QSGMII_CFG(B);
656 			break;
657 		default:
658 			return -EINVAL;
659 		}
660 
661 		pccr->offset = PCCR9;
662 		pccr->width = 3;
663 		break;
664 	case LANE_MODE_10GBASER:
665 		switch (lane) {
666 		case 2:
667 			pccr->shift = XFI_CFG(A);
668 			break;
669 		case 3:
670 			pccr->shift = XFI_CFG(B);
671 			break;
672 		default:
673 			return -EINVAL;
674 		}
675 
676 		pccr->offset = PCCRB;
677 		pccr->width = 3;
678 		break;
679 	default:
680 		return -EINVAL;
681 	}
682 
683 	return 0;
684 }
685 
686 static int ls1088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
687 {
688 	switch (mode) {
689 	case LANE_MODE_1000BASEX_SGMII:
690 		return SGMIIaCR0(lane);
691 	case LANE_MODE_QSGMII:
692 		switch (lane) {
693 		case 0:
694 			return QSGMIIaCR0(A);
695 		case 1:
696 		case 3:
697 			return QSGMIIaCR0(B);
698 		default:
699 			return -EINVAL;
700 		}
701 	case LANE_MODE_10GBASER:
702 		switch (lane) {
703 		case 2:
704 			return XFIaCR0(A);
705 		case 3:
706 			return XFIaCR0(B);
707 		default:
708 			return -EINVAL;
709 		}
710 	default:
711 		return -EINVAL;
712 	}
713 }
714 
715 static const struct lynx_info lynx_info_ls1088a_serdes1 = {
716 	.get_pccr = ls1088a_serdes1_get_pccr,
717 	.get_pcvt_offset = ls1088a_serdes1_get_pcvt_offset,
718 	.pll_read_configuration = lynx_10g_pll_read_configuration,
719 	.lane_read_configuration = lynx_10g_lane_read_configuration,
720 	.cdr_lock_check = lynx_10g_cdr_lock_check,
721 	.num_lanes = 4,
722 	.index = 1,
723 };
724 
725 static int ls2088a_serdes1_get_pccr(enum lynx_lane_mode lane_mode, int lane,
726 				    struct lynx_pccr *pccr)
727 {
728 	switch (lane_mode) {
729 	case LANE_MODE_1000BASEX_SGMII:
730 	case LANE_MODE_2500BASEX:
731 		pccr->offset = PCCR8;
732 		pccr->width = 4;
733 		pccr->shift = SGMII_CFG(lane);
734 		break;
735 	case LANE_MODE_QSGMII:
736 		switch (lane) {
737 		case 2:
738 		case 6:
739 			pccr->shift = QSGMII_CFG(A);
740 			break;
741 		case 7:
742 			pccr->shift = QSGMII_CFG(B);
743 			break;
744 		case 0:
745 		case 4:
746 			pccr->shift = QSGMII_CFG(C);
747 			break;
748 		case 1:
749 		case 5:
750 			pccr->shift = QSGMII_CFG(D);
751 			break;
752 		default:
753 			return -EINVAL;
754 		}
755 
756 		pccr->offset = PCCR9;
757 		pccr->width = 3;
758 		break;
759 	case LANE_MODE_10GBASER:
760 		pccr->offset = PCCRB;
761 		pccr->width = 3;
762 		pccr->shift = XFI_CFG(lane);
763 		break;
764 	default:
765 		return -EINVAL;
766 	}
767 
768 	return 0;
769 }
770 
771 static int ls2088a_serdes1_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
772 {
773 	switch (mode) {
774 	case LANE_MODE_1000BASEX_SGMII:
775 	case LANE_MODE_2500BASEX:
776 		return SGMIIaCR0(lane);
777 	case LANE_MODE_QSGMII:
778 		switch (lane) {
779 		case 2:
780 		case 6:
781 			return QSGMIIaCR0(A);
782 		case 7:
783 			return QSGMIIaCR0(B);
784 		case 0:
785 		case 4:
786 			return QSGMIIaCR0(C);
787 		case 1:
788 		case 5:
789 			return QSGMIIaCR0(D);
790 		default:
791 			return -EINVAL;
792 		}
793 	case LANE_MODE_10GBASER:
794 		return XFIaCR0(lane);
795 	default:
796 		return -EINVAL;
797 	}
798 }
799 
800 static const struct lynx_info lynx_info_ls2088a_serdes1 = {
801 	.get_pccr = ls2088a_serdes1_get_pccr,
802 	.get_pcvt_offset = ls2088a_serdes1_get_pcvt_offset,
803 	.pll_read_configuration = lynx_10g_pll_read_configuration,
804 	.lane_read_configuration = lynx_10g_lane_read_configuration,
805 	.cdr_lock_check = lynx_10g_cdr_lock_check,
806 	.num_lanes = 8,
807 	.index = 1,
808 };
809 
810 static int ls2088a_serdes2_get_pccr(enum lynx_lane_mode lane_mode, int lane,
811 				    struct lynx_pccr *pccr)
812 {
813 	switch (lane_mode) {
814 	case LANE_MODE_1000BASEX_SGMII:
815 	case LANE_MODE_2500BASEX:
816 		pccr->offset = PCCR8;
817 		pccr->width = 4;
818 		pccr->shift = SGMII_CFG(lane);
819 		break;
820 	default:
821 		return -EINVAL;
822 	}
823 
824 	return 0;
825 }
826 
827 static int ls2088a_serdes2_get_pcvt_offset(int lane, enum lynx_lane_mode mode)
828 {
829 	switch (mode) {
830 	case LANE_MODE_1000BASEX_SGMII:
831 	case LANE_MODE_2500BASEX:
832 		return SGMIIaCR0(lane);
833 	default:
834 		return -EINVAL;
835 	}
836 }
837 
838 static const struct lynx_info lynx_info_ls2088a_serdes2 = {
839 	.get_pccr = ls2088a_serdes2_get_pccr,
840 	.get_pcvt_offset = ls2088a_serdes2_get_pcvt_offset,
841 	.pll_read_configuration = lynx_10g_pll_read_configuration,
842 	.lane_read_configuration = lynx_10g_lane_read_configuration,
843 	.cdr_lock_check = lynx_10g_cdr_lock_check,
844 	.num_lanes = 8,
845 	.index = 2,
846 };
847 
848 /* Halting puts the lane in a mode in which it can be reconfigured */
849 static void lynx_10g_lane_halt(struct phy *phy)
850 {
851 	struct lynx_lane *lane = phy_get_drvdata(phy);
852 
853 	/* Issue a reset request */
854 	lynx_lane_rmw(lane, LNaGCR0,
855 		      LNaGCR0_RRST_ON | LNaGCR0_TRST_ON,
856 		      LNaGCR0_RRST | LNaGCR0_TRST);
857 
858 	/* The RM says to wait for at least 50ns */
859 	usleep_range(1, 2);
860 }
861 
862 static void lynx_10g_lane_reset(struct phy *phy)
863 {
864 	struct lynx_lane *lane = phy_get_drvdata(phy);
865 
866 	/* Finalize the reset request */
867 	lynx_lane_rmw(lane, LNaGCR0,
868 		      LNaGCR0_RRST_OFF | LNaGCR0_TRST_OFF,
869 		      LNaGCR0_RRST | LNaGCR0_TRST);
870 }
871 
872 static int lynx_10g_power_off(struct phy *phy)
873 {
874 	struct lynx_lane *lane = phy_get_drvdata(phy);
875 
876 	if (!lane->powered_up)
877 		return 0;
878 
879 	/* Issue a reset request with the power down bits set */
880 	lynx_lane_rmw(lane, LNaGCR0,
881 		      LNaGCR0_RRST_ON | LNaGCR0_TRST_ON |
882 		      LNaGCR0_RX_PD | LNaGCR0_TX_PD,
883 		      LNaGCR0_RRST | LNaGCR0_TRST |
884 		      LNaGCR0_RX_PD | LNaGCR0_TX_PD);
885 
886 	/* The RM says to wait for at least 50ns */
887 	usleep_range(1, 2);
888 
889 	lane->powered_up = false;
890 
891 	return 0;
892 }
893 
894 static int lynx_10g_power_on(struct phy *phy)
895 {
896 	struct lynx_lane *lane = phy_get_drvdata(phy);
897 
898 	if (lane->powered_up)
899 		return 0;
900 
901 	/* RM says that to enable a previously powered down lane, set
902 	 * LNmGCR0[{R,T}X_PD]=0, wait 15 us, then set LNmGCR0[{R,T}RST]=1.
903 	 */
904 	lynx_lane_rmw(lane, LNaGCR0, 0, LNaGCR0_RX_PD | LNaGCR0_TX_PD);
905 	usleep_range(150, 300);
906 	lynx_10g_lane_reset(phy);
907 
908 	lane->powered_up = true;
909 
910 	return 0;
911 }
912 
913 static void lynx_10g_lane_set_nrate(struct lynx_lane *lane,
914 				    struct lynx_pll *pll,
915 				    enum lynx_lane_mode mode)
916 {
917 	enum lynx_10g_rat_sel nrate;
918 
919 	switch (pll->frate_sel) {
920 	case PLLnCR0_FRATE_5G:
921 		switch (mode) {
922 		case LANE_MODE_1000BASEX_SGMII:
923 			nrate = RAT_SEL_QUARTER;
924 			break;
925 		case LANE_MODE_QSGMII:
926 			nrate = RAT_SEL_FULL;
927 			break;
928 		default:
929 			return;
930 		}
931 		break;
932 	case PLLnCR0_FRATE_3_125G:
933 		switch (mode) {
934 		case LANE_MODE_2500BASEX:
935 			nrate = RAT_SEL_FULL;
936 			break;
937 		default:
938 			return;
939 		}
940 		break;
941 	case PLLnCR0_FRATE_5_15625G:
942 		switch (mode) {
943 		case LANE_MODE_10GBASER:
944 		case LANE_MODE_USXGMII:
945 		case LANE_MODE_10G_QXGMII:
946 			nrate = RAT_SEL_DOUBLE;
947 			break;
948 		default:
949 			return;
950 		}
951 		break;
952 	default:
953 		return;
954 	}
955 
956 	lynx_lane_rmw(lane, LNaGCR0,
957 		      FIELD_PREP(LNaGCR0_TRAT_SEL, nrate) |
958 		      FIELD_PREP(LNaGCR0_RRAT_SEL, nrate),
959 		      LNaGCR0_RRAT_SEL | LNaGCR0_TRAT_SEL);
960 }
961 
962 static void lynx_10g_lane_set_pll(struct lynx_lane *lane,
963 				  struct lynx_pll *pll)
964 {
965 	if (pll->id == 0) {
966 		lynx_lane_rmw(lane, LNaGCR0,
967 			      LNaGCR0_RPLL_PLLF | LNaGCR0_TPLL_PLLF,
968 			      LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
969 	} else {
970 		lynx_lane_rmw(lane, LNaGCR0,
971 			      LNaGCR0_RPLL_PLLS | LNaGCR0_TPLL_PLLS,
972 			      LNaGCR0_RPLL_MSK | LNaGCR0_TPLL_MSK);
973 	}
974 }
975 
976 static void lynx_10g_lane_remap_pll(struct lynx_lane *lane,
977 				    enum lynx_lane_mode lane_mode)
978 {
979 	struct lynx_priv *priv = lane->priv;
980 	struct lynx_pll *pll;
981 
982 	/* Switch to the PLL that works with this interface type */
983 	pll = lynx_pll_get(priv, lane_mode);
984 	if (unlikely(!pll))
985 		return;
986 
987 	lynx_10g_lane_set_pll(lane, pll);
988 
989 	/* Choose the portion of clock net to be used on this lane */
990 	lynx_10g_lane_set_nrate(lane, pll, lane_mode);
991 }
992 
993 static void lynx_10g_lane_change_proto_conf(struct lynx_lane *lane,
994 					    enum lynx_lane_mode mode)
995 {
996 	const struct lynx_10g_proto_conf *conf = &lynx_10g_proto_conf[mode];
997 
998 	lynx_lane_rmw(lane, LNaGCR0,
999 		      FIELD_PREP(LNaGCR0_PROTS, conf->proto_sel) |
1000 		      FIELD_PREP(LNaGCR0_IF20BIT_EN, conf->if20bit_en),
1001 		      LNaGCR0_PROTS | LNaGCR0_IF20BIT_EN);
1002 	lynx_lane_rmw(lane, LNaGCR1,
1003 		      FIELD_PREP(LNaGCR1_REIDL_TH, conf->reidl_th) |
1004 		      FIELD_PREP(LNaGCR1_REIDL_ET_MSB, conf->reidl_et_msb) |
1005 		      FIELD_PREP(LNaGCR1_REIDL_ET_SEL, conf->reidl_et_sel) |
1006 		      FIELD_PREP(LNaGCR1_REIDL_EX_MSB, conf->reidl_ex_msb) |
1007 		      FIELD_PREP(LNaGCR1_REIDL_EX_SEL, conf->reidl_ex_sel) |
1008 		      FIELD_PREP(LNaGCR1_ISLEW_RCTL, conf->islew_rctl) |
1009 		      FIELD_PREP(LNaGCR1_OSLEW_RCTL, conf->oslew_rctl),
1010 		      LNaGCR1_REIDL_TH |
1011 		      LNaGCR1_REIDL_ET_MSB | LNaGCR1_REIDL_ET_SEL |
1012 		      LNaGCR1_REIDL_EX_MSB | LNaGCR1_REIDL_EX_SEL |
1013 		      LNaGCR1_ISLEW_RCTL | LNaGCR1_OSLEW_RCTL);
1014 	lynx_lane_rmw(lane, LNaRECR0,
1015 		      FIELD_PREP(LNaRECR0_RXEQ_BST, conf->rxeq_bst) |
1016 		      FIELD_PREP(LNaRECR0_GK2OVD, conf->gk2ovd) |
1017 		      FIELD_PREP(LNaRECR0_GK3OVD, conf->gk3ovd) |
1018 		      FIELD_PREP(LNaRECR0_GK2OVD_EN, conf->gk2ovd_en) |
1019 		      FIELD_PREP(LNaRECR0_GK3OVD_EN, conf->gk3ovd_en) |
1020 		      FIELD_PREP(LNaRECR0_BASE_WAND, conf->base_wand),
1021 		      LNaRECR0_RXEQ_BST | LNaRECR0_GK2OVD | LNaRECR0_GK3OVD |
1022 		      LNaRECR0_GK2OVD_EN | LNaRECR0_GK3OVD_EN |
1023 		      LNaRECR0_BASE_WAND);
1024 	lynx_lane_rmw(lane, LNaTECR0,
1025 		      FIELD_PREP(LNaTECR0_TEQ_TYPE, conf->teq_type) |
1026 		      FIELD_PREP(LNaTECR0_SGN_PREQ, conf->sgn_preq) |
1027 		      FIELD_PREP(LNaTECR0_RATIO_PREQ, conf->ratio_preq) |
1028 		      FIELD_PREP(LNaTECR0_SGN_POST1Q, conf->sgn_post1q) |
1029 		      FIELD_PREP(LNaTECR0_RATIO_PST1Q, conf->ratio_post1q) |
1030 		      FIELD_PREP(LNaTECR0_ADPT_EQ, conf->adpt_eq) |
1031 		      FIELD_PREP(LNaTECR0_AMP_RED, conf->amp_red),
1032 		      LNaTECR0_TEQ_TYPE | LNaTECR0_SGN_PREQ |
1033 		      LNaTECR0_RATIO_PREQ | LNaTECR0_SGN_POST1Q |
1034 		      LNaTECR0_RATIO_PST1Q | LNaTECR0_ADPT_EQ |
1035 		      LNaTECR0_AMP_RED);
1036 	lynx_lane_write(lane, LNaTTLCR0, conf->ttlcr0);
1037 }
1038 
1039 static int lynx_10g_lane_disable_pcvt(struct lynx_lane *lane,
1040 				      enum lynx_lane_mode mode)
1041 {
1042 	struct lynx_priv *priv = lane->priv;
1043 	int err;
1044 
1045 	spin_lock(&priv->pcc_lock);
1046 
1047 	err = lynx_pccr_write(lane, mode, 0);
1048 	if (err)
1049 		goto out;
1050 
1051 	switch (mode) {
1052 	case LANE_MODE_1000BASEX_SGMII:
1053 	case LANE_MODE_2500BASEX:
1054 		err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_DIS,
1055 				    SGMIIaCR1_SGPCS_EN);
1056 		if (err)
1057 			goto out;
1058 
1059 		lynx_pcvt_rmw(lane, mode, CR(0),
1060 			      SGMIIaCR0_RST_SGM_ON | SGMIIaCR0_PD_SGM,
1061 			      SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
1062 		break;
1063 	case LANE_MODE_QSGMII:
1064 		err = lynx_pcvt_rmw(lane, mode, CR(0),
1065 				    QSGMIIaCR0_RST_QSGM_ON | QSGMIIaCR0_PD_QSGM,
1066 				    QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
1067 		if (err)
1068 			goto out;
1069 		break;
1070 	default:
1071 		err = 0;
1072 	}
1073 
1074 out:
1075 	spin_unlock(&priv->pcc_lock);
1076 
1077 	return err;
1078 }
1079 
1080 static int lynx_10g_lane_enable_pcvt(struct lynx_lane *lane,
1081 				     enum lynx_lane_mode mode)
1082 {
1083 	struct lynx_priv *priv = lane->priv;
1084 	u32 val;
1085 	int err;
1086 
1087 	spin_lock(&priv->pcc_lock);
1088 
1089 	switch (mode) {
1090 	case LANE_MODE_1000BASEX_SGMII:
1091 	case LANE_MODE_2500BASEX:
1092 		err = lynx_pcvt_rmw(lane, mode, CR(1), SGMIIaCR1_SGPCS_EN,
1093 				    SGMIIaCR1_SGPCS_EN);
1094 		if (err)
1095 			goto out;
1096 
1097 		lynx_pcvt_rmw(lane, mode, CR(0), SGMIIaCR0_RST_SGM_OFF,
1098 			      SGMIIaCR0_RST_SGM | SGMIIaCR0_PD_SGM);
1099 		break;
1100 	case LANE_MODE_QSGMII:
1101 		err = lynx_pcvt_rmw(lane, mode, CR(0), QSGMIIaCR0_RST_QSGM_OFF,
1102 				    QSGMIIaCR0_RST_QSGM | QSGMIIaCR0_PD_QSGM);
1103 		if (err)
1104 			goto out;
1105 		break;
1106 	default:
1107 		err = 0;
1108 	}
1109 
1110 	/* If the PCS was enabled at boot time, use the backed up PCCR value to
1111 	 * re-enable it here, to preserve the muxing.
1112 	 */
1113 	if (lynx_10g_pccr_val_enabled(lane->default_pccr[mode])) {
1114 		err = lynx_pccr_write(lane, mode, lane->default_pccr[mode]);
1115 		goto out;
1116 	}
1117 
1118 	/* If the PCS was not enabled, set the PCCR to a default value which
1119 	 * enables it (1). The assumption is that this is the only PCS <->
1120 	 * SerDes lane muxing value possible.
1121 	 *
1122 	 * This is mostly useful for SGMII <-> 10GBase-R major protocol
1123 	 * reconfiguration, where at boot time, either the SGMII or the
1124 	 * 10GBase-R PCS is enabled for the lane, but not both.
1125 	 *
1126 	 * In fact, if there are multiple lane muxing options, this function
1127 	 * will most likely not choose the right one. For correct functionality
1128 	 * there, we assume that the PCS we are enabling here was found enabled
1129 	 * at boot time (reset default, or through PBL, or...), and we preserve
1130 	 * its muxing through the default_pccr branch above.
1131 	 */
1132 	val = 0;
1133 
1134 	switch (mode) {
1135 	case LANE_MODE_1000BASEX_SGMII:
1136 	case LANE_MODE_2500BASEX:
1137 		val |= FIELD_PREP(PCCR8_SGMIIa_CFG, 1);
1138 		break;
1139 	case LANE_MODE_QSGMII:
1140 		val |= FIELD_PREP(PCCR9_QSGMIIa_CFG, 1);
1141 		break;
1142 	case LANE_MODE_10G_QXGMII:
1143 		val |= FIELD_PREP(PCCR9_QXGMIIa_CFG, 1);
1144 		break;
1145 	case LANE_MODE_10GBASER:
1146 		val |= FIELD_PREP(PCCRB_XFIa_CFG, 1);
1147 		break;
1148 	case LANE_MODE_USXGMII:
1149 		val |= FIELD_PREP(PCCRB_SXGMIIa_CFG, 1);
1150 		break;
1151 	default:
1152 		err = 0;
1153 		goto out;
1154 	}
1155 
1156 	err = lynx_pccr_write(lane, mode, val);
1157 out:
1158 	spin_unlock(&priv->pcc_lock);
1159 
1160 	return err;
1161 }
1162 
1163 static bool lynx_10g_lane_mode_needs_rcw_override(struct lynx_lane *lane,
1164 						  enum lynx_lane_mode new)
1165 {
1166 	enum lynx_lane_mode curr = lane->mode;
1167 
1168 	/* Major protocol changes, which involve changing the PCS connection to
1169 	 * the GMII MAC with the one to the XGMII MAC, require an RCW override
1170 	 * procedure to reconfigure an internal mux, as documented here:
1171 	 * https://lore.kernel.org/linux-phy/20230810102631.bvozjer3t67r67iy@skbuf/
1172 	 * This is SoC-specific, and not yet implemented in drivers/soc/fsl/guts.c.
1173 	 *
1174 	 * So the supported set of protocols depends on the initial lane mode.
1175 	 *
1176 	 * Minor protocol changes (SGMII <-> 1000Base-X <-> 2500Base-X or
1177 	 * 10GBase-R <-> USXGMII) are supported.
1178 	 */
1179 	if ((lynx_lane_mode_uses_gmii_mac(curr) &&
1180 	     lynx_lane_mode_uses_xgmii_mac(new)) ||
1181 	    (lynx_lane_mode_uses_xgmii_mac(curr) &&
1182 	     lynx_lane_mode_uses_gmii_mac(new)))
1183 		return true;
1184 
1185 	return false;
1186 }
1187 
1188 static int lynx_10g_validate(struct phy *phy, enum phy_mode mode, int submode,
1189 			     union phy_configure_opts *opts)
1190 {
1191 	struct lynx_lane *lane = phy_get_drvdata(phy);
1192 	enum lynx_lane_mode lane_mode;
1193 	int err;
1194 
1195 	err = lynx_phy_mode_to_lane_mode(phy, mode, submode, &lane_mode);
1196 	if (err)
1197 		return err;
1198 
1199 	if (lynx_10g_lane_mode_needs_rcw_override(lane, lane_mode))
1200 		return -EINVAL;
1201 
1202 	return 0;
1203 }
1204 
1205 static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
1206 {
1207 	struct lynx_lane *lane = phy_get_drvdata(phy);
1208 	bool powered_up = lane->powered_up;
1209 	enum lynx_lane_mode lane_mode;
1210 	int err;
1211 
1212 	err = lynx_10g_validate(phy, mode, submode, NULL);
1213 	if (err)
1214 		return err;
1215 
1216 	lane_mode = phy_interface_to_lane_mode(submode);
1217 	/* lynx_10g_validate() already made sure the lane_mode is supported */
1218 
1219 	if (lane_mode == lane->mode)
1220 		return 0;
1221 
1222 	/* If the lane is powered up, put the lane into the halt state while
1223 	 * the reconfiguration is being done.
1224 	 */
1225 	if (powered_up)
1226 		lynx_10g_lane_halt(phy);
1227 
1228 	err = lynx_10g_lane_disable_pcvt(lane, lane->mode);
1229 	if (err)
1230 		goto out;
1231 
1232 	lynx_10g_lane_change_proto_conf(lane, lane_mode);
1233 	lynx_10g_lane_remap_pll(lane, lane_mode);
1234 	WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode));
1235 
1236 	lane->mode = lane_mode;
1237 
1238 out:
1239 	if (powered_up) {
1240 		/* The RM says to wait for at least 120 ns */
1241 		usleep_range(1, 2);
1242 		lynx_10g_lane_reset(phy);
1243 	}
1244 
1245 	return err;
1246 }
1247 
1248 static int lynx_10g_init(struct phy *phy)
1249 {
1250 	struct lynx_lane *lane = phy_get_drvdata(phy);
1251 
1252 	/* Mark the fact that the lane was init */
1253 	lane->init = true;
1254 
1255 	/* SerDes lanes are powered on at boot time. Any lane that is
1256 	 * managed by this driver will get powered off when its consumer
1257 	 * calls phy_init().
1258 	 */
1259 	lane->powered_up = true;
1260 	lynx_10g_power_off(phy);
1261 
1262 	return 0;
1263 }
1264 
1265 static int lynx_10g_exit(struct phy *phy)
1266 {
1267 	struct lynx_lane *lane = phy_get_drvdata(phy);
1268 
1269 	/* The lane returns to the state where it isn't managed by the
1270 	 * consumer, so we must treat is as if it isn't initialized, and always
1271 	 * powered on.
1272 	 */
1273 	lane->init = false;
1274 	lane->powered_up = false;
1275 	lynx_10g_power_on(phy);
1276 
1277 	return 0;
1278 }
1279 
1280 static const struct phy_ops lynx_10g_ops = {
1281 	.init		= lynx_10g_init,
1282 	.exit		= lynx_10g_exit,
1283 	.power_on	= lynx_10g_power_on,
1284 	.power_off	= lynx_10g_power_off,
1285 	.set_mode	= lynx_10g_set_mode,
1286 	.validate	= lynx_10g_validate,
1287 	.owner		= THIS_MODULE,
1288 };
1289 
1290 static int lynx_10g_probe(struct platform_device *pdev)
1291 {
1292 	return lynx_probe(pdev, of_device_get_match_data(&pdev->dev),
1293 			  &lynx_10g_ops);
1294 }
1295 
1296 static const struct of_device_id lynx_10g_of_match_table[] = {
1297 	{ .compatible = "fsl,ls1028a-serdes", .data = &lynx_info_ls1028a },
1298 	{ .compatible = "fsl,ls1046a-serdes1", .data = &lynx_info_ls1046a_serdes1 },
1299 	{ .compatible = "fsl,ls1046a-serdes2", .data = &lynx_info_ls1046a_serdes2 },
1300 	{ .compatible = "fsl,ls1088a-serdes1", .data = &lynx_info_ls1088a_serdes1 },
1301 	{ .compatible = "fsl,ls2088a-serdes1", .data = &lynx_info_ls2088a_serdes1 },
1302 	{ .compatible = "fsl,ls2088a-serdes2", .data = &lynx_info_ls2088a_serdes2 },
1303 	{}
1304 };
1305 MODULE_DEVICE_TABLE(of, lynx_10g_of_match_table);
1306 
1307 static struct platform_driver lynx_10g_driver = {
1308 	.probe	= lynx_10g_probe,
1309 	.remove	= lynx_remove,
1310 	.driver	= {
1311 		.name = "lynx-10g",
1312 		.of_match_table = lynx_10g_of_match_table,
1313 	},
1314 };
1315 module_platform_driver(lynx_10g_driver);
1316 
1317 MODULE_IMPORT_NS("PHY_FSL_LYNX");
1318 MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
1319 MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
1320 MODULE_DESCRIPTION("Lynx 10G SerDes PHY driver for Layerscape SoCs");
1321 MODULE_LICENSE("GPL");
1322