powerpc/mm: Avoid calling arch_enter/leave_lazy_mmu() in set_ptes
[platform/kernel/linux-starfive.git] / drivers / phy / freescale / phy-fsl-lynx-28g.c
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");