18281c58fSMingkai Hu /*
28281c58fSMingkai Hu * Copyright 2015 Freescale Semiconductor, Inc.
38281c58fSMingkai Hu *
48281c58fSMingkai Hu * SPDX-License-Identifier: GPL-2.0+
58281c58fSMingkai Hu */
68281c58fSMingkai Hu
78281c58fSMingkai Hu #include <common.h>
88281c58fSMingkai Hu #include <asm/io.h>
91221ce45SMasahiro Yamada #include <linux/errno.h>
108281c58fSMingkai Hu #include <asm/arch/fsl_serdes.h>
118281c58fSMingkai Hu #include <asm/arch/soc.h>
128281c58fSMingkai Hu
138281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
148281c58fSMingkai Hu static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT];
158281c58fSMingkai Hu #endif
16da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
17da4d620cSQianyu Gong static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT];
18da4d620cSQianyu Gong #endif
198281c58fSMingkai Hu
is_serdes_configured(enum srds_prtcl device)208281c58fSMingkai Hu int is_serdes_configured(enum srds_prtcl device)
218281c58fSMingkai Hu {
228281c58fSMingkai Hu int ret = 0;
238281c58fSMingkai Hu
248281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
2571fe2225SHou Zhiqiang if (!serdes1_prtcl_map[NONE])
2671fe2225SHou Zhiqiang fsl_serdes_init();
2771fe2225SHou Zhiqiang
288281c58fSMingkai Hu ret |= serdes1_prtcl_map[device];
298281c58fSMingkai Hu #endif
30da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
3171fe2225SHou Zhiqiang if (!serdes2_prtcl_map[NONE])
3271fe2225SHou Zhiqiang fsl_serdes_init();
3371fe2225SHou Zhiqiang
34da4d620cSQianyu Gong ret |= serdes2_prtcl_map[device];
35da4d620cSQianyu Gong #endif
368281c58fSMingkai Hu
378281c58fSMingkai Hu return !!ret;
388281c58fSMingkai Hu }
398281c58fSMingkai Hu
serdes_get_first_lane(u32 sd,enum srds_prtcl device)408281c58fSMingkai Hu int serdes_get_first_lane(u32 sd, enum srds_prtcl device)
418281c58fSMingkai Hu {
428281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
438281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]);
448281c58fSMingkai Hu int i;
458281c58fSMingkai Hu
468281c58fSMingkai Hu switch (sd) {
478281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
488281c58fSMingkai Hu case FSL_SRDS_1:
498281c58fSMingkai Hu cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
508281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
518281c58fSMingkai Hu break;
528281c58fSMingkai Hu #endif
53da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
54da4d620cSQianyu Gong case FSL_SRDS_2:
55da4d620cSQianyu Gong cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
56da4d620cSQianyu Gong cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
57da4d620cSQianyu Gong break;
58da4d620cSQianyu Gong #endif
598281c58fSMingkai Hu default:
608281c58fSMingkai Hu printf("invalid SerDes%d\n", sd);
618281c58fSMingkai Hu break;
628281c58fSMingkai Hu }
638281c58fSMingkai Hu
648281c58fSMingkai Hu /* Is serdes enabled at all? */
658281c58fSMingkai Hu if (unlikely(cfg == 0))
668281c58fSMingkai Hu return -ENODEV;
678281c58fSMingkai Hu
688281c58fSMingkai Hu for (i = 0; i < SRDS_MAX_LANES; i++) {
698281c58fSMingkai Hu if (serdes_get_prtcl(sd, cfg, i) == device)
708281c58fSMingkai Hu return i;
718281c58fSMingkai Hu }
728281c58fSMingkai Hu
738281c58fSMingkai Hu return -ENODEV;
748281c58fSMingkai Hu }
758281c58fSMingkai Hu
get_serdes_protocol(void)768281c58fSMingkai Hu int get_serdes_protocol(void)
778281c58fSMingkai Hu {
788281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
798281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]) &
808281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
818281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
828281c58fSMingkai Hu
838281c58fSMingkai Hu return cfg;
848281c58fSMingkai Hu }
858281c58fSMingkai Hu
serdes_clock_to_string(u32 clock)868281c58fSMingkai Hu const char *serdes_clock_to_string(u32 clock)
878281c58fSMingkai Hu {
888281c58fSMingkai Hu switch (clock) {
898281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_100:
908281c58fSMingkai Hu return "100";
918281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_125:
928281c58fSMingkai Hu return "125";
938281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_156_25:
948281c58fSMingkai Hu return "156.25";
958281c58fSMingkai Hu default:
968281c58fSMingkai Hu return "100";
978281c58fSMingkai Hu }
988281c58fSMingkai Hu }
998281c58fSMingkai Hu
serdes_init(u32 sd,u32 sd_addr,u32 sd_prctl_mask,u32 sd_prctl_shift,u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])1008281c58fSMingkai Hu void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift,
1018281c58fSMingkai Hu u8 serdes_prtcl_map[SERDES_PRCTL_COUNT])
1028281c58fSMingkai Hu {
1038281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
1048281c58fSMingkai Hu u32 cfg;
1058281c58fSMingkai Hu int lane;
1068281c58fSMingkai Hu
10771fe2225SHou Zhiqiang if (serdes_prtcl_map[NONE])
10871fe2225SHou Zhiqiang return;
10971fe2225SHou Zhiqiang
1101a338921STom Rini memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT);
1118281c58fSMingkai Hu
1128281c58fSMingkai Hu cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask;
1138281c58fSMingkai Hu cfg >>= sd_prctl_shift;
1148281c58fSMingkai Hu printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg);
1158281c58fSMingkai Hu
1168281c58fSMingkai Hu if (!is_serdes_prtcl_valid(sd, cfg))
1178281c58fSMingkai Hu printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg);
1188281c58fSMingkai Hu
1198281c58fSMingkai Hu for (lane = 0; lane < SRDS_MAX_LANES; lane++) {
1208281c58fSMingkai Hu enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane);
1218281c58fSMingkai Hu
1228281c58fSMingkai Hu if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT))
1238281c58fSMingkai Hu debug("Unknown SerDes lane protocol %d\n", lane_prtcl);
1248281c58fSMingkai Hu else
1258281c58fSMingkai Hu serdes_prtcl_map[lane_prtcl] = 1;
1268281c58fSMingkai Hu }
12771fe2225SHou Zhiqiang
12871fe2225SHou Zhiqiang /* Set the first element to indicate serdes has been initialized */
12971fe2225SHou Zhiqiang serdes_prtcl_map[NONE] = 1;
1308281c58fSMingkai Hu }
1318281c58fSMingkai Hu
get_serdes_volt(void)132*031acdbaSHou Zhiqiang __weak int get_serdes_volt(void)
133*031acdbaSHou Zhiqiang {
134*031acdbaSHou Zhiqiang return -1;
135*031acdbaSHou Zhiqiang }
136*031acdbaSHou Zhiqiang
set_serdes_volt(int svdd)137*031acdbaSHou Zhiqiang __weak int set_serdes_volt(int svdd)
138*031acdbaSHou Zhiqiang {
139*031acdbaSHou Zhiqiang return -1;
140*031acdbaSHou Zhiqiang }
141*031acdbaSHou Zhiqiang
setup_serdes_volt(u32 svdd)142*031acdbaSHou Zhiqiang int setup_serdes_volt(u32 svdd)
143*031acdbaSHou Zhiqiang {
144*031acdbaSHou Zhiqiang struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
145*031acdbaSHou Zhiqiang struct ccsr_serdes *serdes1_base;
146*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
147*031acdbaSHou Zhiqiang struct ccsr_serdes *serdes2_base;
148*031acdbaSHou Zhiqiang #endif
149*031acdbaSHou Zhiqiang u32 cfg_rcw4 = gur_in32(&gur->rcwsr[4]);
150*031acdbaSHou Zhiqiang u32 cfg_rcw5 = gur_in32(&gur->rcwsr[5]);
151*031acdbaSHou Zhiqiang u32 cfg_tmp, reg = 0;
152*031acdbaSHou Zhiqiang int svdd_cur, svdd_tar;
153*031acdbaSHou Zhiqiang int ret;
154*031acdbaSHou Zhiqiang int i;
155*031acdbaSHou Zhiqiang
156*031acdbaSHou Zhiqiang /* Only support switch SVDD to 900mV/1000mV */
157*031acdbaSHou Zhiqiang if (svdd != 900 && svdd != 1000)
158*031acdbaSHou Zhiqiang return -EINVAL;
159*031acdbaSHou Zhiqiang
160*031acdbaSHou Zhiqiang svdd_tar = svdd;
161*031acdbaSHou Zhiqiang svdd_cur = get_serdes_volt();
162*031acdbaSHou Zhiqiang if (svdd_cur < 0)
163*031acdbaSHou Zhiqiang return -EINVAL;
164*031acdbaSHou Zhiqiang
165*031acdbaSHou Zhiqiang debug("%s: current SVDD: %dmV; target SVDD: %dmV\n",
166*031acdbaSHou Zhiqiang __func__, svdd_cur, svdd_tar);
167*031acdbaSHou Zhiqiang if (svdd_cur == svdd_tar)
168*031acdbaSHou Zhiqiang return 0;
169*031acdbaSHou Zhiqiang
170*031acdbaSHou Zhiqiang serdes1_base = (void *)CONFIG_SYS_FSL_SERDES_ADDR;
171*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
172*031acdbaSHou Zhiqiang serdes2_base = (void *)serdes1_base + 0x10000;
173*031acdbaSHou Zhiqiang #endif
174*031acdbaSHou Zhiqiang
175*031acdbaSHou Zhiqiang /* Put the all enabled lanes in reset */
176*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
177*031acdbaSHou Zhiqiang cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
178*031acdbaSHou Zhiqiang cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
179*031acdbaSHou Zhiqiang
180*031acdbaSHou Zhiqiang for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
181*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->lane[i].gcr0);
182*031acdbaSHou Zhiqiang reg &= 0xFF9FFFFF;
183*031acdbaSHou Zhiqiang out_be32(&serdes1_base->lane[i].gcr0, reg);
184*031acdbaSHou Zhiqiang }
185*031acdbaSHou Zhiqiang #endif
186*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
187*031acdbaSHou Zhiqiang cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
188*031acdbaSHou Zhiqiang cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
189*031acdbaSHou Zhiqiang
190*031acdbaSHou Zhiqiang for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
191*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->lane[i].gcr0);
192*031acdbaSHou Zhiqiang reg &= 0xFF9FFFFF;
193*031acdbaSHou Zhiqiang out_be32(&serdes2_base->lane[i].gcr0, reg);
194*031acdbaSHou Zhiqiang }
195*031acdbaSHou Zhiqiang #endif
196*031acdbaSHou Zhiqiang
197*031acdbaSHou Zhiqiang /* Put the all enabled PLL in reset */
198*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
199*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
200*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
201*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
202*031acdbaSHou Zhiqiang reg &= 0xFFFFFFBF;
203*031acdbaSHou Zhiqiang reg |= 0x10000000;
204*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
205*031acdbaSHou Zhiqiang udelay(1);
206*031acdbaSHou Zhiqiang
207*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
208*031acdbaSHou Zhiqiang reg &= 0xFFFFFF1F;
209*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
210*031acdbaSHou Zhiqiang }
211*031acdbaSHou Zhiqiang udelay(1);
212*031acdbaSHou Zhiqiang #endif
213*031acdbaSHou Zhiqiang
214*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
215*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
216*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
217*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
218*031acdbaSHou Zhiqiang reg &= 0xFFFFFFBF;
219*031acdbaSHou Zhiqiang reg |= 0x10000000;
220*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
221*031acdbaSHou Zhiqiang udelay(1);
222*031acdbaSHou Zhiqiang
223*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
224*031acdbaSHou Zhiqiang reg &= 0xFFFFFF1F;
225*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
226*031acdbaSHou Zhiqiang }
227*031acdbaSHou Zhiqiang udelay(1);
228*031acdbaSHou Zhiqiang #endif
229*031acdbaSHou Zhiqiang
230*031acdbaSHou Zhiqiang /* Put the Rx/Tx calibration into reset */
231*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
232*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->srdstcalcr);
233*031acdbaSHou Zhiqiang reg &= 0xF7FFFFFF;
234*031acdbaSHou Zhiqiang out_be32(&serdes1_base->srdstcalcr, reg);
235*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->srdsrcalcr);
236*031acdbaSHou Zhiqiang reg &= 0xF7FFFFFF;
237*031acdbaSHou Zhiqiang out_be32(&serdes1_base->srdsrcalcr, reg);
238*031acdbaSHou Zhiqiang
239*031acdbaSHou Zhiqiang #endif
240*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
241*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->srdstcalcr);
242*031acdbaSHou Zhiqiang reg &= 0xF7FFFFFF;
243*031acdbaSHou Zhiqiang out_be32(&serdes2_base->srdstcalcr, reg);
244*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->srdsrcalcr);
245*031acdbaSHou Zhiqiang reg &= 0xF7FFFFFF;
246*031acdbaSHou Zhiqiang out_be32(&serdes2_base->srdsrcalcr, reg);
247*031acdbaSHou Zhiqiang #endif
248*031acdbaSHou Zhiqiang
249*031acdbaSHou Zhiqiang /*
250*031acdbaSHou Zhiqiang * If SVDD set failed, will not return directly, so that the
251*031acdbaSHou Zhiqiang * serdes lanes can complete reseting.
252*031acdbaSHou Zhiqiang */
253*031acdbaSHou Zhiqiang ret = set_serdes_volt(svdd_tar);
254*031acdbaSHou Zhiqiang if (ret)
255*031acdbaSHou Zhiqiang printf("%s: Failed to set SVDD\n", __func__);
256*031acdbaSHou Zhiqiang
257*031acdbaSHou Zhiqiang /* Wait for SVDD to stabilize */
258*031acdbaSHou Zhiqiang udelay(100);
259*031acdbaSHou Zhiqiang
260*031acdbaSHou Zhiqiang /* For each PLL that’s not disabled via RCW */
261*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
262*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
263*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
264*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
265*031acdbaSHou Zhiqiang reg |= 0x00000020;
266*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
267*031acdbaSHou Zhiqiang udelay(1);
268*031acdbaSHou Zhiqiang
269*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
270*031acdbaSHou Zhiqiang reg |= 0x00000080;
271*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
272*031acdbaSHou Zhiqiang
273*031acdbaSHou Zhiqiang /* Take the Rx/Tx calibration out of reset */
274*031acdbaSHou Zhiqiang if (!(cfg_tmp == 0x3 && i == 1)) {
275*031acdbaSHou Zhiqiang udelay(1);
276*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->srdstcalcr);
277*031acdbaSHou Zhiqiang reg |= 0x08000000;
278*031acdbaSHou Zhiqiang out_be32(&serdes1_base->srdstcalcr, reg);
279*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->srdsrcalcr);
280*031acdbaSHou Zhiqiang reg |= 0x08000000;
281*031acdbaSHou Zhiqiang out_be32(&serdes1_base->srdsrcalcr, reg);
282*031acdbaSHou Zhiqiang }
283*031acdbaSHou Zhiqiang }
284*031acdbaSHou Zhiqiang udelay(1);
285*031acdbaSHou Zhiqiang #endif
286*031acdbaSHou Zhiqiang
287*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
288*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
289*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
290*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
291*031acdbaSHou Zhiqiang reg |= 0x00000020;
292*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
293*031acdbaSHou Zhiqiang udelay(1);
294*031acdbaSHou Zhiqiang
295*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
296*031acdbaSHou Zhiqiang reg |= 0x00000080;
297*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
298*031acdbaSHou Zhiqiang
299*031acdbaSHou Zhiqiang /* Take the Rx/Tx calibration out of reset */
300*031acdbaSHou Zhiqiang if (!(cfg_tmp == 0x3 && i == 1)) {
301*031acdbaSHou Zhiqiang udelay(1);
302*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->srdstcalcr);
303*031acdbaSHou Zhiqiang reg |= 0x08000000;
304*031acdbaSHou Zhiqiang out_be32(&serdes2_base->srdstcalcr, reg);
305*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->srdsrcalcr);
306*031acdbaSHou Zhiqiang reg |= 0x08000000;
307*031acdbaSHou Zhiqiang out_be32(&serdes2_base->srdsrcalcr, reg);
308*031acdbaSHou Zhiqiang }
309*031acdbaSHou Zhiqiang }
310*031acdbaSHou Zhiqiang udelay(1);
311*031acdbaSHou Zhiqiang
312*031acdbaSHou Zhiqiang #endif
313*031acdbaSHou Zhiqiang
314*031acdbaSHou Zhiqiang /* Wait for at lesat 625us to ensure the PLLs being reset are locked */
315*031acdbaSHou Zhiqiang udelay(800);
316*031acdbaSHou Zhiqiang
317*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
318*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
319*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
320*031acdbaSHou Zhiqiang /* if the PLL is not locked, set RST_ERR */
321*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].pllcr0);
322*031acdbaSHou Zhiqiang if (!((reg >> 23) & 0x1)) {
323*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
324*031acdbaSHou Zhiqiang reg |= 0x20000000;
325*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
326*031acdbaSHou Zhiqiang } else {
327*031acdbaSHou Zhiqiang udelay(1);
328*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
329*031acdbaSHou Zhiqiang reg &= 0xFFFFFFEF;
330*031acdbaSHou Zhiqiang reg |= 0x00000040;
331*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
332*031acdbaSHou Zhiqiang udelay(1);
333*031acdbaSHou Zhiqiang }
334*031acdbaSHou Zhiqiang }
335*031acdbaSHou Zhiqiang #endif
336*031acdbaSHou Zhiqiang
337*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
338*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
339*031acdbaSHou Zhiqiang for (i = 0; i < 2 && !(cfg_tmp & (0x1 << (1 - i))); i++) {
340*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].pllcr0);
341*031acdbaSHou Zhiqiang if (!((reg >> 23) & 0x1)) {
342*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
343*031acdbaSHou Zhiqiang reg |= 0x20000000;
344*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
345*031acdbaSHou Zhiqiang } else {
346*031acdbaSHou Zhiqiang udelay(1);
347*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
348*031acdbaSHou Zhiqiang reg &= 0xFFFFFFEF;
349*031acdbaSHou Zhiqiang reg |= 0x00000040;
350*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
351*031acdbaSHou Zhiqiang udelay(1);
352*031acdbaSHou Zhiqiang }
353*031acdbaSHou Zhiqiang }
354*031acdbaSHou Zhiqiang #endif
355*031acdbaSHou Zhiqiang
356*031acdbaSHou Zhiqiang /* Take the all enabled lanes out of reset */
357*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
358*031acdbaSHou Zhiqiang cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
359*031acdbaSHou Zhiqiang cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
360*031acdbaSHou Zhiqiang
361*031acdbaSHou Zhiqiang for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
362*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->lane[i].gcr0);
363*031acdbaSHou Zhiqiang reg |= 0x00600000;
364*031acdbaSHou Zhiqiang out_be32(&serdes1_base->lane[i].gcr0, reg);
365*031acdbaSHou Zhiqiang }
366*031acdbaSHou Zhiqiang #endif
367*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
368*031acdbaSHou Zhiqiang cfg_tmp = cfg_rcw4 & FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK;
369*031acdbaSHou Zhiqiang cfg_tmp >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT;
370*031acdbaSHou Zhiqiang
371*031acdbaSHou Zhiqiang for (i = 0; i < 4 && cfg_tmp & (0xf << (3 - i)); i++) {
372*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->lane[i].gcr0);
373*031acdbaSHou Zhiqiang reg |= 0x00600000;
374*031acdbaSHou Zhiqiang out_be32(&serdes2_base->lane[i].gcr0, reg);
375*031acdbaSHou Zhiqiang }
376*031acdbaSHou Zhiqiang #endif
377*031acdbaSHou Zhiqiang /* For each PLL being reset, and achieved PLL lock set RST_DONE */
378*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_1
379*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 22) & 0x3;
380*031acdbaSHou Zhiqiang for (i = 0; i < 2; i++) {
381*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].pllcr0);
382*031acdbaSHou Zhiqiang if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
383*031acdbaSHou Zhiqiang reg = in_be32(&serdes1_base->bank[i].rstctl);
384*031acdbaSHou Zhiqiang reg |= 0x40000000;
385*031acdbaSHou Zhiqiang out_be32(&serdes1_base->bank[i].rstctl, reg);
386*031acdbaSHou Zhiqiang }
387*031acdbaSHou Zhiqiang }
388*031acdbaSHou Zhiqiang #endif
389*031acdbaSHou Zhiqiang #ifdef CONFIG_SYS_FSL_SRDS_2
390*031acdbaSHou Zhiqiang cfg_tmp = (cfg_rcw5 >> 20) & 0x3;
391*031acdbaSHou Zhiqiang for (i = 0; i < 2; i++) {
392*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].pllcr0);
393*031acdbaSHou Zhiqiang if (!(cfg_tmp & (0x1 << (1 - i))) && ((reg >> 23) & 0x1)) {
394*031acdbaSHou Zhiqiang reg = in_be32(&serdes2_base->bank[i].rstctl);
395*031acdbaSHou Zhiqiang reg |= 0x40000000;
396*031acdbaSHou Zhiqiang out_be32(&serdes2_base->bank[i].rstctl, reg);
397*031acdbaSHou Zhiqiang }
398*031acdbaSHou Zhiqiang }
399*031acdbaSHou Zhiqiang #endif
400*031acdbaSHou Zhiqiang
401*031acdbaSHou Zhiqiang return ret;
402*031acdbaSHou Zhiqiang }
403*031acdbaSHou Zhiqiang
fsl_serdes_init(void)4048281c58fSMingkai Hu void fsl_serdes_init(void)
4058281c58fSMingkai Hu {
4068281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1
4078281c58fSMingkai Hu serdes_init(FSL_SRDS_1,
4088281c58fSMingkai Hu CONFIG_SYS_FSL_SERDES_ADDR,
4098281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK,
4108281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT,
4118281c58fSMingkai Hu serdes1_prtcl_map);
4128281c58fSMingkai Hu #endif
413da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2
414da4d620cSQianyu Gong serdes_init(FSL_SRDS_2,
415da4d620cSQianyu Gong CONFIG_SYS_FSL_SERDES_ADDR,
416da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK,
417da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT,
418da4d620cSQianyu Gong serdes2_prtcl_map);
419da4d620cSQianyu Gong #endif
4208281c58fSMingkai Hu }
421