arm: mach-k3: Enable dcache in SPL
[oweals/u-boot.git] / arch / arm / cpu / armv8 / fsl-layerscape / fsl_lsch2_serdes.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2015 Freescale Semiconductor, Inc.
4  */
5
6 #include <common.h>
7 #include <asm/io.h>
8 #include <linux/errno.h>
9 #include <asm/arch/fsl_serdes.h>
10 #include <asm/arch/soc.h>
11
12 #ifdef CONFIG_SYS_FSL_SRDS_1
13 static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
14 #endif
15 #ifdef CONFIG_SYS_FSL_SRDS_2
16 static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
17 #endif
18
19 int is_serdes_configured(enum srds_prtcl device)
20 {
21         int ret = 0;
22
23 #ifdef CONFIG_SYS_FSL_SRDS_1
24         if (!serdes1_prtcl_map[NONE])
25                 fsl_serdes_init();
26
27         ret |= serdes1_prtcl_map[device];
28 #endif
29 #ifdef CONFIG_SYS_FSL_SRDS_2
30         if (!serdes2_prtcl_map[NONE])
31                 fsl_serdes_init();
32
33         ret |= serdes2_prtcl_map[device];
34 #endif
35
36         return !!ret;
37 }
38
39 int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
40 {
41         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
42         u32 cfg = gur_in32(&gur->rcwsr[4]);
43         int i;
44
45         switch (sd) {
46 #ifdef CONFIG_SYS_FSL_SRDS_1
47         case FSL_SRDS_1:
48                 cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
49                 cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
50                 break;
51 #endif
52 #ifdef CONFIG_SYS_FSL_SRDS_2
53         case FSL_SRDS_2:
54                 cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
55                 cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
56                 break;
57 #endif
58         default:
59                 printf("invalid SerDes%d\n", sd);
60                 break;
61         }
62
63         /* Is serdes enabled at all? */
64         if (unlikely(cfg == 0))
65                 return -ENODEV;
66
67         for (i = 0; i < SRDS_MAX_LANES; i++) {
68                 if (serdes_get_prtcl(sd, cfg, i) == device)
69                         return i;
70         }
71
72         return -ENODEV;
73 }
74
75 int get_serdes_protocol(void)
76 {
77         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
78         u32 cfg = gur_in32(&gur->rcwsr[4]) &
79                           FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
80         cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
81
82         return cfg;
83 }
84
85 const char *serdes_clock_to_string(u32 clock)
86 {
87         switch (clock) {
88         case SRDS_PLLCR0_RFCK_SEL_100:
89                 return "100";
90         case SRDS_PLLCR0_RFCK_SEL_125:
91                 return "125";
92         case SRDS_PLLCR0_RFCK_SEL_156_25:
93                 return "156.25";
94         default:
95                 return "100";
96         }
97 }
98
99 void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
100                  u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
101 {
102         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
103         u32 cfg;
104         int lane;
105
106         if (serdes_prtcl_map[NONE])
107                 return;
108
109         memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
110
111         cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
112         cfg >>= sd_prctl_shift;
113         printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
114
115         if (!is_serdes_prtcl_valid(sd, cfg))
116                 printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
117
118         for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
119                 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
120
121                 if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
122                         debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
123                 else
124                         serdes_prtcl_map[lane_prtcl] = 1;
125         }
126
127         /* Set the first element to indicate serdes has been initialized */
128         serdes_prtcl_map[NONE] = 1;
129 }
130
131 __weak int get_serdes_volt(void)
132 {
133         return -1;
134 }
135
136 __weak int set_serdes_volt(int svdd)
137 {
138         return -1;
139 }
140
141 int setup_serdes_volt(u32 svdd)
142 {
143         struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
144         struct ccsr_serdes *serdes1_base;
145 #ifdef CONFIG_SYS_FSL_SRDS_2
146         struct ccsr_serdes *serdes2_base;
147 #endif
148         u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
149         u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
150         u32 cfg_tmp, reg = 0;
151         int svdd_cur, svdd_tar;
152         int ret;
153         int i;
154
155         /* Only support switch SVDD to 900mV/1000mV */
156         if (svdd != 900 && svdd != 1000)
157                 return -EINVAL;
158
159         svdd_tar = svdd;
160         svdd_cur = get_serdes_volt();
161         if (svdd_cur < 0)
162                 return -EINVAL;
163
164         debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
165               __func__, svdd_cur, svdd_tar);
166         if (svdd_cur == svdd_tar)
167                 return 0;
168
169         serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
170 #ifdef CONFIG_SYS_FSL_SRDS_2
171         serdes2_base = (void *)serdes1_base + 0x10000;
172 #endif
173
174         /* Put the all enabled lanes in reset */
175 #ifdef CONFIG_SYS_FSL_SRDS_1
176         cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
177         cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
178
179         for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
180                 reg = in_be32(&serdes1_base->lane[i].gcr0);
181                 reg &= 0xFF9FFFFF;
182                 out_be32(&serdes1_base->lane[i].gcr0, reg);
183         }
184 #endif
185 #ifdef CONFIG_SYS_FSL_SRDS_2
186         cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
187         cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
188
189         for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
190                 reg = in_be32(&serdes2_base->lane[i].gcr0);
191                 reg &= 0xFF9FFFFF;
192                 out_be32(&serdes2_base->lane[i].gcr0, reg);
193         }
194 #endif
195
196         /* Put the all enabled PLL in reset */
197 #ifdef CONFIG_SYS_FSL_SRDS_1
198         cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
199         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
200                 reg = in_be32(&serdes1_base->bank[i].rstctl);
201                 reg &= 0xFFFFFFBF;
202                 reg |= 0x10000000;
203                 out_be32(&serdes1_base->bank[i].rstctl, reg);
204                 udelay(1);
205
206                 reg = in_be32(&serdes1_base->bank[i].rstctl);
207                 reg &= 0xFFFFFF1F;
208                 out_be32(&serdes1_base->bank[i].rstctl, reg);
209         }
210         udelay(1);
211 #endif
212
213 #ifdef CONFIG_SYS_FSL_SRDS_2
214         cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
215         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
216                 reg = in_be32(&serdes2_base->bank[i].rstctl);
217                 reg &= 0xFFFFFFBF;
218                 reg |= 0x10000000;
219                 out_be32(&serdes2_base->bank[i].rstctl, reg);
220                 udelay(1);
221
222                 reg = in_be32(&serdes2_base->bank[i].rstctl);
223                 reg &= 0xFFFFFF1F;
224                 out_be32(&serdes2_base->bank[i].rstctl, reg);
225         }
226         udelay(1);
227 #endif
228
229         /* Put the Rx/Tx calibration into reset */
230 #ifdef CONFIG_SYS_FSL_SRDS_1
231         reg = in_be32(&serdes1_base->srdstcalcr);
232         reg &= 0xF7FFFFFF;
233         out_be32(&serdes1_base->srdstcalcr, reg);
234         reg = in_be32(&serdes1_base->srdsrcalcr);
235         reg &= 0xF7FFFFFF;
236         out_be32(&serdes1_base->srdsrcalcr, reg);
237
238 #endif
239 #ifdef CONFIG_SYS_FSL_SRDS_2
240         reg = in_be32(&serdes2_base->srdstcalcr);
241         reg &= 0xF7FFFFFF;
242         out_be32(&serdes2_base->srdstcalcr, reg);
243         reg = in_be32(&serdes2_base->srdsrcalcr);
244         reg &= 0xF7FFFFFF;
245         out_be32(&serdes2_base->srdsrcalcr, reg);
246 #endif
247
248         /*
249          * If SVDD set failed, will not return directly, so that the
250          * serdes lanes can complete reseting.
251          */
252         ret = set_serdes_volt(svdd_tar);
253         if (ret)
254                 printf("%s: Failed to set SVDD\n", __func__);
255
256         /* Wait for SVDD to stabilize */
257         udelay(100);
258
259         /* For each PLL that’s not disabled via RCW */
260 #ifdef CONFIG_SYS_FSL_SRDS_1
261         cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
262         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
263                 reg = in_be32(&serdes1_base->bank[i].rstctl);
264                 reg |= 0x00000020;
265                 out_be32(&serdes1_base->bank[i].rstctl, reg);
266                 udelay(1);
267
268                 reg = in_be32(&serdes1_base->bank[i].rstctl);
269                 reg |= 0x00000080;
270                 out_be32(&serdes1_base->bank[i].rstctl, reg);
271
272                 /* Take the Rx/Tx calibration out of reset */
273                 if (!(cfg_tmp == 0x3 && i == 1)) {
274                         udelay(1);
275                         reg = in_be32(&serdes1_base->srdstcalcr);
276                         reg |= 0x08000000;
277                         out_be32(&serdes1_base->srdstcalcr, reg);
278                         reg = in_be32(&serdes1_base->srdsrcalcr);
279                         reg |= 0x08000000;
280                         out_be32(&serdes1_base->srdsrcalcr, reg);
281                 }
282         }
283         udelay(1);
284 #endif
285
286 #ifdef CONFIG_SYS_FSL_SRDS_2
287         cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
288         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
289                 reg = in_be32(&serdes2_base->bank[i].rstctl);
290                 reg |= 0x00000020;
291                 out_be32(&serdes2_base->bank[i].rstctl, reg);
292                 udelay(1);
293
294                 reg = in_be32(&serdes2_base->bank[i].rstctl);
295                 reg |= 0x00000080;
296                 out_be32(&serdes2_base->bank[i].rstctl, reg);
297
298                 /* Take the Rx/Tx calibration out of reset */
299                 if (!(cfg_tmp == 0x3 && i == 1)) {
300                         udelay(1);
301                         reg = in_be32(&serdes2_base->srdstcalcr);
302                         reg |= 0x08000000;
303                         out_be32(&serdes2_base->srdstcalcr, reg);
304                         reg = in_be32(&serdes2_base->srdsrcalcr);
305                         reg |= 0x08000000;
306                         out_be32(&serdes2_base->srdsrcalcr, reg);
307                 }
308         }
309         udelay(1);
310
311 #endif
312
313         /* Wait for at lesat 625us to ensure the PLLs being reset are locked */
314         udelay(800);
315
316 #ifdef CONFIG_SYS_FSL_SRDS_1
317         cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
318         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
319                 /* if the PLL is not locked, set RST_ERR */
320                 reg = in_be32(&serdes1_base->bank[i].pllcr0);
321                 if (!((reg >> 23) & 0x1)) {
322                         reg = in_be32(&serdes1_base->bank[i].rstctl);
323                         reg |= 0x20000000;
324                         out_be32(&serdes1_base->bank[i].rstctl, reg);
325                 } else {
326                         udelay(1);
327                         reg = in_be32(&serdes1_base->bank[i].rstctl);
328                         reg &= 0xFFFFFFEF;
329                         reg |= 0x00000040;
330                         out_be32(&serdes1_base->bank[i].rstctl, reg);
331                         udelay(1);
332                 }
333         }
334 #endif
335
336 #ifdef CONFIG_SYS_FSL_SRDS_2
337         cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
338         for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
339                 reg = in_be32(&serdes2_base->bank[i].pllcr0);
340                 if (!((reg >> 23) & 0x1)) {
341                         reg = in_be32(&serdes2_base->bank[i].rstctl);
342                         reg |= 0x20000000;
343                         out_be32(&serdes2_base->bank[i].rstctl, reg);
344                 } else {
345                         udelay(1);
346                         reg = in_be32(&serdes2_base->bank[i].rstctl);
347                         reg &= 0xFFFFFFEF;
348                         reg |= 0x00000040;
349                         out_be32(&serdes2_base->bank[i].rstctl, reg);
350                         udelay(1);
351                 }
352         }
353 #endif
354
355         /* Take the all enabled lanes out of reset */
356 #ifdef CONFIG_SYS_FSL_SRDS_1
357         cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
358         cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
359
360         for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
361                 reg = in_be32(&serdes1_base->lane[i].gcr0);
362                 reg |= 0x00600000;
363                 out_be32(&serdes1_base->lane[i].gcr0, reg);
364         }
365 #endif
366 #ifdef CONFIG_SYS_FSL_SRDS_2
367         cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
368         cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
369
370         for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
371                 reg = in_be32(&serdes2_base->lane[i].gcr0);
372                 reg |= 0x00600000;
373                 out_be32(&serdes2_base->lane[i].gcr0, reg);
374         }
375 #endif
376         /* For each PLL being reset, and achieved PLL lock set RST_DONE */
377 #ifdef CONFIG_SYS_FSL_SRDS_1
378         cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
379         for (i = 0; i < 2; i++) {
380                 reg = in_be32(&serdes1_base->bank[i].pllcr0);
381                 if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
382                         reg = in_be32(&serdes1_base->bank[i].rstctl);
383                         reg |= 0x40000000;
384                         out_be32(&serdes1_base->bank[i].rstctl, reg);
385                 }
386         }
387 #endif
388 #ifdef CONFIG_SYS_FSL_SRDS_2
389         cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
390         for (i = 0; i < 2; i++) {
391                 reg = in_be32(&serdes2_base->bank[i].pllcr0);
392                 if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
393                         reg = in_be32(&serdes2_base->bank[i].rstctl);
394                         reg |= 0x40000000;
395                         out_be32(&serdes2_base->bank[i].rstctl, reg);
396                 }
397         }
398 #endif
399
400         return ret;
401 }
402
403 void fsl_serdes_init(void)
404 {
405 #ifdef CONFIG_SYS_FSL_SRDS_1
406         serdes_init(FSL_SRDS_1,
407                     CONFIG_SYS_FSL_SERDES_ADDR,
408                     FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
409                     FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
410                     serdes1_prtcl_map);
411 #endif
412 #ifdef CONFIG_SYS_FSL_SRDS_2
413         serdes_init(FSL_SRDS_2,
414                     CONFIG_SYS_FSL_SERDES_ADDR,
415                     FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
416                     FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
417                     serdes2_prtcl_map);
418 #endif
419 }