cvmx-helper-board.c revision 210286
1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * Helper functions to abstract board specific data about 48 * network ports from the rest of the cvmx-helper files. 49 * 50 * <hr>$Revision: 41946 $<hr> 51 */ 52#include "cvmx.h" 53#include "cvmx-app-init.h" 54#include "cvmx-mdio.h" 55#include "cvmx-sysinfo.h" 56#include "cvmx-helper.h" 57#include "cvmx-helper-util.h" 58#include "cvmx-helper-board.h" 59 60/** 61 * cvmx_override_board_link_get(int ipd_port) is a function 62 * pointer. It is meant to allow customization of the process of 63 * talking to a PHY to determine link speed. It is called every 64 * time a PHY must be polled for link status. Users should set 65 * this pointer to a function before calling any cvmx-helper 66 * operations. 67 */ 68CVMX_SHARED cvmx_helper_link_info_t (*cvmx_override_board_link_get)(int ipd_port) = NULL; 69 70/** 71 * Return the MII PHY address associated with the given IPD 72 * port. A result of -1 means there isn't a MII capable PHY 73 * connected to this port. On chips supporting multiple MII 74 * busses the bus number is encoded in bits <15:8>. 75 * 76 * This function must be modified for every new Octeon board. 77 * Internally it uses switch statements based on the cvmx_sysinfo 78 * data to determine board types and revisions. It replies on the 79 * fact that every Octeon board receives a unique board type 80 * enumeration from the bootloader. 81 * 82 * @param ipd_port Octeon IPD port to get the MII address for. 83 * 84 * @return MII PHY address and bus number or -1. 85 */ 86int cvmx_helper_board_get_mii_address(int ipd_port) 87{ 88 switch (cvmx_sysinfo_get()->board_type) 89 { 90 case CVMX_BOARD_TYPE_SIM: 91 /* Simulator doesn't have MII */ 92 return -1; 93 case CVMX_BOARD_TYPE_EBT3000: 94 case CVMX_BOARD_TYPE_EBT5800: 95 case CVMX_BOARD_TYPE_THUNDER: 96 case CVMX_BOARD_TYPE_NICPRO2: 97 /* Interface 0 is SPI4, interface 1 is RGMII */ 98 if ((ipd_port >= 16) && (ipd_port < 20)) 99 return ipd_port - 16; 100 else 101 return -1; 102 case CVMX_BOARD_TYPE_KODAMA: 103 case CVMX_BOARD_TYPE_EBH3100: 104 case CVMX_BOARD_TYPE_HIKARI: 105 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 106 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 107 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 108 /* Port 0 is WAN connected to a PHY, Port 1 is GMII connected to a 109 switch */ 110 if (ipd_port == 0) 111 return 4; 112 else if (ipd_port == 1) 113 return 9; 114 else 115 return -1; 116 case CVMX_BOARD_TYPE_NAC38: 117 /* Board has 8 RGMII ports PHYs are 0-7 */ 118 if ((ipd_port >= 0) && (ipd_port < 4)) 119 return ipd_port; 120 else if ((ipd_port >= 16) && (ipd_port < 20)) 121 return ipd_port - 16 + 4; 122 else 123 return -1; 124 case CVMX_BOARD_TYPE_EBH3000: 125 /* Board has dual SPI4 and no PHYs */ 126 return -1; 127 case CVMX_BOARD_TYPE_EBH5200: 128 case CVMX_BOARD_TYPE_EBH5201: 129 case CVMX_BOARD_TYPE_EBT5200: 130 /* Board has 4 SGMII ports. The PHYs start right after the MII 131 ports MII0 = 0, MII1 = 1, SGMII = 2-5 */ 132 if ((ipd_port >= 0) && (ipd_port < 4)) 133 return ipd_port+2; 134 else 135 return -1; 136 case CVMX_BOARD_TYPE_EBH5600: 137 case CVMX_BOARD_TYPE_EBH5601: 138 /* Board has 8 SGMII ports. 4 connect out, two connect to a switch, 139 and 2 loop to each other */ 140 if ((ipd_port >= 0) && (ipd_port < 4)) 141 return ipd_port+1; 142 else 143 return -1; 144 case CVMX_BOARD_TYPE_CUST_NB5: 145 if (ipd_port == 2) 146 return 4; 147 else 148 return -1; 149 case CVMX_BOARD_TYPE_NIC_XLE_4G: 150 /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 151 if ((ipd_port >= 16) && (ipd_port < 20)) 152 return ipd_port - 16 + 1; 153 else 154 return -1; 155 case CVMX_BOARD_TYPE_BBGW_REF: 156 return -1; /* No PHYs are connected to Octeon, everything is through switch */ 157 } 158 159 /* Some unknown board. Somebody forgot to update this function... */ 160 cvmx_dprintf("cvmx_helper_board_get_mii_address: Unknown board type %d\n", 161 cvmx_sysinfo_get()->board_type); 162 return -1; 163} 164 165 166/** 167 * @INTERNAL 168 * This function is the board specific method of determining an 169 * ethernet ports link speed. Most Octeon boards have Marvell PHYs 170 * and are handled by the fall through case. This function must be 171 * updated for boards that don't have the normal Marvell PHYs. 172 * 173 * This function must be modified for every new Octeon board. 174 * Internally it uses switch statements based on the cvmx_sysinfo 175 * data to determine board types and revisions. It relies on the 176 * fact that every Octeon board receives a unique board type 177 * enumeration from the bootloader. 178 * 179 * @param ipd_port IPD input port associated with the port we want to get link 180 * status for. 181 * 182 * @return The ports link status. If the link isn't fully resolved, this must 183 * return zero. 184 */ 185cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 186{ 187 cvmx_helper_link_info_t result; 188 int phy_addr; 189 int is_broadcom_phy = 0; 190 191 /* Give the user a chance to override the processing of this function */ 192 if (cvmx_override_board_link_get) 193 return cvmx_override_board_link_get(ipd_port); 194 195 /* Unless we fix it later, all links are defaulted to down */ 196 result.u64 = 0; 197 198 /* This switch statement should handle all ports that either don't use 199 Marvell PHYS, or don't support in-band status */ 200 switch (cvmx_sysinfo_get()->board_type) 201 { 202 case CVMX_BOARD_TYPE_SIM: 203 /* The simulator gives you a simulated 1Gbps full duplex link */ 204 result.s.link_up = 1; 205 result.s.full_duplex = 1; 206 result.s.speed = 1000; 207 return result; 208 case CVMX_BOARD_TYPE_EBH3100: 209 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 210 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 211 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 212 /* Port 1 on these boards is always Gigabit */ 213 if (ipd_port == 1) 214 { 215 result.s.link_up = 1; 216 result.s.full_duplex = 1; 217 result.s.speed = 1000; 218 return result; 219 } 220 /* Fall through to the generic code below */ 221 break; 222 case CVMX_BOARD_TYPE_CUST_NB5: 223 /* Port 1 on these boards is always Gigabit */ 224 if (ipd_port == 1) 225 { 226 result.s.link_up = 1; 227 result.s.full_duplex = 1; 228 result.s.speed = 1000; 229 return result; 230 } 231 else /* The other port uses a broadcom PHY */ 232 is_broadcom_phy = 1; 233 break; 234 case CVMX_BOARD_TYPE_BBGW_REF: 235 /* Port 1 on these boards is always Gigabit */ 236 if (ipd_port == 2) 237 { 238 /* Port 2 is not hooked up */ 239 result.u64 = 0; 240 return result; 241 } 242 else 243 { 244 /* Ports 0 and 1 connect to the switch */ 245 result.s.link_up = 1; 246 result.s.full_duplex = 1; 247 result.s.speed = 1000; 248 return result; 249 } 250 break; 251 } 252 253 phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 254 if (phy_addr != -1) 255 { 256 if (is_broadcom_phy) 257 { 258 /* Below we are going to read SMI/MDIO register 0x19 which works 259 on Broadcom parts */ 260 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x19); 261 switch ((phy_status>>8) & 0x7) 262 { 263 case 0: 264 result.u64 = 0; 265 break; 266 case 1: 267 result.s.link_up = 1; 268 result.s.full_duplex = 0; 269 result.s.speed = 10; 270 break; 271 case 2: 272 result.s.link_up = 1; 273 result.s.full_duplex = 1; 274 result.s.speed = 10; 275 break; 276 case 3: 277 result.s.link_up = 1; 278 result.s.full_duplex = 0; 279 result.s.speed = 100; 280 break; 281 case 4: 282 result.s.link_up = 1; 283 result.s.full_duplex = 1; 284 result.s.speed = 100; 285 break; 286 case 5: 287 result.s.link_up = 1; 288 result.s.full_duplex = 1; 289 result.s.speed = 100; 290 break; 291 case 6: 292 result.s.link_up = 1; 293 result.s.full_duplex = 0; 294 result.s.speed = 1000; 295 break; 296 case 7: 297 result.s.link_up = 1; 298 result.s.full_duplex = 1; 299 result.s.speed = 1000; 300 break; 301 } 302 } 303 else 304 { 305 /* This code assumes we are using a Marvell Gigabit PHY. All the 306 speed information can be read from register 17 in one go. Somebody 307 using a different PHY will need to handle it above in the board 308 specific area */ 309 int phy_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 310 311 /* If the resolve bit 11 isn't set, see if autoneg is turned off 312 (bit 12, reg 0). The resolve bit doesn't get set properly when 313 autoneg is off, so force it */ 314 if ((phy_status & (1<<11)) == 0) 315 { 316 int auto_status = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0); 317 if ((auto_status & (1<<12)) == 0) 318 phy_status |= 1<<11; 319 } 320 321 /* Only return a link if the PHY has finished auto negotiation 322 and set the resolved bit (bit 11) */ 323 if (phy_status & (1<<11)) 324 { 325 result.s.link_up = 1; 326 result.s.full_duplex = ((phy_status>>13)&1); 327 switch ((phy_status>>14)&3) 328 { 329 case 0: /* 10 Mbps */ 330 result.s.speed = 10; 331 break; 332 case 1: /* 100 Mbps */ 333 result.s.speed = 100; 334 break; 335 case 2: /* 1 Gbps */ 336 result.s.speed = 1000; 337 break; 338 case 3: /* Illegal */ 339 result.u64 = 0; 340 break; 341 } 342 } 343 } 344 } 345 else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN58XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) 346 { 347 /* We don't have a PHY address, so attempt to use in-band status. It is 348 really important that boards not supporting in-band status never get 349 here. Reading broken in-band status tends to do bad things */ 350 cvmx_gmxx_rxx_rx_inbnd_t inband_status; 351 int interface = cvmx_helper_get_interface_num(ipd_port); 352 int index = cvmx_helper_get_interface_index_num(ipd_port); 353 inband_status.u64 = cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 354 355 result.s.link_up = inband_status.s.status; 356 result.s.full_duplex = inband_status.s.duplex; 357 switch (inband_status.s.speed) 358 { 359 case 0: /* 10 Mbps */ 360 result.s.speed = 10; 361 break; 362 case 1: /* 100 Mbps */ 363 result.s.speed = 100; 364 break; 365 case 2: /* 1 Gbps */ 366 result.s.speed = 1000; 367 break; 368 case 3: /* Illegal */ 369 result.u64 = 0; 370 break; 371 } 372 } 373 else 374 { 375 /* We don't have a PHY address and we don't have in-band status. There 376 is no way to determine the link speed. Return down assuming this 377 port isn't wired */ 378 result.u64 = 0; 379 } 380 381 /* If link is down, return all fields as zero. */ 382 if (!result.s.link_up) 383 result.u64 = 0; 384 385 return result; 386} 387 388 389/** 390 * This function as a board specific method of changing the PHY 391 * speed, duplex, and auto-negotiation. This programs the PHY and 392 * not Octeon. This can be used to force Octeon's links to 393 * specific settings. 394 * 395 * @param phy_addr The address of the PHY to program 396 * @param enable_autoneg 397 * Non zero if you want to enable auto-negotiation. 398 * @param link_info Link speed to program. If the speed is zero and auto-negotiation 399 * is enabled, all possible negotiation speeds are advertised. 400 * 401 * @return Zero on success, negative on failure 402 */ 403int cvmx_helper_board_link_set_phy(int phy_addr, cvmx_helper_board_set_phy_link_flags_types_t link_flags, 404 cvmx_helper_link_info_t link_info) 405{ 406 407 /* Set the flow control settings based on link_flags */ 408 if ((link_flags & set_phy_link_flags_flow_control_mask) != set_phy_link_flags_flow_control_dont_touch) 409 { 410 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 411 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 412 reg_autoneg_adver.s.asymmetric_pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 413 reg_autoneg_adver.s.pause = (link_flags & set_phy_link_flags_flow_control_mask) == set_phy_link_flags_flow_control_enable; 414 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 415 } 416 417 /* If speed isn't set and autoneg is on advertise all supported modes */ 418 if ((link_flags & set_phy_link_flags_autoneg) && (link_info.s.speed == 0)) 419 { 420 cvmx_mdio_phy_reg_control_t reg_control; 421 cvmx_mdio_phy_reg_status_t reg_status; 422 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 423 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 424 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 425 426 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 427 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 428 reg_autoneg_adver.s.advert_100base_t4 = reg_status.s.capable_100base_t4; 429 reg_autoneg_adver.s.advert_10base_tx_full = reg_status.s.capable_10_full; 430 reg_autoneg_adver.s.advert_10base_tx_half = reg_status.s.capable_10_half; 431 reg_autoneg_adver.s.advert_100base_tx_full = reg_status.s.capable_100base_x_full; 432 reg_autoneg_adver.s.advert_100base_tx_half = reg_status.s.capable_100base_x_half; 433 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 434 if (reg_status.s.capable_extended_status) 435 { 436 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 437 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 438 reg_control_1000.s.advert_1000base_t_full = reg_extended_status.s.capable_1000base_t_full; 439 reg_control_1000.s.advert_1000base_t_half = reg_extended_status.s.capable_1000base_t_half; 440 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 441 } 442 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 443 reg_control.s.autoneg_enable = 1; 444 reg_control.s.restart_autoneg = 1; 445 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 446 } 447 else if ((link_flags & set_phy_link_flags_autoneg)) 448 { 449 cvmx_mdio_phy_reg_control_t reg_control; 450 cvmx_mdio_phy_reg_status_t reg_status; 451 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 452 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 453 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 454 455 reg_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_STATUS); 456 reg_autoneg_adver.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 457 reg_autoneg_adver.s.advert_100base_t4 = 0; 458 reg_autoneg_adver.s.advert_10base_tx_full = 0; 459 reg_autoneg_adver.s.advert_10base_tx_half = 0; 460 reg_autoneg_adver.s.advert_100base_tx_full = 0; 461 reg_autoneg_adver.s.advert_100base_tx_half = 0; 462 if (reg_status.s.capable_extended_status) 463 { 464 reg_extended_status.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 465 reg_control_1000.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000); 466 reg_control_1000.s.advert_1000base_t_full = 0; 467 reg_control_1000.s.advert_1000base_t_half = 0; 468 } 469 switch (link_info.s.speed) 470 { 471 case 10: 472 reg_autoneg_adver.s.advert_10base_tx_full = link_info.s.full_duplex; 473 reg_autoneg_adver.s.advert_10base_tx_half = !link_info.s.full_duplex; 474 break; 475 case 100: 476 reg_autoneg_adver.s.advert_100base_tx_full = link_info.s.full_duplex; 477 reg_autoneg_adver.s.advert_100base_tx_half = !link_info.s.full_duplex; 478 break; 479 case 1000: 480 reg_control_1000.s.advert_1000base_t_full = link_info.s.full_duplex; 481 reg_control_1000.s.advert_1000base_t_half = !link_info.s.full_duplex; 482 break; 483 } 484 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_AUTONEG_ADVER, reg_autoneg_adver.u16); 485 if (reg_status.s.capable_extended_status) 486 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL_1000, reg_control_1000.u16); 487 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 488 reg_control.s.autoneg_enable = 1; 489 reg_control.s.restart_autoneg = 1; 490 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 491 } 492 else 493 { 494 cvmx_mdio_phy_reg_control_t reg_control; 495 reg_control.u16 = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL); 496 reg_control.s.autoneg_enable = 0; 497 reg_control.s.restart_autoneg = 1; 498 reg_control.s.duplex = link_info.s.full_duplex; 499 if (link_info.s.speed == 1000) 500 { 501 reg_control.s.speed_msb = 1; 502 reg_control.s.speed_lsb = 0; 503 } 504 else if (link_info.s.speed == 100) 505 { 506 reg_control.s.speed_msb = 0; 507 reg_control.s.speed_lsb = 1; 508 } 509 else if (link_info.s.speed == 10) 510 { 511 reg_control.s.speed_msb = 0; 512 reg_control.s.speed_lsb = 0; 513 } 514 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 515 } 516 return 0; 517} 518 519 520/** 521 * @INTERNAL 522 * This function is called by cvmx_helper_interface_probe() after it 523 * determines the number of ports Octeon can support on a specific 524 * interface. This function is the per board location to override 525 * this value. It is called with the number of ports Octeon might 526 * support and should return the number of actual ports on the 527 * board. 528 * 529 * This function must be modifed for every new Octeon board. 530 * Internally it uses switch statements based on the cvmx_sysinfo 531 * data to determine board types and revisions. It relys on the 532 * fact that every Octeon board receives a unique board type 533 * enumeration from the bootloader. 534 * 535 * @param interface Interface to probe 536 * @param supported_ports 537 * Number of ports Octeon supports. 538 * 539 * @return Number of ports the actual board supports. Many times this will 540 * simple be "support_ports". 541 */ 542int __cvmx_helper_board_interface_probe(int interface, int supported_ports) 543{ 544 switch (cvmx_sysinfo_get()->board_type) 545 { 546 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 547 if (interface == 0) 548 return 2; 549 break; 550 case CVMX_BOARD_TYPE_BBGW_REF: 551 if (interface == 0) 552 return 2; 553 break; 554 case CVMX_BOARD_TYPE_NIC_XLE_4G: 555 if (interface == 0) 556 return 0; 557 break; 558 /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 559 which we don't support. Disable ports connected to it */ 560 case CVMX_BOARD_TYPE_EBH5600: 561 if (interface == 1) 562 return 0; 563 break; 564 } 565#ifdef CVMX_BUILD_FOR_UBOOT 566 if (CVMX_HELPER_INTERFACE_MODE_SPI == cvmx_helper_interface_get_mode(interface) && getenv("disable_spi")) 567 return 0; 568#endif 569 return supported_ports; 570} 571 572 573/** 574 * @INTERNAL 575 * Enable packet input/output from the hardware. This function is 576 * called after by cvmx_helper_packet_hardware_enable() to 577 * perform board specific initialization. For most boards 578 * nothing is needed. 579 * 580 * @param interface Interface to enable 581 * 582 * @return Zero on success, negative on failure 583 */ 584int __cvmx_helper_board_hardware_enable(int interface) 585{ 586 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) 587 { 588 if (interface == 0) 589 { 590 /* Different config for switch port */ 591 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 592 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 593 /* Boards with gigabit WAN ports need a different setting that is 594 compatible with 100 Mbit settings */ 595 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0xc); 596 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0xc); 597 } 598 } 599 else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3010_EVB_HS5) 600 { 601 /* Broadcom PHYs require differnet ASX clocks. Unfortunately 602 many customer don't define a new board Id and simply 603 mangle the CN3010_EVB_HS5 */ 604 if (interface == 0) 605 { 606 /* Some customers boards use a hacked up bootloader that identifies them as 607 ** CN3010_EVB_HS5 evaluation boards. This leads to all kinds of configuration 608 ** problems. Detect one case, and print warning, while trying to do the right thing. 609 */ 610 int phy_addr = cvmx_helper_board_get_mii_address(0); 611 if (phy_addr != -1) 612 { 613 int phy_identifier = cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 0x2); 614 /* Is it a Broadcom PHY? */ 615 if (phy_identifier == 0x0143) 616 { 617 cvmx_dprintf("\n"); 618 cvmx_dprintf("ERROR:\n"); 619 cvmx_dprintf("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 620 cvmx_dprintf("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 621 cvmx_dprintf("ERROR: All boards require a unique board type to identify them.\n"); 622 cvmx_dprintf("ERROR:\n"); 623 cvmx_dprintf("\n"); 624 cvmx_wait(1000000000); 625 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 5); 626 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 5); 627 } 628 } 629 } 630 } 631 return 0; 632} 633 634cvmx_helper_board_usb_clock_types_t __cvmx_helper_board_usb_get_clock_type(void) 635{ 636 switch (cvmx_sysinfo_get()->board_type) { 637 case CVMX_BOARD_TYPE_BBGW_REF: 638 return USB_CLOCK_TYPE_CRYSTAL_12; 639 } 640 return USB_CLOCK_TYPE_REF_48; 641} 642 643int __cvmx_helper_board_usb_get_num_ports(int supported_ports) 644{ 645 switch (cvmx_sysinfo_get()->board_type) { 646 case CVMX_BOARD_TYPE_NIC_XLE_4G: 647 return 0; 648 } 649 650 return supported_ports; 651} 652 653 654