1 /* 2 * Copyright 2014 Freescale Semiconductor, Inc. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <asm/arch/fsl_serdes.h> 9 #include <asm/arch/immap_ls102xa.h> 10 #include <asm/errno.h> 11 #include <asm/io.h> 12 #include "fsl_ls1_serdes.h" 13 14 #ifdef CONFIG_SYS_FSL_SRDS_1 15 static u64 serdes1_prtcl_map; 16 #endif 17 #ifdef CONFIG_SYS_FSL_SRDS_2 18 static u64 serdes2_prtcl_map; 19 #endif 20 21 int is_serdes_configured(enum srds_prtcl device) 22 { 23 u64 ret = 0; 24 25 #ifdef CONFIG_SYS_FSL_SRDS_1 26 ret |= (1ULL << device) & serdes1_prtcl_map; 27 #endif 28 #ifdef CONFIG_SYS_FSL_SRDS_2 29 ret |= (1ULL << device) & serdes2_prtcl_map; 30 #endif 31 32 return !!ret; 33 } 34 35 int serdes_get_first_lane(u32 sd, enum srds_prtcl device) 36 { 37 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 38 u32 cfg = in_be32(&gur->rcwsr[4]); 39 int i; 40 41 switch (sd) { 42 #ifdef CONFIG_SYS_FSL_SRDS_1 43 case FSL_SRDS_1: 44 cfg &= RCWSR4_SRDS1_PRTCL_MASK; 45 cfg >>= RCWSR4_SRDS1_PRTCL_SHIFT; 46 break; 47 #endif 48 #ifdef CONFIG_SYS_FSL_SRDS_2 49 case FSL_SRDS_2: 50 cfg &= RCWSR4_SRDS2_PRTCL_MASK; 51 cfg >>= RCWSR4_SRDS2_PRTCL_SHIFT; 52 break; 53 #endif 54 default: 55 printf("invalid SerDes%d\n", sd); 56 break; 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 u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift) 71 { 72 struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); 73 u64 serdes_prtcl_map = 0; 74 u32 cfg; 75 int lane; 76 77 cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask; 78 cfg >>= sd_prctl_shift; 79 printf("Using SERDES%d Protocol: %d (0x%x)\n", sd + 1, cfg, cfg); 80 81 if (!is_serdes_prtcl_valid(sd, cfg)) 82 printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); 83 84 for (lane = 0; lane < SRDS_MAX_LANES; lane++) { 85 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); 86 87 serdes_prtcl_map |= (1ULL << lane_prtcl); 88 } 89 90 return serdes_prtcl_map; 91 } 92 93 void fsl_serdes_init(void) 94 { 95 #ifdef CONFIG_SYS_FSL_SRDS_1 96 serdes1_prtcl_map = serdes_init(FSL_SRDS_1, 97 CONFIG_SYS_FSL_SERDES_ADDR, 98 RCWSR4_SRDS1_PRTCL_MASK, 99 RCWSR4_SRDS1_PRTCL_SHIFT); 100 #endif 101 #ifdef CONFIG_SYS_FSL_SRDS_2 102 serdes2_prtcl_map = serdes_init(FSL_SRDS_2, 103 CONFIG_SYS_FSL_SERDES_ADDR + 104 FSL_SRDS_2 * 0x1000, 105 RCWSR4_SRDS2_PRTCL_MASK, 106 RCWSR4_SRDS2_PRTCL_SHIFT); 107 #endif 108 } 109 110 const char *serdes_clock_to_string(u32 clock) 111 { 112 switch (clock) { 113 case SRDS_PLLCR0_RFCK_SEL_100: 114 return "100"; 115 case SRDS_PLLCR0_RFCK_SEL_125: 116 return "125"; 117 default: 118 return "100"; 119 } 120 } 121