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