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