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