1 /* 2 * Copyright 2008,2010 Freescale Semiconductor, Inc. 3 * Dave Liu <daveliu@freescale.com> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <config.h> 9 #include <common.h> 10 #include <asm/io.h> 11 #include <asm/immap_85xx.h> 12 #include <asm/fsl_serdes.h> 13 14 /* PORDEVSR register */ 15 #define GUTS_PORDEVSR_OFFS 0xc 16 #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000 17 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27 18 19 /* SerDes CR0 register */ 20 #define FSL_SRDSCR0_OFFS 0x0 21 #define FSL_SRDSCR0_TXEQA_MASK 0x00007000 22 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000 23 #define FSL_SRDSCR0_TXEQA_SATA 0x00001000 24 #define FSL_SRDSCR0_TXEQE_MASK 0x00000700 25 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400 26 #define FSL_SRDSCR0_TXEQE_SATA 0x00000100 27 28 /* SerDes CR1 register */ 29 #define FSL_SRDSCR1_OFFS 0x4 30 #define FSL_SRDSCR1_LANEA_MASK 0x80200000 31 #define FSL_SRDSCR1_LANEA_OFF 0x80200000 32 #define FSL_SRDSCR1_LANEE_MASK 0x08020000 33 #define FSL_SRDSCR1_LANEE_OFF 0x08020000 34 35 /* SerDes CR2 register */ 36 #define FSL_SRDSCR2_OFFS 0x8 37 #define FSL_SRDSCR2_EICA_MASK 0x00001f00 38 #define FSL_SRDSCR2_EICA_SGMII 0x00000400 39 #define FSL_SRDSCR2_EICA_SATA 0x00001400 40 #define FSL_SRDSCR2_EICE_MASK 0x0000001f 41 #define FSL_SRDSCR2_EICE_SGMII 0x00000004 42 #define FSL_SRDSCR2_EICE_SATA 0x00000014 43 44 /* SerDes CR3 register */ 45 #define FSL_SRDSCR3_OFFS 0xc 46 #define FSL_SRDSCR3_LANEA_MASK 0x3f000700 47 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000 48 #define FSL_SRDSCR3_LANEA_SATA 0x15000500 49 #define FSL_SRDSCR3_LANEE_MASK 0x003f0007 50 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000 51 #define FSL_SRDSCR3_LANEE_SATA 0x00150005 52 53 #define SRDS1_MAX_LANES 8 54 #define SRDS2_MAX_LANES 2 55 56 static u32 serdes1_prtcl_map, serdes2_prtcl_map; 57 58 static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = { 59 [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE}, 60 [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1}, 61 [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2}, 62 [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3}, 63 }; 64 65 static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = { 66 [0x1] = {SATA1, SATA2}, 67 [0x3] = {SATA1, NONE}, 68 [0x4] = {SGMII_TSEC1, SGMII_TSEC3}, 69 [0x6] = {SGMII_TSEC1, NONE}, 70 }; 71 72 int is_serdes_configured(enum srds_prtcl device) 73 { 74 int ret; 75 76 if (!(serdes1_prtcl_map & (1 << NONE))) 77 fsl_serdes_init(); 78 79 ret = (1 << device) & serdes1_prtcl_map; 80 81 if (ret) 82 return ret; 83 84 if (!(serdes2_prtcl_map & (1 << NONE))) 85 fsl_serdes_init(); 86 87 return (1 << device) & serdes2_prtcl_map; 88 } 89 90 void fsl_serdes_init(void) 91 { 92 void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 93 void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR; 94 u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS); 95 u32 srds1_io_sel, srds2_io_sel; 96 u32 tmp; 97 int lane; 98 99 if (serdes1_prtcl_map & (1 << NONE) && 100 serdes2_prtcl_map & (1 << NONE)) 101 return; 102 103 srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 104 MPC85xx_PORDEVSR_IO_SEL_SHIFT; 105 106 /* parse the SRDS2_IO_SEL of PORDEVSR */ 107 srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL) 108 >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT; 109 110 debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel); 111 debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel); 112 113 switch (srds2_io_sel) { 114 case 1: /* Lane A - SATA1, Lane E - SATA2 */ 115 /* CR 0 */ 116 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 117 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 118 tmp |= FSL_SRDSCR0_TXEQA_SATA; 119 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 120 tmp |= FSL_SRDSCR0_TXEQE_SATA; 121 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 122 /* CR 1 */ 123 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 124 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 125 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 126 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 127 /* CR 2 */ 128 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 129 tmp &= ~FSL_SRDSCR2_EICA_MASK; 130 tmp |= FSL_SRDSCR2_EICA_SATA; 131 tmp &= ~FSL_SRDSCR2_EICE_MASK; 132 tmp |= FSL_SRDSCR2_EICE_SATA; 133 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 134 /* CR 3 */ 135 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 136 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 137 tmp |= FSL_SRDSCR3_LANEA_SATA; 138 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 139 tmp |= FSL_SRDSCR3_LANEE_SATA; 140 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 141 break; 142 case 3: /* Lane A - SATA1, Lane E - disabled */ 143 /* CR 0 */ 144 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 145 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 146 tmp |= FSL_SRDSCR0_TXEQA_SATA; 147 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 148 /* CR 1 */ 149 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 150 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 151 tmp |= FSL_SRDSCR1_LANEE_OFF; 152 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 153 /* CR 2 */ 154 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 155 tmp &= ~FSL_SRDSCR2_EICA_MASK; 156 tmp |= FSL_SRDSCR2_EICA_SATA; 157 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 158 /* CR 3 */ 159 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 160 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 161 tmp |= FSL_SRDSCR3_LANEA_SATA; 162 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 163 break; 164 case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */ 165 /* CR 0 */ 166 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 167 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 168 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 169 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 170 tmp |= FSL_SRDSCR0_TXEQE_SGMII; 171 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 172 /* CR 1 */ 173 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 174 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 175 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 176 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 177 /* CR 2 */ 178 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 179 tmp &= ~FSL_SRDSCR2_EICA_MASK; 180 tmp |= FSL_SRDSCR2_EICA_SGMII; 181 tmp &= ~FSL_SRDSCR2_EICE_MASK; 182 tmp |= FSL_SRDSCR2_EICE_SGMII; 183 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 184 /* CR 3 */ 185 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 186 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 187 tmp |= FSL_SRDSCR3_LANEA_SGMII; 188 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 189 tmp |= FSL_SRDSCR3_LANEE_SGMII; 190 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 191 break; 192 case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */ 193 /* CR 0 */ 194 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 195 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 196 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 197 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 198 /* CR 1 */ 199 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 200 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 201 tmp |= FSL_SRDSCR1_LANEE_OFF; 202 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 203 /* CR 2 */ 204 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 205 tmp &= ~FSL_SRDSCR2_EICA_MASK; 206 tmp |= FSL_SRDSCR2_EICA_SGMII; 207 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 208 /* CR 3 */ 209 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 210 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 211 tmp |= FSL_SRDSCR3_LANEA_SGMII; 212 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 213 break; 214 case 7: /* Lane A - disabled, Lane E - disabled */ 215 /* CR 1 */ 216 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 217 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 218 tmp |= FSL_SRDSCR1_LANEA_OFF; 219 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 220 tmp |= FSL_SRDSCR1_LANEE_OFF; 221 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 222 break; 223 default: 224 break; 225 } 226 227 if (srds1_io_sel >= ARRAY_SIZE(serdes1_cfg_tbl)) { 228 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel); 229 return; 230 } 231 for (lane = 0; lane < SRDS1_MAX_LANES; lane++) { 232 enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane]; 233 serdes1_prtcl_map |= (1 << lane_prtcl); 234 } 235 236 /* Set the first bit to indicate serdes has been initialized */ 237 serdes1_prtcl_map |= (1 << NONE); 238 239 if (srds2_io_sel >= ARRAY_SIZE(serdes2_cfg_tbl)) { 240 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel); 241 return; 242 } 243 244 for (lane = 0; lane < SRDS2_MAX_LANES; lane++) { 245 enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane]; 246 serdes2_prtcl_map |= (1 << lane_prtcl); 247 } 248 249 /* Set the first bit to indicate serdes has been initialized */ 250 serdes2_prtcl_map |= (1 << NONE); 251 } 252