1 /* 2 * Copyright 2012 Freescale Semiconductor, Inc. 3 * 4 * See file CREDITS for list of people who contributed to this 5 * project. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License as 9 * published by the Free Software Foundation; either version 2 of 10 * the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20 * MA 02111-1307 USA 21 */ 22 23 #include <common.h> 24 #include <asm/fsl_serdes.h> 25 #include <asm/immap_85xx.h> 26 #include <asm/io.h> 27 #include <asm/processor.h> 28 #include <asm/fsl_law.h> 29 #include <asm/errno.h> 30 #include "fsl_corenet2_serdes.h" 31 32 static u64 serdes1_prtcl_map; 33 static u64 serdes2_prtcl_map; 34 #ifdef CONFIG_SYS_FSL_SRDS_3 35 static u64 serdes3_prtcl_map; 36 #endif 37 #ifdef CONFIG_SYS_FSL_SRDS_4 38 static u64 serdes4_prtcl_map; 39 #endif 40 41 #ifdef DEBUG 42 static const char *serdes_prtcl_str[] = { 43 [NONE] = "NA", 44 [PCIE1] = "PCIE1", 45 [PCIE2] = "PCIE2", 46 [PCIE3] = "PCIE3", 47 [PCIE4] = "PCIE4", 48 [SATA1] = "SATA1", 49 [SATA2] = "SATA2", 50 [SRIO1] = "SRIO1", 51 [SRIO2] = "SRIO2", 52 [SGMII_FM1_DTSEC1] = "SGMII_FM1_DTSEC1", 53 [SGMII_FM1_DTSEC2] = "SGMII_FM1_DTSEC2", 54 [SGMII_FM1_DTSEC3] = "SGMII_FM1_DTSEC3", 55 [SGMII_FM1_DTSEC4] = "SGMII_FM1_DTSEC4", 56 [SGMII_FM1_DTSEC5] = "SGMII_FM1_DTSEC5", 57 [SGMII_FM1_DTSEC6] = "SGMII_FM1_DTSEC6", 58 [SGMII_FM2_DTSEC1] = "SGMII_FM2_DTSEC1", 59 [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2", 60 [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3", 61 [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4", 62 [XAUI_FM1] = "XAUI_FM1", 63 [XAUI_FM2] = "XAUI_FM2", 64 [AURORA] = "DEBUG", 65 [CPRI1] = "CPRI1", 66 [CPRI2] = "CPRI2", 67 [CPRI3] = "CPRI3", 68 [CPRI4] = "CPRI4", 69 [CPRI5] = "CPRI5", 70 [CPRI6] = "CPRI6", 71 [CPRI7] = "CPRI7", 72 [CPRI8] = "CPRI8", 73 [XAUI_FM1_MAC9] = "XAUI_FM1_MAC9", 74 [XAUI_FM1_MAC10] = "XAUI_FM1_MAC10", 75 [XAUI_FM2_MAC9] = "XAUI_FM2_MAC9", 76 [XAUI_FM2_MAC10] = "XAUI_FM2_MAC10", 77 [HIGIG_FM1_MAC9] = "HiGig_FM1_MAC9", 78 [HIGIG_FM1_MAC10] = "HiGig_FM1_MAC10", 79 [HIGIG_FM2_MAC9] = "HiGig_FM2_MAC9", 80 [HIGIG_FM2_MAC10] = "HiGig_FM2_MAC10", 81 [QSGMII_FM1_A] = "QSGMII_FM1_A", 82 [QSGMII_FM1_B] = "QSGMII_FM1_B", 83 [QSGMII_FM2_A] = "QSGMII_FM2_A", 84 [QSGMII_FM2_B] = "QSGMII_FM2_B", 85 [XFI_FM1_MAC9] = "XFI_FM1_MAC9", 86 [XFI_FM1_MAC10] = "XFI_FM1_MAC10", 87 [XFI_FM2_MAC9] = "XFI_FM2_MAC9", 88 [XFI_FM2_MAC10] = "XFI_FM2_MAC10", 89 [INTERLAKEN] = "INTERLAKEN", 90 }; 91 #endif 92 93 int is_serdes_configured(enum srds_prtcl device) 94 { 95 u64 ret = 0; 96 97 ret |= (1ULL << device) & serdes1_prtcl_map; 98 ret |= (1ULL << device) & serdes2_prtcl_map; 99 #ifdef CONFIG_SYS_FSL_SRDS_3 100 ret |= (1ULL << device) & serdes3_prtcl_map; 101 #endif 102 #ifdef CONFIG_SYS_FSL_SRDS_4 103 ret |= (1ULL << device) & serdes4_prtcl_map; 104 #endif 105 106 return !!ret; 107 } 108 109 int serdes_get_first_lane(u32 sd, enum srds_prtcl device) 110 { 111 const ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 112 u32 cfg = in_be32(&gur->rcwsr[4]); 113 int i; 114 115 switch (sd) { 116 case FSL_SRDS_1: 117 cfg &= FSL_CORENET2_RCWSR4_SRDS1_PRTCL; 118 cfg >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; 119 break; 120 case FSL_SRDS_2: 121 cfg &= FSL_CORENET2_RCWSR4_SRDS2_PRTCL; 122 cfg >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; 123 break; 124 #ifdef CONFIG_SYS_FSL_SRDS_3 125 case FSL_SRDS_3: 126 cfg &= FSL_CORENET2_RCWSR4_SRDS3_PRTCL; 127 cfg >>= FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT; 128 break; 129 #endif 130 #ifdef CONFIG_SYS_FSL_SRDS_4 131 case FSL_SRDS_4: 132 cfg &= FSL_CORENET2_RCWSR4_SRDS4_PRTCL; 133 cfg >>= FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT; 134 break; 135 #endif 136 default: 137 printf("invalid SerDes%d\n", sd); 138 break; 139 } 140 /* Is serdes enabled at all? */ 141 if (unlikely(cfg == 0)) 142 return -ENODEV; 143 144 for (i = 0; i < SRDS_MAX_LANES; i++) { 145 if (serdes_get_prtcl(sd, cfg, i) == device) 146 return i; 147 } 148 149 return -ENODEV; 150 } 151 152 u64 serdes_init(u32 sd, u32 sd_addr, u32 sd_prctl_mask, u32 sd_prctl_shift) 153 { 154 ccsr_gur_t *gur = (void __iomem *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 155 u64 serdes_prtcl_map = 0; 156 u32 cfg; 157 int lane; 158 159 cfg = in_be32(&gur->rcwsr[4]) & sd_prctl_mask; 160 /* Is serdes enabled at all? */ 161 if (!cfg) { 162 printf("SERDES%d is not enabled\n", sd + 1); 163 return 0; 164 } 165 166 cfg >>= sd_prctl_shift; 167 printf("Using SERDES%d Protocol: 0x%x\n", sd + 1, cfg); 168 if (!is_serdes_prtcl_valid(sd, cfg)) 169 printf("SERDES%d[PRTCL] = 0x%x is not valid\n", sd + 1, cfg); 170 171 for (lane = 0; lane < SRDS_MAX_LANES; lane++) { 172 enum srds_prtcl lane_prtcl = serdes_get_prtcl(sd, cfg, lane); 173 serdes_prtcl_map |= (1ULL << lane_prtcl); 174 } 175 176 return serdes_prtcl_map; 177 } 178 179 void fsl_serdes_init(void) 180 { 181 182 serdes1_prtcl_map = serdes_init(FSL_SRDS_1, 183 CONFIG_SYS_FSL_CORENET_SERDES_ADDR, 184 FSL_CORENET2_RCWSR4_SRDS1_PRTCL, 185 FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT); 186 serdes2_prtcl_map = serdes_init(FSL_SRDS_2, 187 CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_2 * 0x1000, 188 FSL_CORENET2_RCWSR4_SRDS2_PRTCL, 189 FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT); 190 #ifdef CONFIG_SYS_FSL_SRDS_3 191 serdes3_prtcl_map = serdes_init(FSL_SRDS_3, 192 CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_3 * 0x1000, 193 FSL_CORENET2_RCWSR4_SRDS3_PRTCL, 194 FSL_CORENET2_RCWSR4_SRDS3_PRTCL_SHIFT); 195 #endif 196 #ifdef CONFIG_SYS_FSL_SRDS_4 197 serdes4_prtcl_map = serdes_init(FSL_SRDS_4, 198 CONFIG_SYS_FSL_CORENET_SERDES_ADDR + FSL_SRDS_4 * 0x1000, 199 FSL_CORENET2_RCWSR4_SRDS4_PRTCL, 200 FSL_CORENET2_RCWSR4_SRDS4_PRTCL_SHIFT); 201 #endif 202 203 } 204