181bd9c1b4e5d639d81283bce37a22635f492392
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / fsl_lsch3_serdes.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2016-2018, 2020 NXP
4  * Copyright 2014-2015 Freescale Semiconductor, Inc.
5  */
6
7 #include <common.h>
8 #include <env.h>
9 #include <log.h>
10 #include <asm/io.h>
11 #include <linux/bitops.h>
12 #include <linux/delay.h>
13 #include <linux/errno.h>
14 #include <asm/arch/fsl_serdes.h>
15 #include <asm/arch/soc.h>
16 #include <fsl-mc/ldpaa_wriop.h>
17
18 #ifdef CONFIG_SYS_FSL_SRDS_1
19 static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
20 #endif
21 #ifdef CONFIG_SYS_FSL_SRDS_2
22 static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
23 #endif
24 #ifdef CONFIG_SYS_NXP_SRDS_3
25 static u8 serdes3_prtcl_map[SERDES_PRCTL_COUNT];
26 #endif
27
28 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
29 #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
30 int xfi_dpmac[XFI14 + 1];
31 int sgmii_dpmac[SGMII18 + 1];
32 int a25gaui_dpmac[_25GE10 + 1];
33 int xlaui_dpmac[_40GE2 + 1];
34 int caui2_dpmac[_50GE2 + 1];
35 int caui4_dpmac[_100GE2 + 1];
36 #else
37 int xfi_dpmac[XFI8 + 1];
38 int sgmii_dpmac[SGMII16 + 1];
39 #endif
40 #endif
41
42 __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
43 {
44         return;
45 }
46
47 /*
48  *The return value of this func is the serdes protocol used.
49  *Typically this function is called number of times depending
50  *upon the number of serdes blocks in the Silicon.
51  *Zero is used to denote that no serdes was enabled,
52  *this is the case when golden RCW was used where DPAA2 bring was
53  *intentionally removed to achieve boot to prompt
54 */
55
56 __weak int serdes_get_number(int serdes, int cfg)
57 {
58         return cfg;
59 }
60
61 int is_serdes_configured(enum srds_prtcl device)
62 {
63         int ret = 0;
64
65 #ifdef CONFIG_SYS_FSL_SRDS_1
66         if (!serdes1_prtcl_map[NONE])
67                 fsl_serdes_init();
68
69         ret |= serdes1_prtcl_map[device];
70 #endif
71 #ifdef CONFIG_SYS_FSL_SRDS_2
72         if (!serdes2_prtcl_map[NONE])
73                 fsl_serdes_init();
74
75         ret |= serdes2_prtcl_map[device];
76 #endif
77 #ifdef CONFIG_SYS_NXP_SRDS_3
78         if (!serdes3_prtcl_map[NONE])
79                 fsl_serdes_init();
80
81         ret |= serdes3_prtcl_map[device];
82 #endif
83
84         return !!ret;
85 }
86
87 int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
88 {
89         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
90         u32 cfg = 0;
91         int i;
92
93         switch (sd) {
94 #ifdef CONFIG_SYS_FSL_SRDS_1
95         case FSL_SRDS_1:
96                 cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
97                 cfg &= FSL_CHASSIS3_SRDS1_PRTCL_MASK;
98                 cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT;
99                 break;
100 #endif
101 #ifdef CONFIG_SYS_FSL_SRDS_2
102         case FSL_SRDS_2:
103                 cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
104                 cfg &= FSL_CHASSIS3_SRDS2_PRTCL_MASK;
105                 cfg >>= FSL_CHASSIS3_SRDS2_PRTCL_SHIFT;
106                 break;
107 #endif
108 #ifdef CONFIG_SYS_NXP_SRDS_3
109         case NXP_SRDS_3:
110                 cfg = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
111                 cfg &= FSL_CHASSIS3_SRDS3_PRTCL_MASK;
112                 cfg >>= FSL_CHASSIS3_SRDS3_PRTCL_SHIFT;
113                 break;
114 #endif
115         default:
116                 printf("invalid SerDes%d\n", sd);
117                 break;
118         }
119
120         cfg = serdes_get_number(sd, cfg);
121
122         /* Is serdes enabled at all? */
123         if (cfg == 0)
124                 return -ENODEV;
125
126         for (i = 0; i < SRDS_MAX_LANES; i++) {
127                 if (serdes_get_prtcl(sd, cfg, i) == device)
128                         return i;
129         }
130
131         return -ENODEV;
132 }
133
134 void serdes_init(u32 sd, u32 sd_addr, u32 rcwsr, u32 sd_prctl_mask,
135                  u32 sd_prctl_shift, u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
136 {
137         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
138         u32 cfg;
139         int lane;
140
141         if (serdes_prtcl_map[NONE])
142                 return;
143
144         memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
145
146         cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
147         cfg >>= sd_prctl_shift;
148
149         cfg = serdes_get_number(sd, cfg);
150         if (cfg == 0) {
151                 printf("SERDES%d is disabled\n", sd + 1);
152         } else {
153                 printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
154
155                 if (!is_serdes_prtcl_valid(sd, cfg))
156                         printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
157         }
158
159         for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
160                 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
161                 if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
162                         debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
163                 else {
164                         serdes_prtcl_map[lane_prtcl] = 1;
165 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
166 #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
167                         if (lane_prtcl >= XFI1 && lane_prtcl <= XFI14)
168                                 wriop_init_dpmac(sd, xfi_dpmac[lane_prtcl],
169                                                  (int)lane_prtcl);
170
171                         if (lane_prtcl >= SGMII1 && lane_prtcl <= SGMII18)
172                                 wriop_init_dpmac(sd, sgmii_dpmac[lane_prtcl],
173                                                  (int)lane_prtcl);
174
175                         if (lane_prtcl >= _25GE1 && lane_prtcl <= _25GE10)
176                                 wriop_init_dpmac(sd, a25gaui_dpmac[lane_prtcl],
177                                                  (int)lane_prtcl);
178
179                         if (lane_prtcl >= _40GE1 && lane_prtcl <= _40GE2)
180                                 wriop_init_dpmac(sd, xlaui_dpmac[lane_prtcl],
181                                                  (int)lane_prtcl);
182
183                         if (lane_prtcl >= _50GE1 && lane_prtcl <= _50GE2)
184                                 wriop_init_dpmac(sd, caui2_dpmac[lane_prtcl],
185                                                  (int)lane_prtcl);
186
187                         if (lane_prtcl >= _100GE1 && lane_prtcl <= _100GE2)
188                                 wriop_init_dpmac(sd, caui4_dpmac[lane_prtcl],
189                                                  (int)lane_prtcl);
190
191 #else
192                         switch (lane_prtcl) {
193                         case QSGMII_A:
194                         case QSGMII_B:
195                         case QSGMII_C:
196                         case QSGMII_D:
197                                 wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
198                                 break;
199                         default:
200                                 if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
201                                         wriop_init_dpmac(sd,
202                                                          xfi_dpmac[lane_prtcl],
203                                                          (int)lane_prtcl);
204
205                                  if (lane_prtcl >= SGMII1 &&
206                                      lane_prtcl <= SGMII16)
207                                         wriop_init_dpmac(sd, sgmii_dpmac[
208                                                          lane_prtcl],
209                                                          (int)lane_prtcl);
210                                 break;
211                         }
212 #endif
213 #endif
214                 }
215         }
216
217         /* Set the first element to indicate serdes has been initialized */
218         serdes_prtcl_map[NONE] = 1;
219 }
220
221 __weak int get_serdes_volt(void)
222 {
223         return -1;
224 }
225
226 __weak int set_serdes_volt(int svdd)
227 {
228         return -1;
229 }
230
231 #define LNAGCR0_RT_RSTB         0x00600000
232
233 #define RSTCTL_RESET_MASK       0x000000E0
234
235 #define RSTCTL_RSTREQ           0x80000000
236 #define RSTCTL_RST_DONE         0x40000000
237 #define RSTCTL_RSTERR           0x20000000
238
239 #define RSTCTL_SDEN             0x00000020
240 #define RSTCTL_SDRST_B          0x00000040
241 #define RSTCTL_PLLRST_B         0x00000080
242
243 #define TCALCR_CALRST_B         0x08000000
244
245 struct serdes_prctl_info {
246         u32 id;
247         u32 mask;
248         u32 shift;
249 };
250
251 struct serdes_prctl_info srds_prctl_info[] = {
252 #ifdef CONFIG_SYS_FSL_SRDS_1
253         {.id = 1,
254          .mask = FSL_CHASSIS3_SRDS1_PRTCL_MASK,
255          .shift = FSL_CHASSIS3_SRDS1_PRTCL_SHIFT
256         },
257
258 #endif
259 #ifdef CONFIG_SYS_FSL_SRDS_2
260         {.id = 2,
261          .mask = FSL_CHASSIS3_SRDS2_PRTCL_MASK,
262          .shift = FSL_CHASSIS3_SRDS2_PRTCL_SHIFT
263         },
264 #endif
265 #ifdef CONFIG_SYS_NXP_SRDS_3
266         {.id = 3,
267          .mask = FSL_CHASSIS3_SRDS3_PRTCL_MASK,
268          .shift = FSL_CHASSIS3_SRDS3_PRTCL_SHIFT
269         },
270 #endif
271         {} /* NULL ENTRY */
272 };
273
274 static int get_serdes_prctl_info_idx(u32 serdes_id)
275 {
276         int pos = 0;
277         struct serdes_prctl_info *srds_info;
278
279         /* loop until NULL ENTRY defined by .id=0 */
280         for (srds_info = srds_prctl_info; srds_info->id != 0;
281              srds_info++, pos++) {
282                 if (srds_info->id == serdes_id)
283                         return pos;
284         }
285
286         return -1;
287 }
288
289 static void do_enabled_lanes_reset(u32 serdes_id, u32 cfg,
290                                    struct ccsr_serdes __iomem *serdes_base,
291                                    bool cmplt)
292 {
293         int i, pos;
294         u32 cfg_tmp;
295
296         pos = get_serdes_prctl_info_idx(serdes_id);
297         if (pos == -1) {
298                 printf("invalid serdes_id %d\n", serdes_id);
299                 return;
300         }
301
302         cfg_tmp = cfg & srds_prctl_info[pos].mask;
303         cfg_tmp >>= srds_prctl_info[pos].shift;
304
305         for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
306                 if (cmplt)
307                         setbits_le32(&serdes_base->lane[i].gcr0,
308                                      LNAGCR0_RT_RSTB);
309                 else
310                         clrbits_le32(&serdes_base->lane[i].gcr0,
311                                      LNAGCR0_RT_RSTB);
312         }
313 }
314
315 static void do_pll_reset(u32 cfg,
316                          struct ccsr_serdes __iomem *serdes_base)
317 {
318         int i;
319
320         for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
321                 clrbits_le32(&serdes_base->bank[i].rstctl,
322                              RSTCTL_RESET_MASK);
323                 udelay(1);
324
325                 setbits_le32(&serdes_base->bank[i].rstctl,
326                              RSTCTL_RSTREQ);
327         }
328         udelay(1);
329 }
330
331 static void do_rx_tx_cal_reset(struct ccsr_serdes __iomem *serdes_base)
332 {
333         clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
334         clrbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
335 }
336
337 static void do_rx_tx_cal_reset_comp(u32 cfg, int i,
338                                     struct ccsr_serdes __iomem *serdes_base)
339 {
340         if (!(cfg == 0x3 && i == 1)) {
341                 udelay(1);
342                 setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
343                 setbits_le32(&serdes_base->srdstcalcr, TCALCR_CALRST_B);
344         }
345         udelay(1);
346 }
347
348 static void do_pll_reset_done(u32 cfg,
349                               struct ccsr_serdes __iomem *serdes_base)
350 {
351         int i;
352         u32 reg = 0;
353
354         for (i = 0; i < 2; i++) {
355                 reg = in_le32(&serdes_base->bank[i].pllcr0);
356                 if (!(cfg & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
357                         setbits_le32(&serdes_base->bank[i].rstctl,
358                                      RSTCTL_RST_DONE);
359                 }
360         }
361 }
362
363 static void do_serdes_enable(u32 cfg,
364                              struct ccsr_serdes __iomem *serdes_base)
365 {
366         int i;
367
368         for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
369                 setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_SDEN);
370                 udelay(1);
371
372                 setbits_le32(&serdes_base->bank[i].rstctl, RSTCTL_PLLRST_B);
373                 udelay(1);
374                 /* Take the Rx/Tx calibration out of reset */
375                 do_rx_tx_cal_reset_comp(cfg, i, serdes_base);
376         }
377 }
378
379 static void do_pll_lock(u32 cfg,
380                         struct ccsr_serdes __iomem *serdes_base)
381 {
382         int i;
383         u32 reg = 0;
384
385         for (i = 0; i < 2 && !(cfg & (0x1 << (1 - i))); i++) {
386                 /* if the PLL is not locked, set RST_ERR */
387                 reg = in_le32(&serdes_base->bank[i].pllcr0);
388                 if (!((reg >> 23) & 0x1)) {
389                         setbits_le32(&serdes_base->bank[i].rstctl,
390                                      RSTCTL_RSTERR);
391                 } else {
392                         udelay(1);
393                         setbits_le32(&serdes_base->bank[i].rstctl,
394                                      RSTCTL_SDRST_B);
395                         udelay(1);
396                 }
397         }
398 }
399
400 int setup_serdes_volt(u32 svdd)
401 {
402         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
403         struct ccsr_serdes __iomem *serdes1_base =
404                         (void *)CONFIG_SYS_FSL_LSCH3_SERDES_ADDR;
405         u32 cfg_rcwsrds1 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]);
406 #ifdef CONFIG_SYS_FSL_SRDS_2
407         struct ccsr_serdes __iomem *serdes2_base =
408                         (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x10000);
409         u32 cfg_rcwsrds2 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS2_REGSR - 1]);
410 #endif
411 #ifdef CONFIG_SYS_NXP_SRDS_3
412         struct ccsr_serdes __iomem *serdes3_base =
413                         (void *)(CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + 0x20000);
414         u32 cfg_rcwsrds3 = gur_in32(&gur->rcwsr[FSL_CHASSIS3_SRDS3_REGSR - 1]);
415 #endif
416         u32 cfg_tmp;
417         int svdd_cur, svdd_tar;
418         int ret = 1;
419
420         /* Only support switch SVDD to 900mV */
421         if (svdd != 900)
422                 return -EINVAL;
423
424         /* Scale up to the LTC resolution is 1/4096V */
425         svdd = (svdd * 4096) / 1000;
426
427         svdd_tar = svdd;
428         svdd_cur = get_serdes_volt();
429         if (svdd_cur < 0)
430                 return -EINVAL;
431
432         debug("%s: current SVDD: %x; target SVDD: %x\n",
433               __func__, svdd_cur, svdd_tar);
434         if (svdd_cur == svdd_tar)
435                 return 0;
436
437         /* Put the all enabled lanes in reset */
438 #ifdef CONFIG_SYS_FSL_SRDS_1
439         do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, false);
440 #endif
441
442 #ifdef CONFIG_SYS_FSL_SRDS_2
443         do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, false);
444 #endif
445 #ifdef CONFIG_SYS_NXP_SRDS_3
446         do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, false);
447 #endif
448
449         /* Put the all enabled PLL in reset */
450 #ifdef CONFIG_SYS_FSL_SRDS_1
451         cfg_tmp = cfg_rcwsrds1 & 0x3;
452         do_pll_reset(cfg_tmp, serdes1_base);
453 #endif
454
455 #ifdef CONFIG_SYS_FSL_SRDS_2
456         cfg_tmp = cfg_rcwsrds1 & 0xC;
457         cfg_tmp >>= 2;
458         do_pll_reset(cfg_tmp, serdes2_base);
459 #endif
460
461 #ifdef CONFIG_SYS_NXP_SRDS_3
462         cfg_tmp = cfg_rcwsrds3 & 0x30;
463         cfg_tmp >>= 4;
464         do_pll_reset(cfg_tmp, serdes3_base);
465 #endif
466
467         /* Put the Rx/Tx calibration into reset */
468 #ifdef CONFIG_SYS_FSL_SRDS_1
469         do_rx_tx_cal_reset(serdes1_base);
470 #endif
471
472 #ifdef CONFIG_SYS_FSL_SRDS_2
473         do_rx_tx_cal_reset(serdes2_base);
474 #endif
475
476 #ifdef CONFIG_SYS_NXP_SRDS_3
477         do_rx_tx_cal_reset(serdes3_base);
478 #endif
479
480         ret = set_serdes_volt(svdd);
481         if (ret < 0) {
482                 printf("could not change SVDD\n");
483                 ret = -1;
484         }
485
486         /* For each PLL that’s not disabled via RCW enable the SERDES */
487 #ifdef CONFIG_SYS_FSL_SRDS_1
488         cfg_tmp = cfg_rcwsrds1 & 0x3;
489         do_serdes_enable(cfg_tmp, serdes1_base);
490 #endif
491 #ifdef CONFIG_SYS_FSL_SRDS_2
492         cfg_tmp = cfg_rcwsrds1 & 0xC;
493         cfg_tmp >>= 2;
494         do_serdes_enable(cfg_tmp, serdes2_base);
495 #endif
496 #ifdef CONFIG_SYS_NXP_SRDS_3
497         cfg_tmp = cfg_rcwsrds3 & 0x30;
498         cfg_tmp >>= 4;
499         do_serdes_enable(cfg_tmp, serdes3_base);
500 #endif
501
502         /* Wait for at at least 625us, ensure the PLLs being reset are locked */
503         udelay(800);
504
505 #ifdef CONFIG_SYS_FSL_SRDS_1
506         cfg_tmp = cfg_rcwsrds1 & 0x3;
507         do_pll_lock(cfg_tmp, serdes1_base);
508 #endif
509
510 #ifdef CONFIG_SYS_FSL_SRDS_2
511         cfg_tmp = cfg_rcwsrds1 & 0xC;
512         cfg_tmp >>= 2;
513         do_pll_lock(cfg_tmp, serdes2_base);
514 #endif
515
516 #ifdef CONFIG_SYS_NXP_SRDS_3
517         cfg_tmp = cfg_rcwsrds3 & 0x30;
518         cfg_tmp >>= 4;
519         do_pll_lock(cfg_tmp, serdes3_base);
520 #endif
521
522         /* Take the all enabled lanes out of reset */
523 #ifdef CONFIG_SYS_FSL_SRDS_1
524         do_enabled_lanes_reset(1, cfg_rcwsrds1, serdes1_base, true);
525 #endif
526 #ifdef CONFIG_SYS_FSL_SRDS_2
527         do_enabled_lanes_reset(2, cfg_rcwsrds2, serdes2_base, true);
528 #endif
529
530 #ifdef CONFIG_SYS_NXP_SRDS_3
531         do_enabled_lanes_reset(3, cfg_rcwsrds3, serdes3_base, true);
532 #endif
533
534         /* For each PLL being reset, and achieved PLL lock set RST_DONE */
535 #ifdef CONFIG_SYS_FSL_SRDS_1
536         cfg_tmp = cfg_rcwsrds1 & 0x3;
537         do_pll_reset_done(cfg_tmp, serdes1_base);
538 #endif
539 #ifdef CONFIG_SYS_FSL_SRDS_2
540         cfg_tmp = cfg_rcwsrds1 & 0xC;
541         cfg_tmp >>= 2;
542         do_pll_reset_done(cfg_tmp, serdes2_base);
543 #endif
544
545 #ifdef CONFIG_SYS_NXP_SRDS_3
546         cfg_tmp = cfg_rcwsrds3 & 0x30;
547         cfg_tmp >>= 4;
548         do_pll_reset_done(cfg_tmp, serdes3_base);
549 #endif
550
551         return ret;
552 }
553
554 void fsl_serdes_init(void)
555 {
556 #if defined(CONFIG_FSL_MC_ENET) && !defined(CONFIG_SPL_BUILD)
557         int i , j;
558
559 #if defined(CONFIG_ARCH_LX2160A) || defined(CONFIG_ARCH_LX2162A)
560         for (i = XFI1, j = 1; i <= XFI14; i++, j++)
561                 xfi_dpmac[i] = j;
562
563         for (i = SGMII1, j = 1; i <= SGMII18; i++, j++)
564                 sgmii_dpmac[i] = j;
565
566         for (i = _25GE1, j = 1; i <= _25GE10; i++, j++)
567                 a25gaui_dpmac[i] = j;
568
569         for (i = _40GE1, j = 1; i <= _40GE2; i++, j++)
570                 xlaui_dpmac[i] = j;
571
572         for (i = _50GE1, j = 1; i <= _50GE2; i++, j++)
573                 caui2_dpmac[i] = j;
574
575         for (i = _100GE1, j = 1; i <= _100GE2; i++, j++)
576                 caui4_dpmac[i] = j;
577 #else
578         for (i = XFI1, j = 1; i <= XFI8; i++, j++)
579                 xfi_dpmac[i] = j;
580
581         for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
582                 sgmii_dpmac[i] = j;
583 #endif
584 #endif
585
586 #ifdef CONFIG_SYS_FSL_SRDS_1
587         serdes_init(FSL_SRDS_1,
588                     CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
589                     FSL_CHASSIS3_SRDS1_REGSR,
590                     FSL_CHASSIS3_SRDS1_PRTCL_MASK,
591                     FSL_CHASSIS3_SRDS1_PRTCL_SHIFT,
592                     serdes1_prtcl_map);
593 #endif
594 #ifdef CONFIG_SYS_FSL_SRDS_2
595         serdes_init(FSL_SRDS_2,
596                     CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
597                     FSL_CHASSIS3_SRDS2_REGSR,
598                     FSL_CHASSIS3_SRDS2_PRTCL_MASK,
599                     FSL_CHASSIS3_SRDS2_PRTCL_SHIFT,
600                     serdes2_prtcl_map);
601 #endif
602 #ifdef CONFIG_SYS_NXP_SRDS_3
603         serdes_init(NXP_SRDS_3,
604                     CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + NXP_SRDS_3 * 0x10000,
605                     FSL_CHASSIS3_SRDS3_REGSR,
606                     FSL_CHASSIS3_SRDS3_PRTCL_MASK,
607                     FSL_CHASSIS3_SRDS3_PRTCL_SHIFT,
608                     serdes3_prtcl_map);
609 #endif
610 }
611
612 int serdes_set_env(int sd, int rcwsr, int sd_prctl_mask, int sd_prctl_shift)
613 {
614         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
615         char scfg[16], snum[16];
616         int cfgr = 0;
617         u32 cfg;
618
619         cfg = gur_in32(&gur->rcwsr[rcwsr - 1]) & sd_prctl_mask;
620         cfg >>= sd_prctl_shift;
621         cfg = serdes_get_number(sd, cfg);
622
623 #if defined(SRDS_BITS_PER_LANE)
624         /*
625          * reverse lanes, lane 0 should be printed first so it must be moved to
626          * high order bits.
627          * For example bb58 should read 85bb, lane 0 being protocol 8.
628          * This only applies to SoCs that define SRDS_BITS_PER_LANE and have
629          * independent per-lane protocol configuration, at this time LS1028A and
630          * LS1088A. LS2 and LX2 SoCs encode the full protocol mix across all
631          * lanes as a single value.
632          */
633         for (int i = 0; i < SRDS_MAX_LANES; i++) {
634                 int tmp;
635
636                 tmp = cfg >> (i * SRDS_BITS_PER_LANE);
637                 tmp &= GENMASK(SRDS_BITS_PER_LANE - 1, 0);
638                 tmp <<= (SRDS_MAX_LANES - i - 1) * SRDS_BITS_PER_LANE;
639                 cfgr |= tmp;
640         }
641 #endif /* SRDS_BITS_PER_LANE */
642
643         snprintf(snum, 16, "serdes%d", sd);
644         snprintf(scfg, 16, "%x", cfgr);
645         env_set(snum, scfg);
646
647         return 0;
648 }
649
650 int serdes_misc_init(void)
651 {
652 #ifdef CONFIG_SYS_FSL_SRDS_1
653         serdes_set_env(FSL_SRDS_1, FSL_CHASSIS3_SRDS1_REGSR,
654                        FSL_CHASSIS3_SRDS1_PRTCL_MASK,
655                        FSL_CHASSIS3_SRDS1_PRTCL_SHIFT);
656 #endif
657 #ifdef CONFIG_SYS_FSL_SRDS_2
658         serdes_set_env(FSL_SRDS_2, FSL_CHASSIS3_SRDS2_REGSR,
659                        FSL_CHASSIS3_SRDS2_PRTCL_MASK,
660                        FSL_CHASSIS3_SRDS2_PRTCL_SHIFT);
661 #endif
662 #ifdef CONFIG_SYS_NXP_SRDS_3
663         serdes_set_env(NXP_SRDS_3, FSL_CHASSIS3_SRDS3_REGSR,
664                        FSL_CHASSIS3_SRDS3_PRTCL_MASK,
665                        FSL_CHASSIS3_SRDS3_PRTCL_SHIFT);
666 #endif
667
668         return 0;
669 }