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> 98281c58fSMingkai Hu #include <asm/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 25*71fe2225SHou Zhiqiang if (!serdes1_prtcl_map[NONE]) 26*71fe2225SHou Zhiqiang fsl_serdes_init(); 27*71fe2225SHou Zhiqiang 288281c58fSMingkai Hu ret |= serdes1_prtcl_map[device]; 298281c58fSMingkai Hu #endif 30da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 31*71fe2225SHou Zhiqiang if (!serdes2_prtcl_map[NONE]) 32*71fe2225SHou Zhiqiang fsl_serdes_init(); 33*71fe2225SHou 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 107*71fe2225SHou Zhiqiang if (serdes_prtcl_map[NONE]) 108*71fe2225SHou Zhiqiang return; 109*71fe2225SHou 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 } 127*71fe2225SHou Zhiqiang 128*71fe2225SHou Zhiqiang /* Set the first element to indicate serdes has been initialized */ 129*71fe2225SHou Zhiqiang serdes_prtcl_map[NONE] = 1; 1308281c58fSMingkai Hu } 1318281c58fSMingkai Hu 1328281c58fSMingkai Hu void fsl_serdes_init(void) 1338281c58fSMingkai Hu { 1348281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 1358281c58fSMingkai Hu serdes_init(FSL_SRDS_1, 1368281c58fSMingkai Hu CONFIG_SYS_FSL_SERDES_ADDR, 1378281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK, 1388281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT, 1398281c58fSMingkai Hu serdes1_prtcl_map); 1408281c58fSMingkai Hu #endif 141da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 142da4d620cSQianyu Gong serdes_init(FSL_SRDS_2, 143da4d620cSQianyu Gong CONFIG_SYS_FSL_SERDES_ADDR, 144da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK, 145da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT, 146da4d620cSQianyu Gong serdes2_prtcl_map); 147da4d620cSQianyu Gong #endif 1488281c58fSMingkai Hu } 149