xref: /linux/drivers/phy/freescale/phy-fsl-lynx-28g.c (revision 9025cebf12d1763de36d5e09e2b0a1e4f9b13b28)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021-2022 NXP. */
3 
4 #include <linux/module.h>
5 #include <linux/phy.h>
6 #include <linux/phy/phy.h>
7 #include <linux/platform_device.h>
8 #include <linux/workqueue.h>
9 
10 #define LYNX_28G_NUM_LANE			8
11 #define LYNX_28G_NUM_PLL			2
12 
13 /* General registers per SerDes block */
14 #define LYNX_28G_PCC8				0x10a0
15 #define LYNX_28G_PCC8_SGMII			0x1
16 #define LYNX_28G_PCC8_SGMII_DIS			0x0
17 
18 #define LYNX_28G_PCCC				0x10b0
19 #define LYNX_28G_PCCC_10GBASER			0x9
20 #define LYNX_28G_PCCC_USXGMII			0x1
21 #define LYNX_28G_PCCC_SXGMII_DIS		0x0
22 
23 #define LYNX_28G_LNa_PCC_OFFSET(lane)		(4 * (LYNX_28G_NUM_LANE - (lane->id) - 1))
24 
25 /* Per PLL registers */
26 #define LYNX_28G_PLLnRSTCTL(pll)		(0x400 + (pll) * 0x100 + 0x0)
27 #define LYNX_28G_PLLnRSTCTL_DIS(rstctl)		(((rstctl) & BIT(24)) >> 24)
28 #define LYNX_28G_PLLnRSTCTL_LOCK(rstctl)	(((rstctl) & BIT(23)) >> 23)
29 
30 #define LYNX_28G_PLLnCR0(pll)			(0x400 + (pll) * 0x100 + 0x4)
31 #define LYNX_28G_PLLnCR0_REFCLK_SEL(cr0)	(((cr0) & GENMASK(20, 16)))
32 #define LYNX_28G_PLLnCR0_REFCLK_SEL_100MHZ	0x0
33 #define LYNX_28G_PLLnCR0_REFCLK_SEL_125MHZ	0x10000
34 #define LYNX_28G_PLLnCR0_REFCLK_SEL_156MHZ	0x20000
35 #define LYNX_28G_PLLnCR0_REFCLK_SEL_150MHZ	0x30000
36 #define LYNX_28G_PLLnCR0_REFCLK_SEL_161MHZ	0x40000
37 
38 #define LYNX_28G_PLLnCR1(pll)			(0x400 + (pll) * 0x100 + 0x8)
39 #define LYNX_28G_PLLnCR1_FRATE_SEL(cr1)		(((cr1) & GENMASK(28, 24)))
40 #define LYNX_28G_PLLnCR1_FRATE_5G_10GVCO	0x0
41 #define LYNX_28G_PLLnCR1_FRATE_5G_25GVCO	0x10000000
42 #define LYNX_28G_PLLnCR1_FRATE_10G_20GVCO	0x6000000
43 
44 /* Per SerDes lane registers */
45 /* Lane a General Control Register */
46 #define LYNX_28G_LNaGCR0(lane)			(0x800 + (lane) * 0x100 + 0x0)
47 #define LYNX_28G_LNaGCR0_PROTO_SEL_MSK		GENMASK(7, 3)
48 #define LYNX_28G_LNaGCR0_PROTO_SEL_SGMII	0x8
49 #define LYNX_28G_LNaGCR0_PROTO_SEL_XFI		0x50
50 #define LYNX_28G_LNaGCR0_IF_WIDTH_MSK		GENMASK(2, 0)
51 #define LYNX_28G_LNaGCR0_IF_WIDTH_10_BIT	0x0
52 #define LYNX_28G_LNaGCR0_IF_WIDTH_20_BIT	0x2
53 
54 /* Lane a Tx Reset Control Register */
55 #define LYNX_28G_LNaTRSTCTL(lane)		(0x800 + (lane) * 0x100 + 0x20)
56 #define LYNX_28G_LNaTRSTCTL_HLT_REQ		BIT(27)
57 #define LYNX_28G_LNaTRSTCTL_RST_DONE		BIT(30)
58 #define LYNX_28G_LNaTRSTCTL_RST_REQ		BIT(31)
59 
60 /* Lane a Tx General Control Register */
61 #define LYNX_28G_LNaTGCR0(lane)			(0x800 + (lane) * 0x100 + 0x24)
62 #define LYNX_28G_LNaTGCR0_USE_PLLF		0x0
63 #define LYNX_28G_LNaTGCR0_USE_PLLS		BIT(28)
64 #define LYNX_28G_LNaTGCR0_USE_PLL_MSK		BIT(28)
65 #define LYNX_28G_LNaTGCR0_N_RATE_FULL		0x0
66 #define LYNX_28G_LNaTGCR0_N_RATE_HALF		0x1000000
67 #define LYNX_28G_LNaTGCR0_N_RATE_QUARTER	0x2000000
68 #define LYNX_28G_LNaTGCR0_N_RATE_MSK		GENMASK(26, 24)
69 
70 #define LYNX_28G_LNaTECR0(lane)			(0x800 + (lane) * 0x100 + 0x30)
71 
72 /* Lane a Rx Reset Control Register */
73 #define LYNX_28G_LNaRRSTCTL(lane)		(0x800 + (lane) * 0x100 + 0x40)
74 #define LYNX_28G_LNaRRSTCTL_HLT_REQ		BIT(27)
75 #define LYNX_28G_LNaRRSTCTL_RST_DONE		BIT(30)
76 #define LYNX_28G_LNaRRSTCTL_RST_REQ		BIT(31)
77 #define LYNX_28G_LNaRRSTCTL_CDR_LOCK		BIT(12)
78 
79 /* Lane a Rx General Control Register */
80 #define LYNX_28G_LNaRGCR0(lane)			(0x800 + (lane) * 0x100 + 0x44)
81 #define LYNX_28G_LNaRGCR0_USE_PLLF		0x0
82 #define LYNX_28G_LNaRGCR0_USE_PLLS		BIT(28)
83 #define LYNX_28G_LNaRGCR0_USE_PLL_MSK		BIT(28)
84 #define LYNX_28G_LNaRGCR0_N_RATE_MSK		GENMASK(26, 24)
85 #define LYNX_28G_LNaRGCR0_N_RATE_FULL		0x0
86 #define LYNX_28G_LNaRGCR0_N_RATE_HALF		0x1000000
87 #define LYNX_28G_LNaRGCR0_N_RATE_QUARTER	0x2000000
88 #define LYNX_28G_LNaRGCR0_N_RATE_MSK		GENMASK(26, 24)
89 
90 #define LYNX_28G_LNaRGCR1(lane)			(0x800 + (lane) * 0x100 + 0x48)
91 
92 #define LYNX_28G_LNaRECR0(lane)			(0x800 + (lane) * 0x100 + 0x50)
93 #define LYNX_28G_LNaRECR1(lane)			(0x800 + (lane) * 0x100 + 0x54)
94 #define LYNX_28G_LNaRECR2(lane)			(0x800 + (lane) * 0x100 + 0x58)
95 
96 #define LYNX_28G_LNaRSCCR0(lane)		(0x800 + (lane) * 0x100 + 0x74)
97 
98 #define LYNX_28G_LNaPSS(lane)			(0x1000 + (lane) * 0x4)
99 #define LYNX_28G_LNaPSS_TYPE(pss)		(((pss) & GENMASK(30, 24)) >> 24)
100 #define LYNX_28G_LNaPSS_TYPE_SGMII		0x4
101 #define LYNX_28G_LNaPSS_TYPE_XFI		0x28
102 
103 #define LYNX_28G_SGMIIaCR1(lane)		(0x1804 + (lane) * 0x10)
104 #define LYNX_28G_SGMIIaCR1_SGPCS_EN		BIT(11)
105 #define LYNX_28G_SGMIIaCR1_SGPCS_DIS		0x0
106 #define LYNX_28G_SGMIIaCR1_SGPCS_MSK		BIT(11)
107 
108 struct lynx_28g_priv;
109 
110 struct lynx_28g_pll {
111 	struct lynx_28g_priv *priv;
112 	u32 rstctl, cr0, cr1;
113 	int id;
114 	DECLARE_PHY_INTERFACE_MASK(supported);
115 };
116 
117 struct lynx_28g_lane {
118 	struct lynx_28g_priv *priv;
119 	struct phy *phy;
120 	bool powered_up;
121 	bool init;
122 	unsigned int id;
123 	phy_interface_t interface;
124 };
125 
126 struct lynx_28g_priv {
127 	void __iomem *base;
128 	struct device *dev;
129 	struct lynx_28g_pll pll[LYNX_28G_NUM_PLL];
130 	struct lynx_28g_lane lane[LYNX_28G_NUM_LANE];
131 
132 	struct delayed_work cdr_check;
133 };
134 
135 static void lynx_28g_rmw(struct lynx_28g_priv *priv, unsigned long off,
136 			 u32 val, u32 mask)
137 {
138 	void __iomem *reg = priv->base + off;
139 	u32 orig, tmp;
140 
141 	orig = ioread32(reg);
142 	tmp = orig & ~mask;
143 	tmp |= val;
144 	iowrite32(tmp, reg);
145 }
146 
147 #define lynx_28g_lane_rmw(lane, reg, val, mask)	\
148 	lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
149 		     LYNX_28G_##reg##_##val, LYNX_28G_##reg##_##mask)
150 #define lynx_28g_lane_read(lane, reg)			\
151 	ioread32((lane)->priv->base + LYNX_28G_##reg((lane)->id))
152 #define lynx_28g_pll_read(pll, reg)			\
153 	ioread32((pll)->priv->base + LYNX_28G_##reg((pll)->id))
154 
155 static bool lynx_28g_supports_interface(struct lynx_28g_priv *priv, int intf)
156 {
157 	int i;
158 
159 	for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
160 		if (LYNX_28G_PLLnRSTCTL_DIS(priv->pll[i].rstctl))
161 			continue;
162 
163 		if (test_bit(intf, priv->pll[i].supported))
164 			return true;
165 	}
166 
167 	return false;
168 }
169 
170 static struct lynx_28g_pll *lynx_28g_pll_get(struct lynx_28g_priv *priv,
171 					     phy_interface_t intf)
172 {
173 	struct lynx_28g_pll *pll;
174 	int i;
175 
176 	for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
177 		pll = &priv->pll[i];
178 
179 		if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
180 			continue;
181 
182 		if (test_bit(intf, pll->supported))
183 			return pll;
184 	}
185 
186 	return NULL;
187 }
188 
189 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane *lane,
190 				    struct lynx_28g_pll *pll,
191 				    phy_interface_t intf)
192 {
193 	switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
194 	case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
195 	case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
196 		switch (intf) {
197 		case PHY_INTERFACE_MODE_SGMII:
198 		case PHY_INTERFACE_MODE_1000BASEX:
199 			lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_QUARTER, N_RATE_MSK);
200 			lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_QUARTER, N_RATE_MSK);
201 			break;
202 		default:
203 			break;
204 		}
205 		break;
206 	case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
207 		switch (intf) {
208 		case PHY_INTERFACE_MODE_10GBASER:
209 		case PHY_INTERFACE_MODE_USXGMII:
210 			lynx_28g_lane_rmw(lane, LNaTGCR0, N_RATE_FULL, N_RATE_MSK);
211 			lynx_28g_lane_rmw(lane, LNaRGCR0, N_RATE_FULL, N_RATE_MSK);
212 			break;
213 		default:
214 			break;
215 		}
216 		break;
217 	default:
218 		break;
219 	}
220 }
221 
222 static void lynx_28g_lane_set_pll(struct lynx_28g_lane *lane,
223 				  struct lynx_28g_pll *pll)
224 {
225 	if (pll->id == 0) {
226 		lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLF, USE_PLL_MSK);
227 		lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLF, USE_PLL_MSK);
228 	} else {
229 		lynx_28g_lane_rmw(lane, LNaTGCR0, USE_PLLS, USE_PLL_MSK);
230 		lynx_28g_lane_rmw(lane, LNaRGCR0, USE_PLLS, USE_PLL_MSK);
231 	}
232 }
233 
234 static void lynx_28g_cleanup_lane(struct lynx_28g_lane *lane)
235 {
236 	u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
237 	struct lynx_28g_priv *priv = lane->priv;
238 
239 	/* Cleanup the protocol configuration registers of the current protocol */
240 	switch (lane->interface) {
241 	case PHY_INTERFACE_MODE_10GBASER:
242 		lynx_28g_rmw(priv, LYNX_28G_PCCC,
243 			     LYNX_28G_PCCC_SXGMII_DIS << lane_offset,
244 			     GENMASK(3, 0) << lane_offset);
245 		break;
246 	case PHY_INTERFACE_MODE_SGMII:
247 	case PHY_INTERFACE_MODE_1000BASEX:
248 		lynx_28g_rmw(priv, LYNX_28G_PCC8,
249 			     LYNX_28G_PCC8_SGMII_DIS << lane_offset,
250 			     GENMASK(3, 0) << lane_offset);
251 		break;
252 	default:
253 		break;
254 	}
255 }
256 
257 static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane *lane)
258 {
259 	u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
260 	struct lynx_28g_priv *priv = lane->priv;
261 	struct lynx_28g_pll *pll;
262 
263 	lynx_28g_cleanup_lane(lane);
264 
265 	/* Setup the lane to run in SGMII */
266 	lynx_28g_rmw(priv, LYNX_28G_PCC8,
267 		     LYNX_28G_PCC8_SGMII << lane_offset,
268 		     GENMASK(3, 0) << lane_offset);
269 
270 	/* Setup the protocol select and SerDes parallel interface width */
271 	lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_SGMII, PROTO_SEL_MSK);
272 	lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_10_BIT, IF_WIDTH_MSK);
273 
274 	/* Switch to the PLL that works with this interface type */
275 	pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_SGMII);
276 	lynx_28g_lane_set_pll(lane, pll);
277 
278 	/* Choose the portion of clock net to be used on this lane */
279 	lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_SGMII);
280 
281 	/* Enable the SGMII PCS */
282 	lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_EN, SGPCS_MSK);
283 
284 	/* Configure the appropriate equalization parameters for the protocol */
285 	iowrite32(0x00808006, priv->base + LYNX_28G_LNaTECR0(lane->id));
286 	iowrite32(0x04310000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
287 	iowrite32(0x9f800000, priv->base + LYNX_28G_LNaRECR0(lane->id));
288 	iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
289 	iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR2(lane->id));
290 	iowrite32(0x00000000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
291 }
292 
293 static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane *lane)
294 {
295 	u32 lane_offset = LYNX_28G_LNa_PCC_OFFSET(lane);
296 	struct lynx_28g_priv *priv = lane->priv;
297 	struct lynx_28g_pll *pll;
298 
299 	lynx_28g_cleanup_lane(lane);
300 
301 	/* Enable the SXGMII lane */
302 	lynx_28g_rmw(priv, LYNX_28G_PCCC,
303 		     LYNX_28G_PCCC_10GBASER << lane_offset,
304 		     GENMASK(3, 0) << lane_offset);
305 
306 	/* Setup the protocol select and SerDes parallel interface width */
307 	lynx_28g_lane_rmw(lane, LNaGCR0, PROTO_SEL_XFI, PROTO_SEL_MSK);
308 	lynx_28g_lane_rmw(lane, LNaGCR0, IF_WIDTH_20_BIT, IF_WIDTH_MSK);
309 
310 	/* Switch to the PLL that works with this interface type */
311 	pll = lynx_28g_pll_get(priv, PHY_INTERFACE_MODE_10GBASER);
312 	lynx_28g_lane_set_pll(lane, pll);
313 
314 	/* Choose the portion of clock net to be used on this lane */
315 	lynx_28g_lane_set_nrate(lane, pll, PHY_INTERFACE_MODE_10GBASER);
316 
317 	/* Disable the SGMII PCS */
318 	lynx_28g_lane_rmw(lane, SGMIIaCR1, SGPCS_DIS, SGPCS_MSK);
319 
320 	/* Configure the appropriate equalization parameters for the protocol */
321 	iowrite32(0x10808307, priv->base + LYNX_28G_LNaTECR0(lane->id));
322 	iowrite32(0x10000000, priv->base + LYNX_28G_LNaRGCR1(lane->id));
323 	iowrite32(0x00000000, priv->base + LYNX_28G_LNaRECR0(lane->id));
324 	iowrite32(0x001f0000, priv->base + LYNX_28G_LNaRECR1(lane->id));
325 	iowrite32(0x81000020, priv->base + LYNX_28G_LNaRECR2(lane->id));
326 	iowrite32(0x00002000, priv->base + LYNX_28G_LNaRSCCR0(lane->id));
327 }
328 
329 static int lynx_28g_power_off(struct phy *phy)
330 {
331 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
332 	u32 trstctl, rrstctl;
333 
334 	if (!lane->powered_up)
335 		return 0;
336 
337 	/* Issue a halt request */
338 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, HLT_REQ, HLT_REQ);
339 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, HLT_REQ, HLT_REQ);
340 
341 	/* Wait until the halting process is complete */
342 	do {
343 		trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
344 		rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
345 	} while ((trstctl & LYNX_28G_LNaTRSTCTL_HLT_REQ) ||
346 		 (rrstctl & LYNX_28G_LNaRRSTCTL_HLT_REQ));
347 
348 	lane->powered_up = false;
349 
350 	return 0;
351 }
352 
353 static int lynx_28g_power_on(struct phy *phy)
354 {
355 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
356 	u32 trstctl, rrstctl;
357 
358 	if (lane->powered_up)
359 		return 0;
360 
361 	/* Issue a reset request on the lane */
362 	lynx_28g_lane_rmw(lane, LNaTRSTCTL, RST_REQ, RST_REQ);
363 	lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
364 
365 	/* Wait until the reset sequence is completed */
366 	do {
367 		trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
368 		rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
369 	} while (!(trstctl & LYNX_28G_LNaTRSTCTL_RST_DONE) ||
370 		 !(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
371 
372 	lane->powered_up = true;
373 
374 	return 0;
375 }
376 
377 static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
378 {
379 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
380 	struct lynx_28g_priv *priv = lane->priv;
381 	int powered_up = lane->powered_up;
382 	int err = 0;
383 
384 	if (mode != PHY_MODE_ETHERNET)
385 		return -EOPNOTSUPP;
386 
387 	if (lane->interface == PHY_INTERFACE_MODE_NA)
388 		return -EOPNOTSUPP;
389 
390 	if (!lynx_28g_supports_interface(priv, submode))
391 		return -EOPNOTSUPP;
392 
393 	/* If the lane is powered up, put the lane into the halt state while
394 	 * the reconfiguration is being done.
395 	 */
396 	if (powered_up)
397 		lynx_28g_power_off(phy);
398 
399 	switch (submode) {
400 	case PHY_INTERFACE_MODE_SGMII:
401 	case PHY_INTERFACE_MODE_1000BASEX:
402 		lynx_28g_lane_set_sgmii(lane);
403 		break;
404 	case PHY_INTERFACE_MODE_10GBASER:
405 		lynx_28g_lane_set_10gbaser(lane);
406 		break;
407 	default:
408 		err = -EOPNOTSUPP;
409 		goto out;
410 	}
411 
412 	lane->interface = submode;
413 
414 out:
415 	/* Power up the lane if necessary */
416 	if (powered_up)
417 		lynx_28g_power_on(phy);
418 
419 	return err;
420 }
421 
422 static int lynx_28g_validate(struct phy *phy, enum phy_mode mode, int submode,
423 			     union phy_configure_opts *opts __always_unused)
424 {
425 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
426 	struct lynx_28g_priv *priv = lane->priv;
427 
428 	if (mode != PHY_MODE_ETHERNET)
429 		return -EOPNOTSUPP;
430 
431 	if (!lynx_28g_supports_interface(priv, submode))
432 		return -EOPNOTSUPP;
433 
434 	return 0;
435 }
436 
437 static int lynx_28g_init(struct phy *phy)
438 {
439 	struct lynx_28g_lane *lane = phy_get_drvdata(phy);
440 
441 	/* Mark the fact that the lane was init */
442 	lane->init = true;
443 
444 	/* SerDes lanes are powered on at boot time.  Any lane that is managed
445 	 * by this driver will get powered down at init time aka at dpaa2-eth
446 	 * probe time.
447 	 */
448 	lane->powered_up = true;
449 	lynx_28g_power_off(phy);
450 
451 	return 0;
452 }
453 
454 static const struct phy_ops lynx_28g_ops = {
455 	.init		= lynx_28g_init,
456 	.power_on	= lynx_28g_power_on,
457 	.power_off	= lynx_28g_power_off,
458 	.set_mode	= lynx_28g_set_mode,
459 	.validate	= lynx_28g_validate,
460 	.owner		= THIS_MODULE,
461 };
462 
463 static void lynx_28g_pll_read_configuration(struct lynx_28g_priv *priv)
464 {
465 	struct lynx_28g_pll *pll;
466 	int i;
467 
468 	for (i = 0; i < LYNX_28G_NUM_PLL; i++) {
469 		pll = &priv->pll[i];
470 		pll->priv = priv;
471 		pll->id = i;
472 
473 		pll->rstctl = lynx_28g_pll_read(pll, PLLnRSTCTL);
474 		pll->cr0 = lynx_28g_pll_read(pll, PLLnCR0);
475 		pll->cr1 = lynx_28g_pll_read(pll, PLLnCR1);
476 
477 		if (LYNX_28G_PLLnRSTCTL_DIS(pll->rstctl))
478 			continue;
479 
480 		switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll->cr1)) {
481 		case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO:
482 		case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO:
483 			/* 5GHz clock net */
484 			__set_bit(PHY_INTERFACE_MODE_1000BASEX, pll->supported);
485 			__set_bit(PHY_INTERFACE_MODE_SGMII, pll->supported);
486 			break;
487 		case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO:
488 			/* 10.3125GHz clock net */
489 			__set_bit(PHY_INTERFACE_MODE_10GBASER, pll->supported);
490 			break;
491 		default:
492 			/* 6GHz, 12.890625GHz, 8GHz */
493 			break;
494 		}
495 	}
496 }
497 
498 #define work_to_lynx(w) container_of((w), struct lynx_28g_priv, cdr_check.work)
499 
500 static void lynx_28g_cdr_lock_check(struct work_struct *work)
501 {
502 	struct lynx_28g_priv *priv = work_to_lynx(work);
503 	struct lynx_28g_lane *lane;
504 	u32 rrstctl;
505 	int i;
506 
507 	for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
508 		lane = &priv->lane[i];
509 
510 		if (!lane->init)
511 			continue;
512 
513 		if (!lane->powered_up)
514 			continue;
515 
516 		rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
517 		if (!(rrstctl & LYNX_28G_LNaRRSTCTL_CDR_LOCK)) {
518 			lynx_28g_lane_rmw(lane, LNaRRSTCTL, RST_REQ, RST_REQ);
519 			do {
520 				rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
521 			} while (!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
522 		}
523 	}
524 	queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
525 			   msecs_to_jiffies(1000));
526 }
527 
528 static void lynx_28g_lane_read_configuration(struct lynx_28g_lane *lane)
529 {
530 	u32 pss, protocol;
531 
532 	pss = lynx_28g_lane_read(lane, LNaPSS);
533 	protocol = LYNX_28G_LNaPSS_TYPE(pss);
534 	switch (protocol) {
535 	case LYNX_28G_LNaPSS_TYPE_SGMII:
536 		lane->interface = PHY_INTERFACE_MODE_SGMII;
537 		break;
538 	case LYNX_28G_LNaPSS_TYPE_XFI:
539 		lane->interface = PHY_INTERFACE_MODE_10GBASER;
540 		break;
541 	default:
542 		lane->interface = PHY_INTERFACE_MODE_NA;
543 	}
544 }
545 
546 static struct phy *lynx_28g_xlate(struct device *dev,
547 				  struct of_phandle_args *args)
548 {
549 	struct lynx_28g_priv *priv = dev_get_drvdata(dev);
550 	int idx = args->args[0];
551 
552 	if (WARN_ON(idx >= LYNX_28G_NUM_LANE))
553 		return ERR_PTR(-EINVAL);
554 
555 	return priv->lane[idx].phy;
556 }
557 
558 static int lynx_28g_probe(struct platform_device *pdev)
559 {
560 	struct device *dev = &pdev->dev;
561 	struct phy_provider *provider;
562 	struct lynx_28g_priv *priv;
563 	int i;
564 
565 	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
566 	if (!priv)
567 		return -ENOMEM;
568 	priv->dev = &pdev->dev;
569 
570 	priv->base = devm_platform_ioremap_resource(pdev, 0);
571 	if (IS_ERR(priv->base))
572 		return PTR_ERR(priv->base);
573 
574 	lynx_28g_pll_read_configuration(priv);
575 
576 	for (i = 0; i < LYNX_28G_NUM_LANE; i++) {
577 		struct lynx_28g_lane *lane = &priv->lane[i];
578 		struct phy *phy;
579 
580 		memset(lane, 0, sizeof(*lane));
581 
582 		phy = devm_phy_create(&pdev->dev, NULL, &lynx_28g_ops);
583 		if (IS_ERR(phy))
584 			return PTR_ERR(phy);
585 
586 		lane->priv = priv;
587 		lane->phy = phy;
588 		lane->id = i;
589 		phy_set_drvdata(phy, lane);
590 		lynx_28g_lane_read_configuration(lane);
591 	}
592 
593 	dev_set_drvdata(dev, priv);
594 
595 	INIT_DELAYED_WORK(&priv->cdr_check, lynx_28g_cdr_lock_check);
596 
597 	queue_delayed_work(system_power_efficient_wq, &priv->cdr_check,
598 			   msecs_to_jiffies(1000));
599 
600 	dev_set_drvdata(&pdev->dev, priv);
601 	provider = devm_of_phy_provider_register(&pdev->dev, lynx_28g_xlate);
602 
603 	return PTR_ERR_OR_ZERO(provider);
604 }
605 
606 static const struct of_device_id lynx_28g_of_match_table[] = {
607 	{ .compatible = "fsl,lynx-28g" },
608 	{ },
609 };
610 MODULE_DEVICE_TABLE(of, lynx_28g_of_match_table);
611 
612 static struct platform_driver lynx_28g_driver = {
613 	.probe	= lynx_28g_probe,
614 	.driver	= {
615 		.name = "lynx-28g",
616 		.of_match_table = lynx_28g_of_match_table,
617 	},
618 };
619 module_platform_driver(lynx_28g_driver);
620 
621 MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
622 MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");
623 MODULE_LICENSE("GPL v2");
624