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 #ifdef CONFIG_SYS_FSL_SRDS_2 17 static u8 serdes2_prtcl_map[SERDES_PRCTL_COUNT]; 18 #endif 19 20 int is_serdes_configured(enum srds_prtcl device) 21 { 22 int ret = 0; 23 24 #ifdef CONFIG_SYS_FSL_SRDS_1 25 ret |= serdes1_prtcl_map[device]; 26 #endif 27 #ifdef CONFIG_SYS_FSL_SRDS_2 28 ret |= serdes2_prtcl_map[device]; 29 #endif 30 31 return !!ret; 32 } 33 34 int serdes_get_first_lane(u32 sd, enum srds_prtcl device) 35 { 36 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 37 u32 cfg = gur_in32(&gur->rcwsr[4]); 38 int i; 39 40 switch (sd) { 41 #ifdef CONFIG_SYS_FSL_SRDS_1 42 case FSL_SRDS_1: 43 cfg &= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 44 cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 45 break; 46 #endif 47 #ifdef CONFIG_SYS_FSL_SRDS_2 48 case FSL_SRDS_2: 49 cfg &= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK; 50 cfg >>= FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT; 51 break; 52 #endif 53 default: 54 printf("invalid SerDes%d\n", sd); 55 break; 56 } 57 58 /* Is serdes enabled at all? */ 59 if (unlikely(cfg == 0)) 60 return -ENODEV; 61 62 for (i = 0; i < SRDS_MAX_LANES; i++) { 63 if (serdes_get_prtcl(sd, cfg, i) == device) 64 return i; 65 } 66 67 return -ENODEV; 68 } 69 70 int get_serdes_protocol(void) 71 { 72 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 73 u32 cfg = gur_in32(&gur->rcwsr[4]) & 74 FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK; 75 cfg >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT; 76 77 return cfg; 78 } 79 80 const char *serdes_clock_to_string(u32 clock) 81 { 82 switch (clock) { 83 case SRDS_PLLCR0_RFCK_SEL_100: 84 return "100"; 85 case SRDS_PLLCR0_RFCK_SEL_125: 86 return "125"; 87 case SRDS_PLLCR0_RFCK_SEL_156_25: 88 return "156.25"; 89 default: 90 return "100"; 91 } 92 } 93 94 void serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift, 95 u8 serdes_prtcl_map[SERDES_PRCTL_COUNT]) 96 { 97 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 98 u32 cfg; 99 int lane; 100 101 memset(serdes_prtcl_map, 0, sizeof(u8) * SERDES_PRCTL_COUNT); 102 103 cfg = gur_in32(&gur->rcwsr[4]) & sd_prctl_mask; 104 cfg >>= sd_prctl_shift; 105 printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); 106 107 if (!is_serdes_prtcl_valid(sd, cfg)) 108 printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); 109 110 for (lane = 0; lane < SRDS_MAX_LANES; lane++) { 111 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); 112 113 if (unlikely(lane_prtcl >= SERDES_PRCTL_COUNT)) 114 debug("Unknown SerDes lane protocol %d\n", lane_prtcl); 115 else 116 serdes_prtcl_map[lane_prtcl] = 1; 117 } 118 } 119 120 void fsl_serdes_init(void) 121 { 122 #ifdef CONFIG_SYS_FSL_SRDS_1 123 serdes_init(FSL_SRDS_1, 124 CONFIG_SYS_FSL_SERDES_ADDR, 125 FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK, 126 FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT, 127 serdes1_prtcl_map); 128 #endif 129 #ifdef CONFIG_SYS_FSL_SRDS_2 130 serdes_init(FSL_SRDS_2, 131 CONFIG_SYS_FSL_SERDES_ADDR, 132 FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_MASK, 133 FSL_CHASSIS2_RCWSR4_SRDS2_PRTCL_SHIFT, 134 serdes2_prtcl_map); 135 #endif 136 } 137