1*8281c58fSMingkai Hu /* 2*8281c58fSMingkai Hu * Copyright 2015 Freescale Semiconductor, Inc. 3*8281c58fSMingkai Hu * 4*8281c58fSMingkai Hu * SPDX-License-Identifier: GPL-2.0+ 5*8281c58fSMingkai Hu */ 6*8281c58fSMingkai Hu 7*8281c58fSMingkai Hu #include <common.h> 8*8281c58fSMingkai Hu #include <asm/io.h> 9*8281c58fSMingkai Hu #include <asm/errno.h> 10*8281c58fSMingkai Hu #include <asm/arch/fsl_serdes.h> 11*8281c58fSMingkai Hu #include <asm/arch/soc.h> 12*8281c58fSMingkai Hu 13*8281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 14*8281c58fSMingkai Hu static u8 serdes1_prtcl_map[SERDES_PRCTL_COUNT]; 15*8281c58fSMingkai Hu #endif 16*8281c58fSMingkai Hu 17*8281c58fSMingkai Hu int is_serdes_configured(enum srds_prtcl device) 18*8281c58fSMingkai Hu { 19*8281c58fSMingkai Hu int ret = 0; 20*8281c58fSMingkai Hu 21*8281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 22*8281c58fSMingkai Hu ret |= serdes1_prtcl_map[device]; 23*8281c58fSMingkai Hu #endif 24*8281c58fSMingkai Hu 25*8281c58fSMingkai Hu return !!ret; 26*8281c58fSMingkai Hu } 27*8281c58fSMingkai Hu 28*8281c58fSMingkai Hu int serdes_get_first_lane(u32 sd, enum srds_prtcl device) 29*8281c58fSMingkai Hu { 30*8281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 31*8281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]); 32*8281c58fSMingkai Hu int i; 33*8281c58fSMingkai Hu 34*8281c58fSMingkai Hu switch (sd) { 35*8281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 36*8281c58fSMingkai Hu case FSL_SRDS_1: 37*8281c58fSMingkai Hu cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 38*8281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 39*8281c58fSMingkai Hu break; 40*8281c58fSMingkai Hu #endif 41*8281c58fSMingkai Hu default: 42*8281c58fSMingkai Hu printf("invalid SerDes%d\n", sd); 43*8281c58fSMingkai Hu break; 44*8281c58fSMingkai Hu } 45*8281c58fSMingkai Hu 46*8281c58fSMingkai Hu /* Is serdes enabled at all? */ 47*8281c58fSMingkai Hu if (unlikely(cfg == 0)) 48*8281c58fSMingkai Hu return -ENODEV; 49*8281c58fSMingkai Hu 50*8281c58fSMingkai Hu for (i = 0; i < SRDS_MAX_LANES; i++) { 51*8281c58fSMingkai Hu if (serdes_get_prtcl(sd, cfg, i) == device) 52*8281c58fSMingkai Hu return i; 53*8281c58fSMingkai Hu } 54*8281c58fSMingkai Hu 55*8281c58fSMingkai Hu return -ENODEV; 56*8281c58fSMingkai Hu } 57*8281c58fSMingkai Hu 58*8281c58fSMingkai Hu int get_serdes_protocol(void) 59*8281c58fSMingkai Hu { 60*8281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 61*8281c58fSMingkai Hu u32 cfg = gur_in32(&gur->rcwsr[4]) & 62*8281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 63*8281c58fSMingkai Hu cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 64*8281c58fSMingkai Hu 65*8281c58fSMingkai Hu return cfg; 66*8281c58fSMingkai Hu } 67*8281c58fSMingkai Hu 68*8281c58fSMingkai Hu const char *serdes_clock_to_string(u32 clock) 69*8281c58fSMingkai Hu { 70*8281c58fSMingkai Hu switch (clock) { 71*8281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_100: 72*8281c58fSMingkai Hu return "100"; 73*8281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_125: 74*8281c58fSMingkai Hu return "125"; 75*8281c58fSMingkai Hu case SRDS_PLLCR0_RFCK_SEL_156_25: 76*8281c58fSMingkai Hu return "156.25"; 77*8281c58fSMingkai Hu default: 78*8281c58fSMingkai Hu return "100"; 79*8281c58fSMingkai Hu } 80*8281c58fSMingkai Hu } 81*8281c58fSMingkai Hu 82*8281c58fSMingkai Hu void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, 83*8281c58fSMingkai Hu u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) 84*8281c58fSMingkai Hu { 85*8281c58fSMingkai Hu struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 86*8281c58fSMingkai Hu u32 cfg; 87*8281c58fSMingkai Hu int lane; 88*8281c58fSMingkai Hu 89*8281c58fSMingkai Hu memset(serdes_prtcl_map, 0, sizeof(serdes_prtcl_map)); 90*8281c58fSMingkai Hu 91*8281c58fSMingkai Hu cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask; 92*8281c58fSMingkai Hu cfg >>= sd_prctl_shift; 93*8281c58fSMingkai Hu printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); 94*8281c58fSMingkai Hu 95*8281c58fSMingkai Hu if (!is_serdes_prtcl_valid(sd, cfg)) 96*8281c58fSMingkai Hu printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); 97*8281c58fSMingkai Hu 98*8281c58fSMingkai Hu for (lane = 0; lane < SRDS_MAX_LANES; lane++) { 99*8281c58fSMingkai Hu enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); 100*8281c58fSMingkai Hu 101*8281c58fSMingkai Hu if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) 102*8281c58fSMingkai Hu debug("Unknown SerDes lane protocol %d\n", lane_prtcl); 103*8281c58fSMingkai Hu else 104*8281c58fSMingkai Hu serdes_prtcl_map[lane_prtcl] = 1; 105*8281c58fSMingkai Hu } 106*8281c58fSMingkai Hu } 107*8281c58fSMingkai Hu 108*8281c58fSMingkai Hu void fsl_serdes_init(void) 109*8281c58fSMingkai Hu { 110*8281c58fSMingkai Hu #ifdef CONFIG_SYS_FSL_SRDS_1 111*8281c58fSMingkai Hu serdes_init(FSL_SRDS_1, 112*8281c58fSMingkai Hu CONFIG_SYS_FSL_SERDES_ADDR, 113*8281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK, 114*8281c58fSMingkai Hu FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT, 115*8281c58fSMingkai Hu serdes1_prtcl_map); 116*8281c58fSMingkai Hu #endif 117*8281c58fSMingkai Hu } 118