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