]> git.sur5r.net Git - u-boot/blob - arch/arm/cpu/armv8/fsl-layerscape/fsl_lsch3_serdes.c
arm: fsl-layerscape: Move QSGMII wriop_init to SoC file
[u-boot] / arch / arm / cpu / armv8 / fsl-layerscape / fsl_lsch3_serdes.c
1 /*
2  * Copyright 2014-2015 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
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
21 #ifdef CONFIG_FSL_MC_ENET
22 int xfi_dpmac[XFI8 + 1];
23 int sgmii_dpmac[SGMII16 + 1];
24 #endif
25
26 __weak void wriop_init_dpmac_qsgmii(int sd, int lane_prtcl)
27 {
28         return;
29 }
30
31 int is_serdes_configured(enum srds_prtcl device)
32 {
33         int ret = 0;
34
35 #ifdef CONFIG_SYS_FSL_SRDS_1
36         if (!serdes1_prtcl_map[NONE])
37                 fsl_serdes_init();
38
39         ret |= serdes1_prtcl_map[device];
40 #endif
41 #ifdef CONFIG_SYS_FSL_SRDS_2
42         if (!serdes2_prtcl_map[NONE])
43                 fsl_serdes_init();
44
45         ret |= serdes2_prtcl_map[device];
46 #endif
47
48         return !!ret;
49 }
50
51 int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
52 {
53         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
54         u32 cfg = gur_in32(&gur->rcwsr[28]);
55         int i;
56
57         switch (sd) {
58 #ifdef CONFIG_SYS_FSL_SRDS_1
59         case FSL_SRDS_1:
60                 cfg &= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK;
61                 cfg >>= FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT;
62                 break;
63 #endif
64 #ifdef CONFIG_SYS_FSL_SRDS_2
65         case FSL_SRDS_2:
66                 cfg &= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK;
67                 cfg >>= FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT;
68                 break;
69 #endif
70         default:
71                 printf("invalid SerDes%d\n", sd);
72                 break;
73         }
74         /* Is serdes enabled at all? */
75         if (cfg == 0)
76                 return -ENODEV;
77
78         for (i = 0; i < SRDS_MAX_LANES; i++) {
79                 if (serdes_get_prtcl(sd, cfg, i) == device)
80                         return i;
81         }
82
83         return -ENODEV;
84 }
85
86 void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
87                 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
88 {
89         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
90         u32 cfg;
91         int lane;
92
93         if (serdes_prtcl_map[NONE])
94                 return;
95
96         memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
97
98         cfg = gur_in32(&gur->rcwsr[28]) & sd_prctl_mask;
99         cfg >>= sd_prctl_shift;
100         printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
101
102         if (!is_serdes_prtcl_valid(sd, cfg))
103                 printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
104
105         for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
106                 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
107                 if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
108                         debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
109                 else {
110                         serdes_prtcl_map[lane_prtcl] = 1;
111 #ifdef CONFIG_FSL_MC_ENET
112                         switch (lane_prtcl) {
113                         case QSGMII_A:
114                         case QSGMII_B:
115                         case QSGMII_C:
116                         case QSGMII_D:
117                                 wriop_init_dpmac_qsgmii(sd, (int)lane_prtcl);
118                                 break;
119                         default:
120                                 if (lane_prtcl >= XFI1 && lane_prtcl <= XFI8)
121                                         wriop_init_dpmac(sd,
122                                                          xfi_dpmac[lane_prtcl],
123                                                          (int)lane_prtcl);
124
125                                  if (lane_prtcl >= SGMII1 &&
126                                      lane_prtcl <= SGMII16)
127                                         wriop_init_dpmac(sd, sgmii_dpmac[
128                                                          lane_prtcl],
129                                                          (int)lane_prtcl);
130                                 break;
131                         }
132 #endif
133                 }
134         }
135
136         /* Set the first element to indicate serdes has been initialized */
137         serdes_prtcl_map[NONE] = 1;
138 }
139
140 void fsl_serdes_init(void)
141 {
142 #ifdef CONFIG_FSL_MC_ENET
143         int i , j;
144
145         for (i = XFI1, j = 1; i <= XFI8; i++, j++)
146                 xfi_dpmac[i] = j;
147
148         for (i = SGMII1, j = 1; i <= SGMII16; i++, j++)
149                 sgmii_dpmac[i] = j;
150 #endif
151
152 #ifdef CONFIG_SYS_FSL_SRDS_1
153         serdes_init(FSL_SRDS_1,
154                     CONFIG_SYS_FSL_LSCH3_SERDES_ADDR,
155                     FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_MASK,
156                     FSL_CHASSIS3_RCWSR28_SRDS1_PRTCL_SHIFT,
157                     serdes1_prtcl_map);
158 #endif
159 #ifdef CONFIG_SYS_FSL_SRDS_2
160         serdes_init(FSL_SRDS_2,
161                     CONFIG_SYS_FSL_LSCH3_SERDES_ADDR + FSL_SRDS_2 * 0x10000,
162                     FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_MASK,
163                     FSL_CHASSIS3_RCWSR28_SRDS2_PRTCL_SHIFT,
164                     serdes2_prtcl_map);
165 #endif
166 }