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 16*da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 17*da4d620cSQianyu Gong static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; 18*da4d620cSQianyu 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 258281c58fSMingkai Hu ret |= serdes1_prtcl_map[device]; 268281c58fSMingkai Hu #endif 27*da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 28*da4d620cSQianyu Gong ret |= serdes2_prtcl_map[device]; 29*da4d620cSQianyu Gong #endif 308281c58fSMingkai Hu 318281c58fSMingkai Hu return !!ret; 328281c58fSMingkai Hu } 338281c58fSMingkai Hu 348281c58fSMingkai Hu int serdes_get_first_lane(u32 sd, enum srds_prtcl device) 358281c58fSMingkai Hu { 368281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 378281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]); 388281c58fSMingkai Hu int i; 398281c58fSMingkai Hu 408281c58fSMingkai Hu switch (sd) { 418281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 428281c58fSMingkai Hu case FSL_SRDS_1: 438281c58fSMingkai Hu cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 448281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 458281c58fSMingkai Hu break; 468281c58fSMingkai Hu #endif 47*da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 48*da4d620cSQianyu Gong case FSL_SRDS_2: 49*da4d620cSQianyu Gong cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; 50*da4d620cSQianyu Gong cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; 51*da4d620cSQianyu Gong break; 52*da4d620cSQianyu Gong #endif 538281c58fSMingkai Hu default: 548281c58fSMingkai Hu printf("invalid SerDes%d\n", sd); 558281c58fSMingkai Hu break; 568281c58fSMingkai Hu } 578281c58fSMingkai Hu 588281c58fSMingkai Hu /* Is serdes enabled at all? */ 598281c58fSMingkai Hu if (unlikely(cfg == 0)) 608281c58fSMingkai Hu return -ENODEV; 618281c58fSMingkai Hu 628281c58fSMingkai Hu for (i = 0; i < SRDS_MAX_LANES; i++) { 638281c58fSMingkai Hu if (serdes_get_prtcl(sd, cfg, i) == device) 648281c58fSMingkai Hu return i; 658281c58fSMingkai Hu } 668281c58fSMingkai Hu 678281c58fSMingkai Hu return -ENODEV; 688281c58fSMingkai Hu } 698281c58fSMingkai Hu 708281c58fSMingkai Hu int get_serdes_protocol(void) 718281c58fSMingkai Hu { 728281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 738281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]) & 748281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 758281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 768281c58fSMingkai Hu 778281c58fSMingkai Hu return cfg; 788281c58fSMingkai Hu } 798281c58fSMingkai Hu 808281c58fSMingkai Hu const char *serdes_clock_to_string(u32 clock) 818281c58fSMingkai Hu { 828281c58fSMingkai Hu switch (clock) { 838281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_100: 848281c58fSMingkai Hu return "100"; 858281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_125: 868281c58fSMingkai Hu return "125"; 878281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_156_25: 888281c58fSMingkai Hu return "156.25"; 898281c58fSMingkai Hu default: 908281c58fSMingkai Hu return "100"; 918281c58fSMingkai Hu } 928281c58fSMingkai Hu } 938281c58fSMingkai Hu 948281c58fSMingkai Hu void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, 958281c58fSMingkai Hu u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) 968281c58fSMingkai Hu { 978281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 988281c58fSMingkai Hu u32 cfg; 998281c58fSMingkai Hu int lane; 1008281c58fSMingkai Hu 1011a338921STom Rini memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT); 1028281c58fSMingkai Hu 1038281c58fSMingkai Hu cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask; 1048281c58fSMingkai Hu cfg >>= sd_prctl_shift; 1058281c58fSMingkai Hu printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); 1068281c58fSMingkai Hu 1078281c58fSMingkai Hu if (!is_serdes_prtcl_valid(sd, cfg)) 1088281c58fSMingkai Hu printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); 1098281c58fSMingkai Hu 1108281c58fSMingkai Hu for (lane = 0; lane < SRDS_MAX_LANES; lane++) { 1118281c58fSMingkai Hu enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); 1128281c58fSMingkai Hu 1138281c58fSMingkai Hu if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) 1148281c58fSMingkai Hu debug("Unknown SerDes lane protocol %d\n", lane_prtcl); 1158281c58fSMingkai Hu else 1168281c58fSMingkai Hu serdes_prtcl_map[lane_prtcl] = 1; 1178281c58fSMingkai Hu } 1188281c58fSMingkai Hu } 1198281c58fSMingkai Hu 1208281c58fSMingkai Hu void fsl_serdes_init(void) 1218281c58fSMingkai Hu { 1228281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 1238281c58fSMingkai Hu serdes_init(FSL_SRDS_1, 1248281c58fSMingkai Hu CONFIG_SYS_FSL_SERDES_ADDR, 1258281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK, 1268281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT, 1278281c58fSMingkai Hu serdes1_prtcl_map); 1288281c58fSMingkai Hu #endif 129*da4d620cSQianyu Gong #ifdef CONFIG_SYS_FSL_SRDS_2 130*da4d620cSQianyu Gong serdes_init(FSL_SRDS_2, 131*da4d620cSQianyu Gong CONFIG_SYS_FSL_SERDES_ADDR, 132*da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK, 133*da4d620cSQianyu Gong FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT, 134*da4d620cSQianyu Gong serdes2_prtcl_map); 135*da4d620cSQianyu Gong #endif 1368281c58fSMingkai Hu } 137