1
2
3
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
13static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
14#endif
15#ifdef CONFIG_SYS_FSL_SRDS_2
16static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
17#endif
18
19int 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
39int 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
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
75int 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
85const 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
99void 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
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
141int 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
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
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
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
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
250
251
252 ret = set_serdes_volt(svdd_tar);
253 if (ret)
254 printf("%s: Failed to set SVDD\n", __func__);
255
256
257 udelay(100);
258
259
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
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
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
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
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
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
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
403void 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}
420