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 #define SRDS1_MAX_LANES 8 70 #define SRDS2_MAX_LANES 2 71 72 static u32 serdes1_prtcl_map, serdes2_prtcl_map; 73 74 static u8 serdes1_cfg_tbl[][SRDS1_MAX_LANES] = { 75 [0x2] = {PCIE1, PCIE1, PCIE1, PCIE1, NONE, NONE, NONE, NONE}, 76 [0x3] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1, PCIE1}, 77 [0x5] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE2, PCIE2}, 78 [0x7] = {PCIE1, PCIE1, PCIE1, PCIE1, PCIE2, PCIE2, PCIE3, PCIE3}, 79 }; 80 81 static u8 serdes2_cfg_tbl[][SRDS2_MAX_LANES] = { 82 [0x1] = {SATA1, SATA2}, 83 [0x3] = {SATA1, NONE}, 84 [0x4] = {SGMII_TSEC1, SGMII_TSEC3}, 85 [0x6] = {SGMII_TSEC1, NONE}, 86 }; 87 88 int is_serdes_configured(enum srds_prtcl device) 89 { 90 int ret = (1 << device) & serdes1_prtcl_map; 91 92 if (ret) 93 return ret; 94 95 return (1 << device) & serdes2_prtcl_map; 96 } 97 98 void fsl_serdes_init(void) 99 { 100 void *guts = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 101 void *sd = (void *)CONFIG_SYS_MPC85xx_SERDES2_ADDR; 102 u32 pordevsr = in_be32(guts + GUTS_PORDEVSR_OFFS); 103 u32 srds1_io_sel, srds2_io_sel; 104 u32 tmp; 105 int lane; 106 107 srds1_io_sel = (pordevsr & MPC85xx_PORDEVSR_IO_SEL) >> 108 MPC85xx_PORDEVSR_IO_SEL_SHIFT; 109 110 /* parse the SRDS2_IO_SEL of PORDEVSR */ 111 srds2_io_sel = (pordevsr & GUTS_PORDEVSR_SERDES2_IO_SEL) 112 >> GUTS_PORDEVSR_SERDES2_IO_SEL_SHIFT; 113 114 debug("PORDEVSR[SRDS1_IO_SEL] = %x\n", srds1_io_sel); 115 debug("PORDEVSR[SRDS2_IO_SEL] = %x\n", srds2_io_sel); 116 117 switch (srds2_io_sel) { 118 case 1: /* Lane A - SATA1, Lane E - SATA2 */ 119 /* CR 0 */ 120 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 121 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 122 tmp |= FSL_SRDSCR0_TXEQA_SATA; 123 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 124 tmp |= FSL_SRDSCR0_TXEQE_SATA; 125 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 126 /* CR 1 */ 127 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 128 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 129 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 130 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 131 /* CR 2 */ 132 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 133 tmp &= ~FSL_SRDSCR2_EICA_MASK; 134 tmp |= FSL_SRDSCR2_EICA_SATA; 135 tmp &= ~FSL_SRDSCR2_EICE_MASK; 136 tmp |= FSL_SRDSCR2_EICE_SATA; 137 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 138 /* CR 3 */ 139 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 140 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 141 tmp |= FSL_SRDSCR3_LANEA_SATA; 142 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 143 tmp |= FSL_SRDSCR3_LANEE_SATA; 144 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 145 break; 146 case 3: /* Lane A - SATA1, Lane E - disabled */ 147 /* CR 0 */ 148 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 149 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 150 tmp |= FSL_SRDSCR0_TXEQA_SATA; 151 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 152 /* CR 1 */ 153 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 154 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 155 tmp |= FSL_SRDSCR1_LANEE_OFF; 156 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 157 /* CR 2 */ 158 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 159 tmp &= ~FSL_SRDSCR2_EICA_MASK; 160 tmp |= FSL_SRDSCR2_EICA_SATA; 161 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 162 /* CR 3 */ 163 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 164 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 165 tmp |= FSL_SRDSCR3_LANEA_SATA; 166 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 167 break; 168 case 4: /* Lane A - eTSEC1 SGMII, Lane E - eTSEC3 SGMII */ 169 /* CR 0 */ 170 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 171 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 172 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 173 tmp &= ~FSL_SRDSCR0_TXEQE_MASK; 174 tmp |= FSL_SRDSCR0_TXEQE_SGMII; 175 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 176 /* CR 1 */ 177 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 178 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 179 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 180 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 181 /* CR 2 */ 182 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 183 tmp &= ~FSL_SRDSCR2_EICA_MASK; 184 tmp |= FSL_SRDSCR2_EICA_SGMII; 185 tmp &= ~FSL_SRDSCR2_EICE_MASK; 186 tmp |= FSL_SRDSCR2_EICE_SGMII; 187 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 188 /* CR 3 */ 189 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 190 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 191 tmp |= FSL_SRDSCR3_LANEA_SGMII; 192 tmp &= ~FSL_SRDSCR3_LANEE_MASK; 193 tmp |= FSL_SRDSCR3_LANEE_SGMII; 194 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 195 break; 196 case 6: /* Lane A - eTSEC1 SGMII, Lane E - disabled */ 197 /* CR 0 */ 198 tmp = in_be32(sd + FSL_SRDSCR0_OFFS); 199 tmp &= ~FSL_SRDSCR0_TXEQA_MASK; 200 tmp |= FSL_SRDSCR0_TXEQA_SGMII; 201 out_be32(sd + FSL_SRDSCR0_OFFS, tmp); 202 /* CR 1 */ 203 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 204 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 205 tmp |= FSL_SRDSCR1_LANEE_OFF; 206 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 207 /* CR 2 */ 208 tmp = in_be32(sd + FSL_SRDSCR2_OFFS); 209 tmp &= ~FSL_SRDSCR2_EICA_MASK; 210 tmp |= FSL_SRDSCR2_EICA_SGMII; 211 out_be32(sd + FSL_SRDSCR2_OFFS, tmp); 212 /* CR 3 */ 213 tmp = in_be32(sd + FSL_SRDSCR3_OFFS); 214 tmp &= ~FSL_SRDSCR3_LANEA_MASK; 215 tmp |= FSL_SRDSCR3_LANEA_SGMII; 216 out_be32(sd + FSL_SRDSCR3_OFFS, tmp); 217 break; 218 case 7: /* Lane A - disabled, Lane E - disabled */ 219 /* CR 1 */ 220 tmp = in_be32(sd + FSL_SRDSCR1_OFFS); 221 tmp &= ~FSL_SRDSCR1_LANEA_MASK; 222 tmp |= FSL_SRDSCR1_LANEA_OFF; 223 tmp &= ~FSL_SRDSCR1_LANEE_MASK; 224 tmp |= FSL_SRDSCR1_LANEE_OFF; 225 out_be32(sd + FSL_SRDSCR1_OFFS, tmp); 226 break; 227 default: 228 break; 229 } 230 231 if (srds1_io_sel > ARRAY_SIZE(serdes1_cfg_tbl)) { 232 printf("Invalid PORDEVSR[SRDS1_IO_SEL] = %d\n", srds1_io_sel); 233 return; 234 } 235 for (lane = 0; lane < SRDS1_MAX_LANES; lane++) { 236 enum srds_prtcl lane_prtcl = serdes1_cfg_tbl[srds1_io_sel][lane]; 237 serdes1_prtcl_map |= (1 << lane_prtcl); 238 } 239 240 if (srds2_io_sel > ARRAY_SIZE(serdes2_cfg_tbl)) { 241 printf("Invalid PORDEVSR[SRDS2_IO_SEL] = %d\n", srds2_io_sel); 242 return; 243 } 244 245 for (lane = 0; lane < SRDS2_MAX_LANES; lane++) { 246 enum srds_prtcl lane_prtcl = serdes2_cfg_tbl[srds2_io_sel][lane]; 247 serdes2_prtcl_map |= (1 << lane_prtcl); 248 } 249 } 250