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 }
420