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 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 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 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 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 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 132*031acdbaSHou Zhiqiang __weak int get_serdes_volt(void) 133*031acdbaSHou Zhiqiang { 134*031acdbaSHou Zhiqiang return -1; 135*031acdbaSHou Zhiqiang } 136*031acdbaSHou Zhiqiang 137*031acdbaSHou Zhiqiang __weak int set_serdes_volt(int svdd) 138*031acdbaSHou Zhiqiang { 139*031acdbaSHou Zhiqiang return -1; 140*031acdbaSHou Zhiqiang } 141*031acdbaSHou Zhiqiang 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 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