1 /* 2 * Copyright 2012 Freescale Semiconductor, Inc. 3 * Author: Sandeep Kumar Singh <sandeep@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 /* This file is based on board/freescale/corenet_ds/eth_superhydra.c */ 25 26 /* 27 * This file handles the board muxing between the Fman Ethernet MACs and 28 * the RGMII/SGMII/XGMII PHYs on a Freescale B4860 "Centaur". The SGMII 29 * PHYs are the two on-board 1Gb ports. There are no RGMII PHY on board. 30 * The 10Gb XGMII PHY is provided via the XAUI riser card. There is only 31 * one Fman device on B4860. The SERDES configuration is used to determine 32 * where the SGMII and XAUI cards exist, and also which Fman MACs are routed 33 * to which PHYs. So for a given Fman MAC, there is one and only PHY it 34 * connects to. MACs cannot be routed to PHYs dynamically. This configuration 35 * is done at boot time by reading SERDES protocol from RCW. 36 */ 37 38 #include <common.h> 39 #include <netdev.h> 40 #include <asm/fsl_serdes.h> 41 #include <fm_eth.h> 42 #include <fsl_mdio.h> 43 #include <malloc.h> 44 #include <fdt_support.h> 45 #include <asm/fsl_dtsec.h> 46 47 #include "../common/ngpixis.h" 48 #include "../common/fman.h" 49 #include "../common/qixis.h" 50 #include "b4860qds_qixis.h" 51 52 #define EMI_NONE 0xFFFFFFFF 53 54 #ifdef CONFIG_FMAN_ENET 55 56 /* 57 * Mapping of all 16 SERDES lanes to board slots. A value n(>0) will mean that 58 * lane at index is mapped to slot number n. A value of '0' will mean 59 * that the mapping must be determined dynamically, or that the lane maps to 60 * something other than a board slot 61 */ 62 static u8 lane_to_slot[] = { 63 0, 0, 0, 0, 64 0, 0, 0, 0, 65 1, 1, 1, 1, 66 0, 0, 0, 0 67 }; 68 69 /* 70 * This function initializes the lane_to_slot[] array. It reads RCW to check 71 * if Serdes2{E,F,G,H} is configured as slot 2 or as SFP and initializes 72 * lane_to_slot[] accordingly 73 */ 74 static void initialize_lane_to_slot(void) 75 { 76 unsigned int serdes2_prtcl; 77 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 78 serdes2_prtcl = in_be32(&gur->rcwsr[4]) & 79 FSL_CORENET2_RCWSR4_SRDS2_PRTCL; 80 serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; 81 debug("Initializing lane to slot: Serdes2 protocol: %x\n", 82 serdes2_prtcl); 83 84 switch (serdes2_prtcl) { 85 case 0x18: 86 /* 87 * Configuration: 88 * SERDES: 2 89 * Lanes: A,B,C,D: SGMII 90 * Lanes: E,F: Aur 91 * Lanes: G,H: SRIO 92 */ 93 case 0x91: 94 /* 95 * Configuration: 96 * SERDES: 2 97 * Lanes: A,B: SGMII 98 * Lanes: C,D: SRIO2 99 * Lanes: E,F,G,H: XAUI2 100 */ 101 case 0x93: 102 /* 103 * Configuration: 104 * SERDES: 2 105 * Lanes: A,B,C,D: SGMII 106 * Lanes: E,F,G,H: XAUI2 107 */ 108 case 0x98: 109 /* 110 * Configuration: 111 * SERDES: 2 112 * Lanes: A,B,C,D: XAUI2 113 * Lanes: E,F,G,H: XAUI2 114 */ 115 case 0x9a: 116 /* 117 * Configuration: 118 * SERDES: 2 119 * Lanes: A,B: PCI 120 * Lanes: C,D: SGMII 121 * Lanes: E,F,G,H: XAUI2 122 */ 123 case 0x9e: 124 /* 125 * Configuration: 126 * SERDES: 2 127 * Lanes: A,B,C,D: PCI 128 * Lanes: E,F,G,H: XAUI2 129 */ 130 case 0xb2: 131 /* 132 * Configuration: 133 * SERDES: 2 134 * Lanes: A,B,C,D: PCI 135 * Lanes: E,F: SGMII 3&4 136 * Lanes: G,H: XFI 137 */ 138 case 0xc2: 139 /* 140 * Configuration: 141 * SERDES: 2 142 * Lanes: A,B: SGMII 143 * Lanes: C,D: SRIO2 144 * Lanes: E,F,G,H: XAUI2 145 */ 146 lane_to_slot[12] = 2; 147 lane_to_slot[13] = lane_to_slot[12]; 148 lane_to_slot[14] = lane_to_slot[12]; 149 lane_to_slot[15] = lane_to_slot[12]; 150 break; 151 152 default: 153 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n", 154 serdes2_prtcl); 155 break; 156 } 157 return; 158 } 159 160 #endif /* #ifdef CONFIG_FMAN_ENET */ 161 162 int board_eth_init(bd_t *bis) 163 { 164 #ifdef CONFIG_FMAN_ENET 165 struct memac_mdio_info memac_mdio_info; 166 struct memac_mdio_info tg_memac_mdio_info; 167 unsigned int i; 168 unsigned int serdes1_prtcl, serdes2_prtcl; 169 ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 170 serdes1_prtcl = in_be32(&gur->rcwsr[4]) & 171 FSL_CORENET2_RCWSR4_SRDS1_PRTCL; 172 if (!serdes1_prtcl) { 173 printf("SERDES1 is not enabled\n"); 174 return 0; 175 } 176 serdes1_prtcl >>= FSL_CORENET2_RCWSR4_SRDS1_PRTCL_SHIFT; 177 debug("Using SERDES1 Protocol: 0x%x:\n", serdes1_prtcl); 178 179 serdes2_prtcl = in_be32(&gur->rcwsr[4]) & 180 FSL_CORENET2_RCWSR4_SRDS2_PRTCL; 181 if (!serdes2_prtcl) { 182 printf("SERDES2 is not enabled\n"); 183 return 0; 184 } 185 serdes2_prtcl >>= FSL_CORENET2_RCWSR4_SRDS2_PRTCL_SHIFT; 186 debug("Using SERDES2 Protocol: 0x%x:\n", serdes2_prtcl); 187 188 printf("Initializing Fman\n"); 189 190 initialize_lane_to_slot(); 191 192 memac_mdio_info.regs = 193 (struct memac_mdio_controller *)CONFIG_SYS_FM1_DTSEC_MDIO_ADDR; 194 memac_mdio_info.name = DEFAULT_FM_MDIO_NAME; 195 196 /* Register the real 1G MDIO bus */ 197 fm_memac_mdio_init(bis, &memac_mdio_info); 198 199 tg_memac_mdio_info.regs = 200 (struct memac_mdio_controller *)CONFIG_SYS_FM1_TGEC_MDIO_ADDR; 201 tg_memac_mdio_info.name = DEFAULT_FM_TGEC_MDIO_NAME; 202 203 /* Register the real 10G MDIO bus */ 204 fm_memac_mdio_init(bis, &tg_memac_mdio_info); 205 206 /* 207 * Program the two on board DTSEC PHY addresses assuming that they are 208 * all SGMII. RGMII is not supported on this board. Setting SGMII 5 and 209 * 6 to on board SGMII phys 210 */ 211 fm_info_set_phy_address(FM1_DTSEC5, CONFIG_SYS_FM1_DTSEC5_PHY_ADDR); 212 fm_info_set_phy_address(FM1_DTSEC6, CONFIG_SYS_FM1_DTSEC6_PHY_ADDR); 213 214 switch (serdes1_prtcl) { 215 case 0x2a: 216 /* Serdes 1: A-B SGMII, Configuring DTSEC 5 and 6 */ 217 debug("Setting phy addresses for FM1_DTSEC5: %x and" 218 "FM1_DTSEC6: %x\n", CONFIG_SYS_FM1_DTSEC5_PHY_ADDR, 219 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR); 220 /* Fixing Serdes clock by programming FPGA register */ 221 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125); 222 fm_info_set_phy_address(FM1_DTSEC5, 223 CONFIG_SYS_FM1_DTSEC5_PHY_ADDR); 224 fm_info_set_phy_address(FM1_DTSEC6, 225 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR); 226 break; 227 #ifdef CONFIG_PPC_B4420 228 case 0x18: 229 /* Serdes 1: A-D SGMII, Configuring on board dual SGMII Phy */ 230 debug("Setting phy addresses for FM1_DTSEC3: %x and" 231 "FM1_DTSEC4: %x\n", CONFIG_SYS_FM1_DTSEC5_PHY_ADDR, 232 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR); 233 /* Fixing Serdes clock by programming FPGA register */ 234 QIXIS_WRITE(brdcfg[4], QIXIS_SRDS1CLK_125); 235 fm_info_set_phy_address(FM1_DTSEC3, 236 CONFIG_SYS_FM1_DTSEC5_PHY_ADDR); 237 fm_info_set_phy_address(FM1_DTSEC4, 238 CONFIG_SYS_FM1_DTSEC6_PHY_ADDR); 239 break; 240 #endif 241 default: 242 printf("Fman: Unsupported SerDes1 Protocol 0x%02x\n", 243 serdes1_prtcl); 244 break; 245 } 246 switch (serdes2_prtcl) { 247 case 0x18: 248 debug("Setting phy addresses on SGMII Riser card for" 249 "FM1_DTSEC ports: \n"); 250 fm_info_set_phy_address(FM1_DTSEC1, 251 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); 252 fm_info_set_phy_address(FM1_DTSEC2, 253 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); 254 fm_info_set_phy_address(FM1_DTSEC3, 255 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR); 256 fm_info_set_phy_address(FM1_DTSEC4, 257 CONFIG_SYS_FM1_DTSEC4_RISER_PHY_ADDR); 258 break; 259 case 0x49: 260 debug("Setting phy addresses on SGMII Riser card for" 261 "FM1_DTSEC ports: \n"); 262 fm_info_set_phy_address(FM1_DTSEC1, 263 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); 264 fm_info_set_phy_address(FM1_DTSEC2, 265 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); 266 fm_info_set_phy_address(FM1_DTSEC3, 267 CONFIG_SYS_FM1_DTSEC3_RISER_PHY_ADDR); 268 break; 269 case 0x8d: 270 case 0xb2: 271 debug("Setting phy addresses on SGMII Riser card for" 272 "FM1_DTSEC ports: \n"); 273 fm_info_set_phy_address(FM1_DTSEC3, 274 CONFIG_SYS_FM1_DTSEC1_RISER_PHY_ADDR); 275 fm_info_set_phy_address(FM1_DTSEC4, 276 CONFIG_SYS_FM1_DTSEC2_RISER_PHY_ADDR); 277 break; 278 default: 279 printf("Fman: Unsupported SerDes2 Protocol 0x%02x\n", 280 serdes2_prtcl); 281 break; 282 } 283 284 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { 285 int idx = i - FM1_DTSEC1; 286 287 switch (fm_info_get_enet_if(i)) { 288 case PHY_INTERFACE_MODE_SGMII: 289 fm_info_set_mdio(i, 290 miiphy_get_dev_by_name(DEFAULT_FM_MDIO_NAME)); 291 break; 292 case PHY_INTERFACE_MODE_NONE: 293 fm_info_set_phy_address(i, 0); 294 break; 295 default: 296 printf("Fman1: DTSEC%u set to unknown interface %i\n", 297 idx + 1, fm_info_get_enet_if(i)); 298 fm_info_set_phy_address(i, 0); 299 break; 300 } 301 } 302 303 cpu_eth_init(bis); 304 #endif 305 306 return pci_eth_init(bis); 307 } 308 309 void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr, 310 enum fm_port port, int offset) 311 { 312 int phy; 313 char alias[32]; 314 315 if (fm_info_get_enet_if(port) == PHY_INTERFACE_MODE_SGMII) { 316 phy = fm_info_get_phy_address(port); 317 318 sprintf(alias, "phy_sgmii_%x", phy); 319 fdt_set_phy_handle(fdt, compat, addr, alias); 320 } 321 } 322 323 void fdt_fixup_board_enet(void *fdt) 324 { 325 int i; 326 char alias[32]; 327 328 for (i = FM1_DTSEC1; i < FM1_DTSEC1 + CONFIG_SYS_NUM_FM1_DTSEC; i++) { 329 switch (fm_info_get_enet_if(i)) { 330 case PHY_INTERFACE_MODE_NONE: 331 sprintf(alias, "ethernet%u", i); 332 fdt_status_disabled_by_alias(fdt, alias); 333 break; 334 default: 335 break; 336 } 337 } 338 } 339