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 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 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 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 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 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 131031acdbaSHou Zhiqiang __weak int get_serdes_volt(void) 132031acdbaSHou Zhiqiang { 133031acdbaSHou Zhiqiang return -1; 134031acdbaSHou Zhiqiang } 135031acdbaSHou Zhiqiang 136031acdbaSHou Zhiqiang __weak int set_serdes_volt(int svdd) 137031acdbaSHou Zhiqiang { 138031acdbaSHou Zhiqiang return -1; 139031acdbaSHou Zhiqiang } 140031acdbaSHou Zhiqiang 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 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