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