1 /* 2 * Copyright 2008,2010 Freescale Semiconductor, Inc. 3 * Dave Liu <daveliu@freescale.com> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 #include <config.h> 25 #include <common.h> 26 #include <asm/io.h> 27 #include <asm/immap_85xx.h> 28 #include <asm/fsl_serdes.h> 29 30 /* PORDEVSR register */ 31 #define GUTS_PORDEVSR_OFFS 0xc 32 #define GUTS_PORDEVSR_SERDES2_IO_SEL 0x38000000 33 #define GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT 27 34 35 /* SerDes CR0 register */ 36 #define FSL_SRDSCR0_OFFS 0x0 37 #define FSL_SRDSCR0_TXEQA_MASK 0x00007000 38 #define FSL_SRDSCR0_TXEQA_SGMII 0x00004000 39 #define FSL_SRDSCR0_TXEQA_SATA 0x00001000 40 #define FSL_SRDSCR0_TXEQE_MASK 0x00000700 41 #define FSL_SRDSCR0_TXEQE_SGMII 0x00000400 42 #define FSL_SRDSCR0_TXEQE_SATA 0x00000100 43 44 /* SerDes CR1 register */ 45 #define FSL_SRDSCR1_OFFS 0x4 46 #define FSL_SRDSCR1_LANEA_MASK 0x80200000 47 #define FSL_SRDSCR1_LANEA_OFF 0x80200000 48 #define FSL_SRDSCR1_LANEE_MASK 0x08020000 49 #define FSL_SRDSCR1_LANEE_OFF 0x08020000 50 51 /* SerDes CR2 register */ 52 #define FSL_SRDSCR2_OFFS 0x8 53 #define FSL_SRDSCR2_EICA_MASK 0x00001f00 54 #define FSL_SRDSCR2_EICA_SGMII 0x00000400 55 #define FSL_SRDSCR2_EICA_SATA 0x00001400 56 #define FSL_SRDSCR2_EICE_MASK 0x0000001f 57 #define FSL_SRDSCR2_EICE_SGMII 0x00000004 58 #define FSL_SRDSCR2_EICE_SATA 0x00000014 59 60 /* SerDes CR3 register */ 61 #define FSL_SRDSCR3_OFFS 0xc 62 #define FSL_SRDSCR3_LANEA_MASK 0x3f000700 63 #define FSL_SRDSCR3_LANEA_SGMII 0x00000000 64 #define FSL_SRDSCR3_LANEA_SATA 0x15000500 65 #define FSL_SRDSCR3_LANEE_MASK 0x003f0007 66 #define FSL_SRDSCR3_LANEE_SGMII 0x00000000 67 #define FSL_SRDSCR3_LANEE_SATA 0x00150005 68 69 70 #define SRDS1_MAX_LANES 8 71 #define SRDS2_MAX_LANES 2 72 73 static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = { 74 [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE}, 75 [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1}, 76 [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2}, 77 [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3}, 78 }; 79 80 static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = { 81 [0x1] = {SATA1, SATA2}, 82 [0x3] = {SATA1, NONE}, 83 [0x4] = {SGMII_TSEC1, SGMII_TSEC3}, 84 [0x6] = {SGMII_TSEC1, NONE}, 85 }; 86 87 int is_serdes_configured(enum srds_prtcl device) 88 { 89 int i; 90 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 91 u32 pordevsr = in_be32(&gur->pordevsr); 92 u32 srds1_cfg = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 93 MPC85xx_PORDEVSR_IO_SEL_SHIFT; 94 95 u32 srds2_cfg = (pordevsr & MPC85xx_PORDEVSR_SRDS2_IO_SEL) >> 96 GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT; 97 98 debug("%s: dev = %d\n", __FUNCTION__, device); 99 debug("PORDEVSR[IO_SEL] = %x\n", srds1_cfg); 100 debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_cfg); 101 102 if (srds1_cfg > ARRAY_SIZE(serdes1_cfg_tbl)) { 103 printf("Invalid PORDEVSR[IO_SEL] = %d\n", srds1_cfg); 104 return 0; 105 } 106 107 if (srds2_cfg > ARRAY_SIZE(serdes2_cfg_tbl)) { 108 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_cfg); 109 return 0; 110 } 111 112 for (i = 0; i < SRDS1_MAX_LANES; i++) { 113 if (serdes1_cfg_tbl[srds1_cfg][i] == device) 114 return 1; 115 } 116 for (i = 0; i < SRDS2_MAX_LANES; i++) { 117 if (serdes2_cfg_tbl[srds2_cfg][i] == device) 118 return 1; 119 } 120 121 return 0; 122 } 123 124 void fsl_serdes_init(void) 125 { 126 void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 127 void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR; 128 u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS); 129 u32 srds2_io_sel; 130 u32 tmp; 131 132 /* parse the SRDS2_IO_SEL of PORDEVSR */ 133 srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL) 134 >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT; 135 136 switch (srds2_io_sel) { 137 case 1: /* Lane A - SATA1, Lane E - SATA2 */ 138 /* CR 0 */ 139 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 140 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 141 tmp |= FSL_SRDSCR0_TXEQA_SATA; 142 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 143 tmp |= FSL_SRDSCR0_TXEQE_SATA; 144 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 145 /* CR 1 */ 146 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 147 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 148 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 149 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 150 /* CR 2 */ 151 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 152 tmp &= ~FSL_SRDSCR2_EICA_MASK; 153 tmp |= FSL_SRDSCR2_EICA_SATA; 154 tmp &= ~FSL_SRDSCR2_EICE_MASK; 155 tmp |= FSL_SRDSCR2_EICE_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 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 162 tmp |= FSL_SRDSCR3_LANEE_SATA; 163 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 164 break; 165 case 3: /* Lane A - SATA1, Lane E - disabled */ 166 /* CR 0 */ 167 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 168 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 169 tmp |= FSL_SRDSCR0_TXEQA_SATA; 170 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 171 /* CR 1 */ 172 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 173 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 174 tmp |= FSL_SRDSCR1_LANEE_OFF; 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_SATA; 180 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 181 /* CR 3 */ 182 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 183 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 184 tmp |= FSL_SRDSCR3_LANEA_SATA; 185 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 186 break; 187 case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */ 188 /* CR 0 */ 189 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 190 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 191 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 192 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 193 tmp |= FSL_SRDSCR0_TXEQE_SGMII; 194 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 195 /* CR 1 */ 196 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 197 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 198 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 199 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 200 /* CR 2 */ 201 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 202 tmp &= ~FSL_SRDSCR2_EICA_MASK; 203 tmp |= FSL_SRDSCR2_EICA_SGMII; 204 tmp &= ~FSL_SRDSCR2_EICE_MASK; 205 tmp |= FSL_SRDSCR2_EICE_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 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 212 tmp |= FSL_SRDSCR3_LANEE_SGMII; 213 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 214 break; 215 case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */ 216 /* CR 0 */ 217 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 218 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 219 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 220 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 221 /* CR 1 */ 222 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 223 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 224 tmp |= FSL_SRDSCR1_LANEE_OFF; 225 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 226 /* CR 2 */ 227 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 228 tmp &= ~FSL_SRDSCR2_EICA_MASK; 229 tmp |= FSL_SRDSCR2_EICA_SGMII; 230 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 231 /* CR 3 */ 232 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 233 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 234 tmp |= FSL_SRDSCR3_LANEA_SGMII; 235 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 236 break; 237 case 7: /* Lane A - disabled, Lane E - disabled */ 238 /* CR 1 */ 239 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 240 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 241 tmp |= FSL_SRDSCR1_LANEA_OFF; 242 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 243 tmp |= FSL_SRDSCR1_LANEE_OFF; 244 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 245 break; 246 default: 247 break; 248 } 249 } 250