1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
28281c58fSMingkai Hu /*
38281c58fSMingkai Hu  * Copyright 2015 Freescale Semiconductor, Inc.
48281c58fSMingkai Hu  */
58281c58fSMingkai Hu 
68281c58fSMingkai Hu #include <common.h>
78281c58fSMingkai Hu #include <asm/io.h>
81221ce45SMasahiro Yamada #include <linux/errno.h>
98281c58fSMingkai Hu #include <asm/arch/fsl_serdes.h>
108281c58fSMingkai Hu #include <asm/arch/soc.h>
118281c58fSMingkai Hu 
128281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
138281c58fSMingkai Hu static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
148281c58fSMingkai Hu #endif
15da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
16da4d620cSQianyu Gong static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
17da4d620cSQianyu Gong #endif
188281c58fSMingkai Hu 
is_serdes_configured(enum srds_prtcl device)198281c58fSMingkai Hu int is_serdes_configured(enum srds_prtcl device)
208281c58fSMingkai Hu {
218281c58fSMingkai Hu 	int ret = 0;
228281c58fSMingkai Hu 
238281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
2471fe2225SHou Zhiqiang 	if (!serdes1_prtcl_map[NONE])
2571fe2225SHou Zhiqiang 		fsl_serdes_init();
2671fe2225SHou Zhiqiang 
278281c58fSMingkai Hu 	ret |= serdes1_prtcl_map[device];
288281c58fSMingkai Hu #endif
29da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
3071fe2225SHou Zhiqiang 	if (!serdes2_prtcl_map[NONE])
3171fe2225SHou Zhiqiang 		fsl_serdes_init();
3271fe2225SHou Zhiqiang 
33da4d620cSQianyu Gong 	ret |= serdes2_prtcl_map[device];
34da4d620cSQianyu Gong #endif
358281c58fSMingkai Hu 
368281c58fSMingkai Hu 	return !!ret;
378281c58fSMingkai Hu }
388281c58fSMingkai Hu 
serdes_get_first_lane(u32 sd,enum srds_prtcl device)398281c58fSMingkai Hu int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
408281c58fSMingkai Hu {
418281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
428281c58fSMingkai Hu 	u32 cfg = gur_in32(&gur->rcwsr[4]);
438281c58fSMingkai Hu 	int i;
448281c58fSMingkai Hu 
458281c58fSMingkai Hu 	switch (sd) {
468281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
478281c58fSMingkai Hu 	case FSL_SRDS_1:
488281c58fSMingkai Hu 		cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
498281c58fSMingkai Hu 		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
508281c58fSMingkai Hu 		break;
518281c58fSMingkai Hu #endif
52da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
53da4d620cSQianyu Gong 	case FSL_SRDS_2:
54da4d620cSQianyu Gong 		cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
55da4d620cSQianyu Gong 		cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
56da4d620cSQianyu Gong 		break;
57da4d620cSQianyu Gong #endif
588281c58fSMingkai Hu 	default:
598281c58fSMingkai Hu 		printf("invalid SerDes%d\n", sd);
608281c58fSMingkai Hu 		break;
618281c58fSMingkai Hu 	}
628281c58fSMingkai Hu 
638281c58fSMingkai Hu 	/* Is serdes enabled at all? */
648281c58fSMingkai Hu 	if (unlikely(cfg == 0))
658281c58fSMingkai Hu 		return -ENODEV;
668281c58fSMingkai Hu 
678281c58fSMingkai Hu 	for (i = 0; i < SRDS_MAX_LANES; i++) {
688281c58fSMingkai Hu 		if (serdes_get_prtcl(sd, cfg, i) == device)
698281c58fSMingkai Hu 			return i;
708281c58fSMingkai Hu 	}
718281c58fSMingkai Hu 
728281c58fSMingkai Hu 	return -ENODEV;
738281c58fSMingkai Hu }
748281c58fSMingkai Hu 
get_serdes_protocol(void)758281c58fSMingkai Hu int get_serdes_protocol(void)
768281c58fSMingkai Hu {
778281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
788281c58fSMingkai Hu 	u32 cfg = gur_in32(&gur->rcwsr[4]) &
798281c58fSMingkai Hu 			  FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
808281c58fSMingkai Hu 	cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
818281c58fSMingkai Hu 
828281c58fSMingkai Hu 	return cfg;
838281c58fSMingkai Hu }
848281c58fSMingkai Hu 
serdes_clock_to_string(u32 clock)858281c58fSMingkai Hu const char *serdes_clock_to_string(u32 clock)
868281c58fSMingkai Hu {
878281c58fSMingkai Hu 	switch (clock) {
888281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_100:
898281c58fSMingkai Hu 		return "100";
908281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_125:
918281c58fSMingkai Hu 		return "125";
928281c58fSMingkai Hu 	case SRDS_PLLCR0_RFCK_SEL_156_25:
938281c58fSMingkai Hu 		return "156.25";
948281c58fSMingkai Hu 	default:
958281c58fSMingkai Hu 		return "100";
968281c58fSMingkai Hu 	}
978281c58fSMingkai Hu }
988281c58fSMingkai Hu 
serdes_init(u32 sd,u32 sd_addr,u32 sd_prctl_mask,u32 sd_prctl_shift,u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])998281c58fSMingkai Hu void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
1008281c58fSMingkai Hu 		 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
1018281c58fSMingkai Hu {
1028281c58fSMingkai Hu 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
1038281c58fSMingkai Hu 	u32 cfg;
1048281c58fSMingkai Hu 	int lane;
1058281c58fSMingkai Hu 
10671fe2225SHou Zhiqiang 	if (serdes_prtcl_map[NONE])
10771fe2225SHou Zhiqiang 		return;
10871fe2225SHou Zhiqiang 
1091a338921STom Rini 	memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
1108281c58fSMingkai Hu 
1118281c58fSMingkai Hu 	cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
1128281c58fSMingkai Hu 	cfg >>= sd_prctl_shift;
1138281c58fSMingkai Hu 	printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
1148281c58fSMingkai Hu 
1158281c58fSMingkai Hu 	if (!is_serdes_prtcl_valid(sd, cfg))
1168281c58fSMingkai Hu 		printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
1178281c58fSMingkai Hu 
1188281c58fSMingkai Hu 	for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
1198281c58fSMingkai Hu 		enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
1208281c58fSMingkai Hu 
1218281c58fSMingkai Hu 		if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
1228281c58fSMingkai Hu 			debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
1238281c58fSMingkai Hu 		else
1248281c58fSMingkai Hu 			serdes_prtcl_map[lane_prtcl] = 1;
1258281c58fSMingkai Hu 	}
12671fe2225SHou Zhiqiang 
12771fe2225SHou Zhiqiang 	/* Set the first element to indicate serdes has been initialized */
12871fe2225SHou Zhiqiang 	serdes_prtcl_map[NONE] = 1;
1298281c58fSMingkai Hu }
1308281c58fSMingkai Hu 
get_serdes_volt(void)131031acdbaSHou Zhiqiang __weak int get_serdes_volt(void)
132031acdbaSHou Zhiqiang {
133031acdbaSHou Zhiqiang 	return -1;
134031acdbaSHou Zhiqiang }
135031acdbaSHou Zhiqiang 
set_serdes_volt(int svdd)136031acdbaSHou Zhiqiang __weak int set_serdes_volt(int svdd)
137031acdbaSHou Zhiqiang {
138031acdbaSHou Zhiqiang 	return -1;
139031acdbaSHou Zhiqiang }
140031acdbaSHou Zhiqiang 
setup_serdes_volt(u32 svdd)141031acdbaSHou Zhiqiang int setup_serdes_volt(u32 svdd)
142031acdbaSHou Zhiqiang {
143031acdbaSHou Zhiqiang 	struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
144031acdbaSHou Zhiqiang 	struct ccsr_serdes *serdes1_base;
145031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
146031acdbaSHou Zhiqiang 	struct ccsr_serdes *serdes2_base;
147031acdbaSHou Zhiqiang #endif
148031acdbaSHou Zhiqiang 	u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
149031acdbaSHou Zhiqiang 	u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
150031acdbaSHou Zhiqiang 	u32 cfg_tmp, reg = 0;
151031acdbaSHou Zhiqiang 	int svdd_cur, svdd_tar;
152031acdbaSHou Zhiqiang 	int ret;
153031acdbaSHou Zhiqiang 	int i;
154031acdbaSHou Zhiqiang 
155031acdbaSHou Zhiqiang 	/* Only support switch SVDD to 900mV/1000mV */
156031acdbaSHou Zhiqiang 	if (svdd != 900 && svdd != 1000)
157031acdbaSHou Zhiqiang 		return -EINVAL;
158031acdbaSHou Zhiqiang 
159031acdbaSHou Zhiqiang 	svdd_tar = svdd;
160031acdbaSHou Zhiqiang 	svdd_cur = get_serdes_volt();
161031acdbaSHou Zhiqiang 	if (svdd_cur < 0)
162031acdbaSHou Zhiqiang 		return -EINVAL;
163031acdbaSHou Zhiqiang 
164031acdbaSHou Zhiqiang 	debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
165031acdbaSHou Zhiqiang 	      __func__, svdd_cur, svdd_tar);
166031acdbaSHou Zhiqiang 	if (svdd_cur == svdd_tar)
167031acdbaSHou Zhiqiang 		return 0;
168031acdbaSHou Zhiqiang 
169031acdbaSHou Zhiqiang 	serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
170031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
171031acdbaSHou Zhiqiang 	serdes2_base = (void *)serdes1_base + 0x10000;
172031acdbaSHou Zhiqiang #endif
173031acdbaSHou Zhiqiang 
174031acdbaSHou Zhiqiang 	/* Put the all enabled lanes in reset */
175031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
176031acdbaSHou Zhiqiang 	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
177031acdbaSHou Zhiqiang 	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
178031acdbaSHou Zhiqiang 
179031acdbaSHou Zhiqiang 	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
180031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->lane[i].gcr0);
181031acdbaSHou Zhiqiang 		reg &= 0xFF9FFFFF;
182031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->lane[i].gcr0, reg);
183031acdbaSHou Zhiqiang 	}
184031acdbaSHou Zhiqiang #endif
185031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
186031acdbaSHou Zhiqiang 	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
187031acdbaSHou Zhiqiang 	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
188031acdbaSHou Zhiqiang 
189031acdbaSHou Zhiqiang 	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
190031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->lane[i].gcr0);
191031acdbaSHou Zhiqiang 		reg &= 0xFF9FFFFF;
192031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->lane[i].gcr0, reg);
193031acdbaSHou Zhiqiang 	}
194031acdbaSHou Zhiqiang #endif
195031acdbaSHou Zhiqiang 
196031acdbaSHou Zhiqiang 	/* Put the all enabled PLL in reset */
197031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
198031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
199031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
200031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].rstctl);
201031acdbaSHou Zhiqiang 		reg &= 0xFFFFFFBF;
202031acdbaSHou Zhiqiang 		reg |= 0x10000000;
203031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->bank[i].rstctl, reg);
204031acdbaSHou Zhiqiang 		udelay(1);
205031acdbaSHou Zhiqiang 
206031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].rstctl);
207031acdbaSHou Zhiqiang 		reg &= 0xFFFFFF1F;
208031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->bank[i].rstctl, reg);
209031acdbaSHou Zhiqiang 	}
210031acdbaSHou Zhiqiang 	udelay(1);
211031acdbaSHou Zhiqiang #endif
212031acdbaSHou Zhiqiang 
213031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
214031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
215031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
216031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].rstctl);
217031acdbaSHou Zhiqiang 		reg &= 0xFFFFFFBF;
218031acdbaSHou Zhiqiang 		reg |= 0x10000000;
219031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->bank[i].rstctl, reg);
220031acdbaSHou Zhiqiang 		udelay(1);
221031acdbaSHou Zhiqiang 
222031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].rstctl);
223031acdbaSHou Zhiqiang 		reg &= 0xFFFFFF1F;
224031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->bank[i].rstctl, reg);
225031acdbaSHou Zhiqiang 	}
226031acdbaSHou Zhiqiang 	udelay(1);
227031acdbaSHou Zhiqiang #endif
228031acdbaSHou Zhiqiang 
229031acdbaSHou Zhiqiang 	/* Put the Rx/Tx calibration into reset */
230031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
231031acdbaSHou Zhiqiang 	reg = in_be32(&serdes1_base->srdstcalcr);
232031acdbaSHou Zhiqiang 	reg &= 0xF7FFFFFF;
233031acdbaSHou Zhiqiang 	out_be32(&serdes1_base->srdstcalcr, reg);
234031acdbaSHou Zhiqiang 	reg = in_be32(&serdes1_base->srdsrcalcr);
235031acdbaSHou Zhiqiang 	reg &= 0xF7FFFFFF;
236031acdbaSHou Zhiqiang 	out_be32(&serdes1_base->srdsrcalcr, reg);
237031acdbaSHou Zhiqiang 
238031acdbaSHou Zhiqiang #endif
239031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
240031acdbaSHou Zhiqiang 	reg = in_be32(&serdes2_base->srdstcalcr);
241031acdbaSHou Zhiqiang 	reg &= 0xF7FFFFFF;
242031acdbaSHou Zhiqiang 	out_be32(&serdes2_base->srdstcalcr, reg);
243031acdbaSHou Zhiqiang 	reg = in_be32(&serdes2_base->srdsrcalcr);
244031acdbaSHou Zhiqiang 	reg &= 0xF7FFFFFF;
245031acdbaSHou Zhiqiang 	out_be32(&serdes2_base->srdsrcalcr, reg);
246031acdbaSHou Zhiqiang #endif
247031acdbaSHou Zhiqiang 
248031acdbaSHou Zhiqiang 	/*
249031acdbaSHou Zhiqiang 	 * If SVDD set failed, will not return directly, so that the
250031acdbaSHou Zhiqiang 	 * serdes lanes can complete reseting.
251031acdbaSHou Zhiqiang 	 */
252031acdbaSHou Zhiqiang 	ret = set_serdes_volt(svdd_tar);
253031acdbaSHou Zhiqiang 	if (ret)
254031acdbaSHou Zhiqiang 		printf("%s: Failed to set SVDD\n", __func__);
255031acdbaSHou Zhiqiang 
256031acdbaSHou Zhiqiang 	/* Wait for SVDD to stabilize */
257031acdbaSHou Zhiqiang 	udelay(100);
258031acdbaSHou Zhiqiang 
259031acdbaSHou Zhiqiang 	/* For each PLL that’s not disabled via RCW */
260031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
261031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
262031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
263031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].rstctl);
264031acdbaSHou Zhiqiang 		reg |= 0x00000020;
265031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->bank[i].rstctl, reg);
266031acdbaSHou Zhiqiang 		udelay(1);
267031acdbaSHou Zhiqiang 
268031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].rstctl);
269031acdbaSHou Zhiqiang 		reg |= 0x00000080;
270031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->bank[i].rstctl, reg);
271031acdbaSHou Zhiqiang 
272031acdbaSHou Zhiqiang 		/* Take the Rx/Tx calibration out of reset */
273031acdbaSHou Zhiqiang 		if (!(cfg_tmp == 0x3 && i == 1)) {
274031acdbaSHou Zhiqiang 			udelay(1);
275031acdbaSHou Zhiqiang 			reg = in_be32(&serdes1_base->srdstcalcr);
276031acdbaSHou Zhiqiang 			reg |= 0x08000000;
277031acdbaSHou Zhiqiang 			out_be32(&serdes1_base->srdstcalcr, reg);
278031acdbaSHou Zhiqiang 			reg = in_be32(&serdes1_base->srdsrcalcr);
279031acdbaSHou Zhiqiang 			reg |= 0x08000000;
280031acdbaSHou Zhiqiang 			out_be32(&serdes1_base->srdsrcalcr, reg);
281031acdbaSHou Zhiqiang 		}
282031acdbaSHou Zhiqiang 	}
283031acdbaSHou Zhiqiang 	udelay(1);
284031acdbaSHou Zhiqiang #endif
285031acdbaSHou Zhiqiang 
286031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
287031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
288031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
289031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].rstctl);
290031acdbaSHou Zhiqiang 		reg |= 0x00000020;
291031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->bank[i].rstctl, reg);
292031acdbaSHou Zhiqiang 		udelay(1);
293031acdbaSHou Zhiqiang 
294031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].rstctl);
295031acdbaSHou Zhiqiang 		reg |= 0x00000080;
296031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->bank[i].rstctl, reg);
297031acdbaSHou Zhiqiang 
298031acdbaSHou Zhiqiang 		/* Take the Rx/Tx calibration out of reset */
299031acdbaSHou Zhiqiang 		if (!(cfg_tmp == 0x3 && i == 1)) {
300031acdbaSHou Zhiqiang 			udelay(1);
301031acdbaSHou Zhiqiang 			reg = in_be32(&serdes2_base->srdstcalcr);
302031acdbaSHou Zhiqiang 			reg |= 0x08000000;
303031acdbaSHou Zhiqiang 			out_be32(&serdes2_base->srdstcalcr, reg);
304031acdbaSHou Zhiqiang 			reg = in_be32(&serdes2_base->srdsrcalcr);
305031acdbaSHou Zhiqiang 			reg |= 0x08000000;
306031acdbaSHou Zhiqiang 			out_be32(&serdes2_base->srdsrcalcr, reg);
307031acdbaSHou Zhiqiang 		}
308031acdbaSHou Zhiqiang 	}
309031acdbaSHou Zhiqiang 	udelay(1);
310031acdbaSHou Zhiqiang 
311031acdbaSHou Zhiqiang #endif
312031acdbaSHou Zhiqiang 
313031acdbaSHou Zhiqiang 	/* Wait for at lesat 625us to ensure the PLLs being reset are locked */
314031acdbaSHou Zhiqiang 	udelay(800);
315031acdbaSHou Zhiqiang 
316031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
317031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
318031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
319031acdbaSHou Zhiqiang 		/* if the PLL is not locked, set RST_ERR */
320031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].pllcr0);
321031acdbaSHou Zhiqiang 		if (!((reg >> 23) & 0x1)) {
322031acdbaSHou Zhiqiang 			reg = in_be32(&serdes1_base->bank[i].rstctl);
323031acdbaSHou Zhiqiang 			reg |= 0x20000000;
324031acdbaSHou Zhiqiang 			out_be32(&serdes1_base->bank[i].rstctl, reg);
325031acdbaSHou Zhiqiang 		} else {
326031acdbaSHou Zhiqiang 			udelay(1);
327031acdbaSHou Zhiqiang 			reg = in_be32(&serdes1_base->bank[i].rstctl);
328031acdbaSHou Zhiqiang 			reg &= 0xFFFFFFEF;
329031acdbaSHou Zhiqiang 			reg |= 0x00000040;
330031acdbaSHou Zhiqiang 			out_be32(&serdes1_base->bank[i].rstctl, reg);
331031acdbaSHou Zhiqiang 			udelay(1);
332031acdbaSHou Zhiqiang 		}
333031acdbaSHou Zhiqiang 	}
334031acdbaSHou Zhiqiang #endif
335031acdbaSHou Zhiqiang 
336031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
337031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
338031acdbaSHou Zhiqiang 	for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
339031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].pllcr0);
340031acdbaSHou Zhiqiang 		if (!((reg >> 23) & 0x1)) {
341031acdbaSHou Zhiqiang 			reg = in_be32(&serdes2_base->bank[i].rstctl);
342031acdbaSHou Zhiqiang 			reg |= 0x20000000;
343031acdbaSHou Zhiqiang 			out_be32(&serdes2_base->bank[i].rstctl, reg);
344031acdbaSHou Zhiqiang 		} else {
345031acdbaSHou Zhiqiang 			udelay(1);
346031acdbaSHou Zhiqiang 			reg = in_be32(&serdes2_base->bank[i].rstctl);
347031acdbaSHou Zhiqiang 			reg &= 0xFFFFFFEF;
348031acdbaSHou Zhiqiang 			reg |= 0x00000040;
349031acdbaSHou Zhiqiang 			out_be32(&serdes2_base->bank[i].rstctl, reg);
350031acdbaSHou Zhiqiang 			udelay(1);
351031acdbaSHou Zhiqiang 		}
352031acdbaSHou Zhiqiang 	}
353031acdbaSHou Zhiqiang #endif
354031acdbaSHou Zhiqiang 
355031acdbaSHou Zhiqiang 	/* Take the all enabled lanes out of reset */
356031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
357031acdbaSHou Zhiqiang 	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
358031acdbaSHou Zhiqiang 	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
359031acdbaSHou Zhiqiang 
360031acdbaSHou Zhiqiang 	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
361031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->lane[i].gcr0);
362031acdbaSHou Zhiqiang 		reg |= 0x00600000;
363031acdbaSHou Zhiqiang 		out_be32(&serdes1_base->lane[i].gcr0, reg);
364031acdbaSHou Zhiqiang 	}
365031acdbaSHou Zhiqiang #endif
366031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
367031acdbaSHou Zhiqiang 	cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
368031acdbaSHou Zhiqiang 	cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
369031acdbaSHou Zhiqiang 
370031acdbaSHou Zhiqiang 	for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
371031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->lane[i].gcr0);
372031acdbaSHou Zhiqiang 		reg |= 0x00600000;
373031acdbaSHou Zhiqiang 		out_be32(&serdes2_base->lane[i].gcr0, reg);
374031acdbaSHou Zhiqiang 	}
375031acdbaSHou Zhiqiang #endif
376031acdbaSHou Zhiqiang 	/* For each PLL being reset, and achieved PLL lock set RST_DONE */
377031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
378031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
379031acdbaSHou Zhiqiang 	for (i = 0; i < 2; i++) {
380031acdbaSHou Zhiqiang 		reg = in_be32(&serdes1_base->bank[i].pllcr0);
381031acdbaSHou Zhiqiang 		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
382031acdbaSHou Zhiqiang 			reg = in_be32(&serdes1_base->bank[i].rstctl);
383031acdbaSHou Zhiqiang 			reg |= 0x40000000;
384031acdbaSHou Zhiqiang 			out_be32(&serdes1_base->bank[i].rstctl, reg);
385031acdbaSHou Zhiqiang 		}
386031acdbaSHou Zhiqiang 	}
387031acdbaSHou Zhiqiang #endif
388031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
389031acdbaSHou Zhiqiang 	cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
390031acdbaSHou Zhiqiang 	for (i = 0; i < 2; i++) {
391031acdbaSHou Zhiqiang 		reg = in_be32(&serdes2_base->bank[i].pllcr0);
392031acdbaSHou Zhiqiang 		if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
393031acdbaSHou Zhiqiang 			reg = in_be32(&serdes2_base->bank[i].rstctl);
394031acdbaSHou Zhiqiang 			reg |= 0x40000000;
395031acdbaSHou Zhiqiang 			out_be32(&serdes2_base->bank[i].rstctl, reg);
396031acdbaSHou Zhiqiang 		}
397031acdbaSHou Zhiqiang 	}
398031acdbaSHou Zhiqiang #endif
399031acdbaSHou Zhiqiang 
400031acdbaSHou Zhiqiang 	return ret;
401031acdbaSHou Zhiqiang }
402031acdbaSHou Zhiqiang 
fsl_serdes_init(void)4038281c58fSMingkai Hu void fsl_serdes_init(void)
4048281c58fSMingkai Hu {
4058281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
4068281c58fSMingkai Hu 	serdes_init(FSL_SRDS_1,
4078281c58fSMingkai Hu 		    CONFIG_SYS_FSL_SERDES_ADDR,
4088281c58fSMingkai Hu 		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
4098281c58fSMingkai Hu 		    FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
4108281c58fSMingkai Hu 		    serdes1_prtcl_map);
4118281c58fSMingkai Hu #endif
412da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
413da4d620cSQianyu Gong 	serdes_init(FSL_SRDS_2,
414da4d620cSQianyu Gong 		    CONFIG_SYS_FSL_SERDES_ADDR,
415da4d620cSQianyu Gong 		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
416da4d620cSQianyu Gong 		    FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
417da4d620cSQianyu Gong 		    serdes2_prtcl_map);
418da4d620cSQianyu Gong #endif
4198281c58fSMingkai Hu }
420