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