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