1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) 2021-2022 NXP. */
4 #include <linux/module.h>
7 #include <linux/phy/phy.h>
8 #include <linux/platform_device.h>
9 #include <linux/workqueue.h>
11 #define LYNX_28G_NUM_LANE 8
12 #define LYNX_28G_NUM_PLL 2
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
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
24 #define LYNX_28G_LNa_PCC_OFFSET(lane) (4 * (LYNX_28G_NUM_LANE - (lane->id) - 1))
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)
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
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
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
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)
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)
71 #define LYNX_28G_LNaTECR0(lane) (0x800 + (lane) * 0x100 + 0x30)
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)
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)
91 #define LYNX_28G_LNaRGCR1(lane) (0x800 + (lane) * 0x100 + 0x48)
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)
97 #define LYNX_28G_LNaRSCCR0(lane) (0x800 + (lane) * 0x100 + 0x74)
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
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)
109 struct lynx_28g_priv
;
111 struct lynx_28g_pll
{
112 struct lynx_28g_priv
*priv
;
113 u32 rstctl
, cr0
, cr1
;
115 DECLARE_PHY_INTERFACE_MASK(supported
);
118 struct lynx_28g_lane
{
119 struct lynx_28g_priv
*priv
;
124 phy_interface_t interface
;
127 struct lynx_28g_priv
{
130 /* Serialize concurrent access to registers shared between lanes,
134 struct lynx_28g_pll pll
[LYNX_28G_NUM_PLL
];
135 struct lynx_28g_lane lane
[LYNX_28G_NUM_LANE
];
137 struct delayed_work cdr_check
;
140 static void lynx_28g_rmw(struct lynx_28g_priv
*priv
, unsigned long off
,
143 void __iomem
*reg
= priv
->base
+ off
;
146 orig
= ioread32(reg
);
152 #define lynx_28g_lane_rmw(lane, reg, val, mask) \
153 lynx_28g_rmw((lane)->priv, LYNX_28G_##reg(lane->id), \
154 LYNX_28G_##reg##_##val, LYNX_28G_##reg##_##mask)
155 #define lynx_28g_lane_read(lane, reg) \
156 ioread32((lane)->priv->base + LYNX_28G_##reg((lane)->id))
157 #define lynx_28g_pll_read(pll, reg) \
158 ioread32((pll)->priv->base + LYNX_28G_##reg((pll)->id))
160 static bool lynx_28g_supports_interface(struct lynx_28g_priv
*priv
, int intf
)
164 for (i
= 0; i
< LYNX_28G_NUM_PLL
; i
++) {
165 if (LYNX_28G_PLLnRSTCTL_DIS(priv
->pll
[i
].rstctl
))
168 if (test_bit(intf
, priv
->pll
[i
].supported
))
175 static struct lynx_28g_pll
*lynx_28g_pll_get(struct lynx_28g_priv
*priv
,
176 phy_interface_t intf
)
178 struct lynx_28g_pll
*pll
;
181 for (i
= 0; i
< LYNX_28G_NUM_PLL
; i
++) {
184 if (LYNX_28G_PLLnRSTCTL_DIS(pll
->rstctl
))
187 if (test_bit(intf
, pll
->supported
))
194 static void lynx_28g_lane_set_nrate(struct lynx_28g_lane
*lane
,
195 struct lynx_28g_pll
*pll
,
196 phy_interface_t intf
)
198 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll
->cr1
)) {
199 case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO
:
200 case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO
:
202 case PHY_INTERFACE_MODE_SGMII
:
203 case PHY_INTERFACE_MODE_1000BASEX
:
204 lynx_28g_lane_rmw(lane
, LNaTGCR0
, N_RATE_QUARTER
, N_RATE_MSK
);
205 lynx_28g_lane_rmw(lane
, LNaRGCR0
, N_RATE_QUARTER
, N_RATE_MSK
);
211 case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO
:
213 case PHY_INTERFACE_MODE_10GBASER
:
214 case PHY_INTERFACE_MODE_USXGMII
:
215 lynx_28g_lane_rmw(lane
, LNaTGCR0
, N_RATE_FULL
, N_RATE_MSK
);
216 lynx_28g_lane_rmw(lane
, LNaRGCR0
, N_RATE_FULL
, N_RATE_MSK
);
227 static void lynx_28g_lane_set_pll(struct lynx_28g_lane
*lane
,
228 struct lynx_28g_pll
*pll
)
231 lynx_28g_lane_rmw(lane
, LNaTGCR0
, USE_PLLF
, USE_PLL_MSK
);
232 lynx_28g_lane_rmw(lane
, LNaRGCR0
, USE_PLLF
, USE_PLL_MSK
);
234 lynx_28g_lane_rmw(lane
, LNaTGCR0
, USE_PLLS
, USE_PLL_MSK
);
235 lynx_28g_lane_rmw(lane
, LNaRGCR0
, USE_PLLS
, USE_PLL_MSK
);
239 static void lynx_28g_cleanup_lane(struct lynx_28g_lane
*lane
)
241 u32 lane_offset
= LYNX_28G_LNa_PCC_OFFSET(lane
);
242 struct lynx_28g_priv
*priv
= lane
->priv
;
244 /* Cleanup the protocol configuration registers of the current protocol */
245 switch (lane
->interface
) {
246 case PHY_INTERFACE_MODE_10GBASER
:
247 lynx_28g_rmw(priv
, LYNX_28G_PCCC
,
248 LYNX_28G_PCCC_SXGMII_DIS
<< lane_offset
,
249 GENMASK(3, 0) << lane_offset
);
251 case PHY_INTERFACE_MODE_SGMII
:
252 case PHY_INTERFACE_MODE_1000BASEX
:
253 lynx_28g_rmw(priv
, LYNX_28G_PCC8
,
254 LYNX_28G_PCC8_SGMII_DIS
<< lane_offset
,
255 GENMASK(3, 0) << lane_offset
);
262 static void lynx_28g_lane_set_sgmii(struct lynx_28g_lane
*lane
)
264 u32 lane_offset
= LYNX_28G_LNa_PCC_OFFSET(lane
);
265 struct lynx_28g_priv
*priv
= lane
->priv
;
266 struct lynx_28g_pll
*pll
;
268 lynx_28g_cleanup_lane(lane
);
270 /* Setup the lane to run in SGMII */
271 lynx_28g_rmw(priv
, LYNX_28G_PCC8
,
272 LYNX_28G_PCC8_SGMII
<< lane_offset
,
273 GENMASK(3, 0) << lane_offset
);
275 /* Setup the protocol select and SerDes parallel interface width */
276 lynx_28g_lane_rmw(lane
, LNaGCR0
, PROTO_SEL_SGMII
, PROTO_SEL_MSK
);
277 lynx_28g_lane_rmw(lane
, LNaGCR0
, IF_WIDTH_10_BIT
, IF_WIDTH_MSK
);
279 /* Switch to the PLL that works with this interface type */
280 pll
= lynx_28g_pll_get(priv
, PHY_INTERFACE_MODE_SGMII
);
281 lynx_28g_lane_set_pll(lane
, pll
);
283 /* Choose the portion of clock net to be used on this lane */
284 lynx_28g_lane_set_nrate(lane
, pll
, PHY_INTERFACE_MODE_SGMII
);
286 /* Enable the SGMII PCS */
287 lynx_28g_lane_rmw(lane
, SGMIIaCR1
, SGPCS_EN
, SGPCS_MSK
);
289 /* Configure the appropriate equalization parameters for the protocol */
290 iowrite32(0x00808006, priv
->base
+ LYNX_28G_LNaTECR0(lane
->id
));
291 iowrite32(0x04310000, priv
->base
+ LYNX_28G_LNaRGCR1(lane
->id
));
292 iowrite32(0x9f800000, priv
->base
+ LYNX_28G_LNaRECR0(lane
->id
));
293 iowrite32(0x001f0000, priv
->base
+ LYNX_28G_LNaRECR1(lane
->id
));
294 iowrite32(0x00000000, priv
->base
+ LYNX_28G_LNaRECR2(lane
->id
));
295 iowrite32(0x00000000, priv
->base
+ LYNX_28G_LNaRSCCR0(lane
->id
));
298 static void lynx_28g_lane_set_10gbaser(struct lynx_28g_lane
*lane
)
300 u32 lane_offset
= LYNX_28G_LNa_PCC_OFFSET(lane
);
301 struct lynx_28g_priv
*priv
= lane
->priv
;
302 struct lynx_28g_pll
*pll
;
304 lynx_28g_cleanup_lane(lane
);
306 /* Enable the SXGMII lane */
307 lynx_28g_rmw(priv
, LYNX_28G_PCCC
,
308 LYNX_28G_PCCC_10GBASER
<< lane_offset
,
309 GENMASK(3, 0) << lane_offset
);
311 /* Setup the protocol select and SerDes parallel interface width */
312 lynx_28g_lane_rmw(lane
, LNaGCR0
, PROTO_SEL_XFI
, PROTO_SEL_MSK
);
313 lynx_28g_lane_rmw(lane
, LNaGCR0
, IF_WIDTH_20_BIT
, IF_WIDTH_MSK
);
315 /* Switch to the PLL that works with this interface type */
316 pll
= lynx_28g_pll_get(priv
, PHY_INTERFACE_MODE_10GBASER
);
317 lynx_28g_lane_set_pll(lane
, pll
);
319 /* Choose the portion of clock net to be used on this lane */
320 lynx_28g_lane_set_nrate(lane
, pll
, PHY_INTERFACE_MODE_10GBASER
);
322 /* Disable the SGMII PCS */
323 lynx_28g_lane_rmw(lane
, SGMIIaCR1
, SGPCS_DIS
, SGPCS_MSK
);
325 /* Configure the appropriate equalization parameters for the protocol */
326 iowrite32(0x10808307, priv
->base
+ LYNX_28G_LNaTECR0(lane
->id
));
327 iowrite32(0x10000000, priv
->base
+ LYNX_28G_LNaRGCR1(lane
->id
));
328 iowrite32(0x00000000, priv
->base
+ LYNX_28G_LNaRECR0(lane
->id
));
329 iowrite32(0x001f0000, priv
->base
+ LYNX_28G_LNaRECR1(lane
->id
));
330 iowrite32(0x81000020, priv
->base
+ LYNX_28G_LNaRECR2(lane
->id
));
331 iowrite32(0x00002000, priv
->base
+ LYNX_28G_LNaRSCCR0(lane
->id
));
334 static int lynx_28g_power_off(struct phy
*phy
)
336 struct lynx_28g_lane
*lane
= phy_get_drvdata(phy
);
337 u32 trstctl
, rrstctl
;
339 if (!lane
->powered_up
)
342 /* Issue a halt request */
343 lynx_28g_lane_rmw(lane
, LNaTRSTCTL
, HLT_REQ
, HLT_REQ
);
344 lynx_28g_lane_rmw(lane
, LNaRRSTCTL
, HLT_REQ
, HLT_REQ
);
346 /* Wait until the halting process is complete */
348 trstctl
= lynx_28g_lane_read(lane
, LNaTRSTCTL
);
349 rrstctl
= lynx_28g_lane_read(lane
, LNaRRSTCTL
);
350 } while ((trstctl
& LYNX_28G_LNaTRSTCTL_HLT_REQ
) ||
351 (rrstctl
& LYNX_28G_LNaRRSTCTL_HLT_REQ
));
353 lane
->powered_up
= false;
358 static int lynx_28g_power_on(struct phy
*phy
)
360 struct lynx_28g_lane
*lane
= phy_get_drvdata(phy
);
361 u32 trstctl
, rrstctl
;
363 if (lane
->powered_up
)
366 /* Issue a reset request on the lane */
367 lynx_28g_lane_rmw(lane
, LNaTRSTCTL
, RST_REQ
, RST_REQ
);
368 lynx_28g_lane_rmw(lane
, LNaRRSTCTL
, RST_REQ
, RST_REQ
);
370 /* Wait until the reset sequence is completed */
372 trstctl
= lynx_28g_lane_read(lane
, LNaTRSTCTL
);
373 rrstctl
= lynx_28g_lane_read(lane
, LNaRRSTCTL
);
374 } while (!(trstctl
& LYNX_28G_LNaTRSTCTL_RST_DONE
) ||
375 !(rrstctl
& LYNX_28G_LNaRRSTCTL_RST_DONE
));
377 lane
->powered_up
= true;
382 static int lynx_28g_set_mode(struct phy
*phy
, enum phy_mode mode
, int submode
)
384 struct lynx_28g_lane
*lane
= phy_get_drvdata(phy
);
385 struct lynx_28g_priv
*priv
= lane
->priv
;
386 int powered_up
= lane
->powered_up
;
389 if (mode
!= PHY_MODE_ETHERNET
)
392 if (lane
->interface
== PHY_INTERFACE_MODE_NA
)
395 if (!lynx_28g_supports_interface(priv
, submode
))
398 /* If the lane is powered up, put the lane into the halt state while
399 * the reconfiguration is being done.
402 lynx_28g_power_off(phy
);
404 spin_lock(&priv
->pcc_lock
);
407 case PHY_INTERFACE_MODE_SGMII
:
408 case PHY_INTERFACE_MODE_1000BASEX
:
409 lynx_28g_lane_set_sgmii(lane
);
411 case PHY_INTERFACE_MODE_10GBASER
:
412 lynx_28g_lane_set_10gbaser(lane
);
419 lane
->interface
= submode
;
422 spin_unlock(&priv
->pcc_lock
);
424 /* Power up the lane if necessary */
426 lynx_28g_power_on(phy
);
431 static int lynx_28g_validate(struct phy
*phy
, enum phy_mode mode
, int submode
,
432 union phy_configure_opts
*opts __always_unused
)
434 struct lynx_28g_lane
*lane
= phy_get_drvdata(phy
);
435 struct lynx_28g_priv
*priv
= lane
->priv
;
437 if (mode
!= PHY_MODE_ETHERNET
)
440 if (!lynx_28g_supports_interface(priv
, submode
))
446 static int lynx_28g_init(struct phy
*phy
)
448 struct lynx_28g_lane
*lane
= phy_get_drvdata(phy
);
450 /* Mark the fact that the lane was init */
453 /* SerDes lanes are powered on at boot time. Any lane that is managed
454 * by this driver will get powered down at init time aka at dpaa2-eth
457 lane
->powered_up
= true;
458 lynx_28g_power_off(phy
);
463 static const struct phy_ops lynx_28g_ops
= {
464 .init
= lynx_28g_init
,
465 .power_on
= lynx_28g_power_on
,
466 .power_off
= lynx_28g_power_off
,
467 .set_mode
= lynx_28g_set_mode
,
468 .validate
= lynx_28g_validate
,
469 .owner
= THIS_MODULE
,
472 static void lynx_28g_pll_read_configuration(struct lynx_28g_priv
*priv
)
474 struct lynx_28g_pll
*pll
;
477 for (i
= 0; i
< LYNX_28G_NUM_PLL
; i
++) {
482 pll
->rstctl
= lynx_28g_pll_read(pll
, PLLnRSTCTL
);
483 pll
->cr0
= lynx_28g_pll_read(pll
, PLLnCR0
);
484 pll
->cr1
= lynx_28g_pll_read(pll
, PLLnCR1
);
486 if (LYNX_28G_PLLnRSTCTL_DIS(pll
->rstctl
))
489 switch (LYNX_28G_PLLnCR1_FRATE_SEL(pll
->cr1
)) {
490 case LYNX_28G_PLLnCR1_FRATE_5G_10GVCO
:
491 case LYNX_28G_PLLnCR1_FRATE_5G_25GVCO
:
493 __set_bit(PHY_INTERFACE_MODE_1000BASEX
, pll
->supported
);
494 __set_bit(PHY_INTERFACE_MODE_SGMII
, pll
->supported
);
496 case LYNX_28G_PLLnCR1_FRATE_10G_20GVCO
:
497 /* 10.3125GHz clock net */
498 __set_bit(PHY_INTERFACE_MODE_10GBASER
, pll
->supported
);
501 /* 6GHz, 12.890625GHz, 8GHz */
507 #define work_to_lynx(w) container_of((w), struct lynx_28g_priv, cdr_check.work)
509 static void lynx_28g_cdr_lock_check(struct work_struct
*work
)
511 struct lynx_28g_priv
*priv
= work_to_lynx(work
);
512 struct lynx_28g_lane
*lane
;
516 for (i
= 0; i
< LYNX_28G_NUM_LANE
; i
++) {
517 lane
= &priv
->lane
[i
];
519 mutex_lock(&lane
->phy
->mutex
);
521 if (!lane
->init
|| !lane
->powered_up
) {
522 mutex_unlock(&lane
->phy
->mutex
);
526 rrstctl
= lynx_28g_lane_read(lane
, LNaRRSTCTL
);
527 if (!(rrstctl
& LYNX_28G_LNaRRSTCTL_CDR_LOCK
)) {
528 lynx_28g_lane_rmw(lane
, LNaRRSTCTL
, RST_REQ
, RST_REQ
);
530 rrstctl
= lynx_28g_lane_read(lane
, LNaRRSTCTL
);
531 } while (!(rrstctl
& LYNX_28G_LNaRRSTCTL_RST_DONE
));
534 mutex_unlock(&lane
->phy
->mutex
);
536 queue_delayed_work(system_power_efficient_wq
, &priv
->cdr_check
,
537 msecs_to_jiffies(1000));
540 static void lynx_28g_lane_read_configuration(struct lynx_28g_lane
*lane
)
544 pss
= lynx_28g_lane_read(lane
, LNaPSS
);
545 protocol
= LYNX_28G_LNaPSS_TYPE(pss
);
547 case LYNX_28G_LNaPSS_TYPE_SGMII
:
548 lane
->interface
= PHY_INTERFACE_MODE_SGMII
;
550 case LYNX_28G_LNaPSS_TYPE_XFI
:
551 lane
->interface
= PHY_INTERFACE_MODE_10GBASER
;
554 lane
->interface
= PHY_INTERFACE_MODE_NA
;
558 static struct phy
*lynx_28g_xlate(struct device
*dev
,
559 const struct of_phandle_args
*args
)
561 struct lynx_28g_priv
*priv
= dev_get_drvdata(dev
);
562 int idx
= args
->args
[0];
564 if (WARN_ON(idx
>= LYNX_28G_NUM_LANE
))
565 return ERR_PTR(-EINVAL
);
567 return priv
->lane
[idx
].phy
;
570 static int lynx_28g_probe(struct platform_device
*pdev
)
572 struct device
*dev
= &pdev
->dev
;
573 struct phy_provider
*provider
;
574 struct lynx_28g_priv
*priv
;
577 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
580 priv
->dev
= &pdev
->dev
;
582 priv
->base
= devm_platform_ioremap_resource(pdev
, 0);
583 if (IS_ERR(priv
->base
))
584 return PTR_ERR(priv
->base
);
586 lynx_28g_pll_read_configuration(priv
);
588 for (i
= 0; i
< LYNX_28G_NUM_LANE
; i
++) {
589 struct lynx_28g_lane
*lane
= &priv
->lane
[i
];
592 memset(lane
, 0, sizeof(*lane
));
594 phy
= devm_phy_create(&pdev
->dev
, NULL
, &lynx_28g_ops
);
601 phy_set_drvdata(phy
, lane
);
602 lynx_28g_lane_read_configuration(lane
);
605 dev_set_drvdata(dev
, priv
);
607 spin_lock_init(&priv
->pcc_lock
);
608 INIT_DELAYED_WORK(&priv
->cdr_check
, lynx_28g_cdr_lock_check
);
610 queue_delayed_work(system_power_efficient_wq
, &priv
->cdr_check
,
611 msecs_to_jiffies(1000));
613 dev_set_drvdata(&pdev
->dev
, priv
);
614 provider
= devm_of_phy_provider_register(&pdev
->dev
, lynx_28g_xlate
);
616 return PTR_ERR_OR_ZERO(provider
);
619 static void lynx_28g_remove(struct platform_device
*pdev
)
621 struct device
*dev
= &pdev
->dev
;
622 struct lynx_28g_priv
*priv
= dev_get_drvdata(dev
);
624 cancel_delayed_work_sync(&priv
->cdr_check
);
627 static const struct of_device_id lynx_28g_of_match_table
[] = {
628 { .compatible
= "fsl,lynx-28g" },
631 MODULE_DEVICE_TABLE(of
, lynx_28g_of_match_table
);
633 static struct platform_driver lynx_28g_driver
= {
634 .probe
= lynx_28g_probe
,
635 .remove
= lynx_28g_remove
,
638 .of_match_table
= lynx_28g_of_match_table
,
641 module_platform_driver(lynx_28g_driver
);
643 MODULE_AUTHOR("Ioana Ciornei <ioana.ciornei@nxp.com>");
644 MODULE_DESCRIPTION("Lynx 28G SerDes PHY driver for Layerscape SoCs");
645 MODULE_LICENSE("GPL v2");