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 <asm/octeon/cvmx-config.h> 38 39 #include <asm/octeon/cvmx-mdio.h> 40 41 #include <asm/octeon/cvmx-helper.h> 42 #include <asm/octeon/cvmx-helper-util.h> 43 #include <asm/octeon/cvmx-helper-board.h> 44 45 #include <asm/octeon/cvmx-gmxx-defs.h> 46 #include <asm/octeon/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 */ 56 cvmx_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 */ 75 int 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 /* Board has 2 management ports */ 121 if ((ipd_port >= CVMX_HELPER_BOARD_MGMT_IPD_PORT) && 122 (ipd_port < (CVMX_HELPER_BOARD_MGMT_IPD_PORT + 2))) 123 return ipd_port - CVMX_HELPER_BOARD_MGMT_IPD_PORT; 124 /* 125 * Board has 4 SGMII ports. The PHYs start right after the MII 126 * ports MII0 = 0, MII1 = 1, SGMII = 2-5. 127 */ 128 if ((ipd_port >= 0) && (ipd_port < 4)) 129 return ipd_port + 2; 130 else 131 return -1; 132 case CVMX_BOARD_TYPE_EBH5600: 133 case CVMX_BOARD_TYPE_EBH5601: 134 case CVMX_BOARD_TYPE_EBH5610: 135 /* Board has 1 management port */ 136 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 137 return 0; 138 /* 139 * Board has 8 SGMII ports. 4 connect out, two connect 140 * to a switch, and 2 loop to each other 141 */ 142 if ((ipd_port >= 0) && (ipd_port < 4)) 143 return ipd_port + 1; 144 else 145 return -1; 146 case CVMX_BOARD_TYPE_CUST_NB5: 147 if (ipd_port == 2) 148 return 4; 149 else 150 return -1; 151 case CVMX_BOARD_TYPE_NIC_XLE_4G: 152 /* Board has 4 SGMII ports. connected QLM3(interface 1) */ 153 if ((ipd_port >= 16) && (ipd_port < 20)) 154 return ipd_port - 16 + 1; 155 else 156 return -1; 157 case CVMX_BOARD_TYPE_NIC_XLE_10G: 158 case CVMX_BOARD_TYPE_NIC10E: 159 return -1; 160 case CVMX_BOARD_TYPE_NIC4E: 161 if (ipd_port >= 0 && ipd_port <= 3) 162 return (ipd_port + 0x1f) & 0x1f; 163 else 164 return -1; 165 case CVMX_BOARD_TYPE_NIC2E: 166 if (ipd_port >= 0 && ipd_port <= 1) 167 return ipd_port + 1; 168 else 169 return -1; 170 case CVMX_BOARD_TYPE_BBGW_REF: 171 /* 172 * No PHYs are connected to Octeon, everything is 173 * through switch. 174 */ 175 return -1; 176 177 case CVMX_BOARD_TYPE_CUST_WSX16: 178 if (ipd_port >= 0 && ipd_port <= 3) 179 return ipd_port; 180 else if (ipd_port >= 16 && ipd_port <= 19) 181 return ipd_port - 16 + 4; 182 else 183 return -1; 184 case CVMX_BOARD_TYPE_UBNT_E100: 185 if (ipd_port >= 0 && ipd_port <= 2) 186 return 7 - ipd_port; 187 else 188 return -1; 189 case CVMX_BOARD_TYPE_CUST_DSR1000N: 190 /* 191 * Port 2 connects to Broadcom PHY (B5081). Other ports (0-1) 192 * connect to a switch (BCM53115). 193 */ 194 if (ipd_port == 2) 195 return 8; 196 else 197 return -1; 198 case CVMX_BOARD_TYPE_KONTRON_S1901: 199 if (ipd_port == CVMX_HELPER_BOARD_MGMT_IPD_PORT) 200 return 1; 201 else 202 return -1; 203 204 } 205 206 /* Some unknown board. Somebody forgot to update this function... */ 207 cvmx_dprintf 208 ("cvmx_helper_board_get_mii_address: Unknown board type %d\n", 209 cvmx_sysinfo_get()->board_type); 210 return -1; 211 } 212 213 /** 214 * This function is the board specific method of determining an 215 * ethernet ports link speed. Most Octeon boards have Marvell PHYs 216 * and are handled by the fall through case. This function must be 217 * updated for boards that don't have the normal Marvell PHYs. 218 * 219 * This function must be modified for every new Octeon board. 220 * Internally it uses switch statements based on the cvmx_sysinfo 221 * data to determine board types and revisions. It relies on the 222 * fact that every Octeon board receives a unique board type 223 * enumeration from the bootloader. 224 * 225 * @ipd_port: IPD input port associated with the port we want to get link 226 * status for. 227 * 228 * Returns The ports link status. If the link isn't fully resolved, this must 229 * return zero. 230 */ 231 cvmx_helper_link_info_t __cvmx_helper_board_link_get(int ipd_port) 232 { 233 cvmx_helper_link_info_t result; 234 int phy_addr; 235 int is_broadcom_phy = 0; 236 237 /* Give the user a chance to override the processing of this function */ 238 if (cvmx_override_board_link_get) 239 return cvmx_override_board_link_get(ipd_port); 240 241 /* Unless we fix it later, all links are defaulted to down */ 242 result.u64 = 0; 243 244 /* 245 * This switch statement should handle all ports that either don't use 246 * Marvell PHYS, or don't support in-band status. 247 */ 248 switch (cvmx_sysinfo_get()->board_type) { 249 case CVMX_BOARD_TYPE_SIM: 250 /* The simulator gives you a simulated 1Gbps full duplex link */ 251 result.s.link_up = 1; 252 result.s.full_duplex = 1; 253 result.s.speed = 1000; 254 return result; 255 case CVMX_BOARD_TYPE_EBH3100: 256 case CVMX_BOARD_TYPE_CN3010_EVB_HS5: 257 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 258 case CVMX_BOARD_TYPE_CN3020_EVB_HS5: 259 /* Port 1 on these boards is always Gigabit */ 260 if (ipd_port == 1) { 261 result.s.link_up = 1; 262 result.s.full_duplex = 1; 263 result.s.speed = 1000; 264 return result; 265 } 266 /* Fall through to the generic code below */ 267 break; 268 case CVMX_BOARD_TYPE_CUST_NB5: 269 /* Port 1 on these boards is always Gigabit */ 270 if (ipd_port == 1) { 271 result.s.link_up = 1; 272 result.s.full_duplex = 1; 273 result.s.speed = 1000; 274 return result; 275 } else /* The other port uses a broadcom PHY */ 276 is_broadcom_phy = 1; 277 break; 278 case CVMX_BOARD_TYPE_BBGW_REF: 279 /* Port 1 on these boards is always Gigabit */ 280 if (ipd_port == 2) { 281 /* Port 2 is not hooked up */ 282 result.u64 = 0; 283 return result; 284 } else { 285 /* Ports 0 and 1 connect to the switch */ 286 result.s.link_up = 1; 287 result.s.full_duplex = 1; 288 result.s.speed = 1000; 289 return result; 290 } 291 break; 292 case CVMX_BOARD_TYPE_CUST_DSR1000N: 293 if (ipd_port == 0 || ipd_port == 1) { 294 /* Ports 0 and 1 connect to a switch (BCM53115). */ 295 result.s.link_up = 1; 296 result.s.full_duplex = 1; 297 result.s.speed = 1000; 298 return result; 299 } else { 300 /* Port 2 uses a Broadcom PHY (B5081). */ 301 is_broadcom_phy = 1; 302 } 303 break; 304 } 305 306 phy_addr = cvmx_helper_board_get_mii_address(ipd_port); 307 if (phy_addr != -1) { 308 if (is_broadcom_phy) { 309 /* 310 * Below we are going to read SMI/MDIO 311 * register 0x19 which works on Broadcom 312 * parts 313 */ 314 int phy_status = 315 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 316 0x19); 317 switch ((phy_status >> 8) & 0x7) { 318 case 0: 319 result.u64 = 0; 320 break; 321 case 1: 322 result.s.link_up = 1; 323 result.s.full_duplex = 0; 324 result.s.speed = 10; 325 break; 326 case 2: 327 result.s.link_up = 1; 328 result.s.full_duplex = 1; 329 result.s.speed = 10; 330 break; 331 case 3: 332 result.s.link_up = 1; 333 result.s.full_duplex = 0; 334 result.s.speed = 100; 335 break; 336 case 4: 337 result.s.link_up = 1; 338 result.s.full_duplex = 1; 339 result.s.speed = 100; 340 break; 341 case 5: 342 result.s.link_up = 1; 343 result.s.full_duplex = 1; 344 result.s.speed = 100; 345 break; 346 case 6: 347 result.s.link_up = 1; 348 result.s.full_duplex = 0; 349 result.s.speed = 1000; 350 break; 351 case 7: 352 result.s.link_up = 1; 353 result.s.full_duplex = 1; 354 result.s.speed = 1000; 355 break; 356 } 357 } else { 358 /* 359 * This code assumes we are using a Marvell 360 * Gigabit PHY. All the speed information can 361 * be read from register 17 in one 362 * go. Somebody using a different PHY will 363 * need to handle it above in the board 364 * specific area. 365 */ 366 int phy_status = 367 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 17); 368 369 /* 370 * If the resolve bit 11 isn't set, see if 371 * autoneg is turned off (bit 12, reg 0). The 372 * resolve bit doesn't get set properly when 373 * autoneg is off, so force it. 374 */ 375 if ((phy_status & (1 << 11)) == 0) { 376 int auto_status = 377 cvmx_mdio_read(phy_addr >> 8, 378 phy_addr & 0xff, 0); 379 if ((auto_status & (1 << 12)) == 0) 380 phy_status |= 1 << 11; 381 } 382 383 /* 384 * Only return a link if the PHY has finished 385 * auto negotiation and set the resolved bit 386 * (bit 11) 387 */ 388 if (phy_status & (1 << 11)) { 389 result.s.link_up = 1; 390 result.s.full_duplex = ((phy_status >> 13) & 1); 391 switch ((phy_status >> 14) & 3) { 392 case 0: /* 10 Mbps */ 393 result.s.speed = 10; 394 break; 395 case 1: /* 100 Mbps */ 396 result.s.speed = 100; 397 break; 398 case 2: /* 1 Gbps */ 399 result.s.speed = 1000; 400 break; 401 case 3: /* Illegal */ 402 result.u64 = 0; 403 break; 404 } 405 } 406 } 407 } else if (OCTEON_IS_MODEL(OCTEON_CN3XXX) 408 || OCTEON_IS_MODEL(OCTEON_CN58XX) 409 || OCTEON_IS_MODEL(OCTEON_CN50XX)) { 410 /* 411 * We don't have a PHY address, so attempt to use 412 * in-band status. It is really important that boards 413 * not supporting in-band status never get 414 * here. Reading broken in-band status tends to do bad 415 * things 416 */ 417 union cvmx_gmxx_rxx_rx_inbnd inband_status; 418 int interface = cvmx_helper_get_interface_num(ipd_port); 419 int index = cvmx_helper_get_interface_index_num(ipd_port); 420 inband_status.u64 = 421 cvmx_read_csr(CVMX_GMXX_RXX_RX_INBND(index, interface)); 422 423 result.s.link_up = inband_status.s.status; 424 result.s.full_duplex = inband_status.s.duplex; 425 switch (inband_status.s.speed) { 426 case 0: /* 10 Mbps */ 427 result.s.speed = 10; 428 break; 429 case 1: /* 100 Mbps */ 430 result.s.speed = 100; 431 break; 432 case 2: /* 1 Gbps */ 433 result.s.speed = 1000; 434 break; 435 case 3: /* Illegal */ 436 result.u64 = 0; 437 break; 438 } 439 } else { 440 /* 441 * We don't have a PHY address and we don't have 442 * in-band status. There is no way to determine the 443 * link speed. Return down assuming this port isn't 444 * wired 445 */ 446 result.u64 = 0; 447 } 448 449 /* If link is down, return all fields as zero. */ 450 if (!result.s.link_up) 451 result.u64 = 0; 452 453 return result; 454 } 455 456 /** 457 * This function as a board specific method of changing the PHY 458 * speed, duplex, and auto-negotiation. This programs the PHY and 459 * not Octeon. This can be used to force Octeon's links to 460 * specific settings. 461 * 462 * @phy_addr: The address of the PHY to program 463 * @enable_autoneg: 464 * Non zero if you want to enable auto-negotiation. 465 * @link_info: Link speed to program. If the speed is zero and auto-negotiation 466 * is enabled, all possible negotiation speeds are advertised. 467 * 468 * Returns Zero on success, negative on failure 469 */ 470 int cvmx_helper_board_link_set_phy(int phy_addr, 471 cvmx_helper_board_set_phy_link_flags_types_t 472 link_flags, 473 cvmx_helper_link_info_t link_info) 474 { 475 476 /* Set the flow control settings based on link_flags */ 477 if ((link_flags & set_phy_link_flags_flow_control_mask) != 478 set_phy_link_flags_flow_control_dont_touch) { 479 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 480 reg_autoneg_adver.u16 = 481 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 482 CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 483 reg_autoneg_adver.s.asymmetric_pause = 484 (link_flags & set_phy_link_flags_flow_control_mask) == 485 set_phy_link_flags_flow_control_enable; 486 reg_autoneg_adver.s.pause = 487 (link_flags & set_phy_link_flags_flow_control_mask) == 488 set_phy_link_flags_flow_control_enable; 489 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 490 CVMX_MDIO_PHY_REG_AUTONEG_ADVER, 491 reg_autoneg_adver.u16); 492 } 493 494 /* If speed isn't set and autoneg is on advertise all supported modes */ 495 if ((link_flags & set_phy_link_flags_autoneg) 496 && (link_info.s.speed == 0)) { 497 cvmx_mdio_phy_reg_control_t reg_control; 498 cvmx_mdio_phy_reg_status_t reg_status; 499 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 500 cvmx_mdio_phy_reg_extended_status_t reg_extended_status; 501 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 502 503 reg_status.u16 = 504 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 505 CVMX_MDIO_PHY_REG_STATUS); 506 reg_autoneg_adver.u16 = 507 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 508 CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 509 reg_autoneg_adver.s.advert_100base_t4 = 510 reg_status.s.capable_100base_t4; 511 reg_autoneg_adver.s.advert_10base_tx_full = 512 reg_status.s.capable_10_full; 513 reg_autoneg_adver.s.advert_10base_tx_half = 514 reg_status.s.capable_10_half; 515 reg_autoneg_adver.s.advert_100base_tx_full = 516 reg_status.s.capable_100base_x_full; 517 reg_autoneg_adver.s.advert_100base_tx_half = 518 reg_status.s.capable_100base_x_half; 519 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 520 CVMX_MDIO_PHY_REG_AUTONEG_ADVER, 521 reg_autoneg_adver.u16); 522 if (reg_status.s.capable_extended_status) { 523 reg_extended_status.u16 = 524 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 525 CVMX_MDIO_PHY_REG_EXTENDED_STATUS); 526 reg_control_1000.u16 = 527 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 528 CVMX_MDIO_PHY_REG_CONTROL_1000); 529 reg_control_1000.s.advert_1000base_t_full = 530 reg_extended_status.s.capable_1000base_t_full; 531 reg_control_1000.s.advert_1000base_t_half = 532 reg_extended_status.s.capable_1000base_t_half; 533 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 534 CVMX_MDIO_PHY_REG_CONTROL_1000, 535 reg_control_1000.u16); 536 } 537 reg_control.u16 = 538 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 539 CVMX_MDIO_PHY_REG_CONTROL); 540 reg_control.s.autoneg_enable = 1; 541 reg_control.s.restart_autoneg = 1; 542 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 543 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 544 } else if ((link_flags & set_phy_link_flags_autoneg)) { 545 cvmx_mdio_phy_reg_control_t reg_control; 546 cvmx_mdio_phy_reg_status_t reg_status; 547 cvmx_mdio_phy_reg_autoneg_adver_t reg_autoneg_adver; 548 cvmx_mdio_phy_reg_control_1000_t reg_control_1000; 549 550 reg_status.u16 = 551 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 552 CVMX_MDIO_PHY_REG_STATUS); 553 reg_autoneg_adver.u16 = 554 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 555 CVMX_MDIO_PHY_REG_AUTONEG_ADVER); 556 reg_autoneg_adver.s.advert_100base_t4 = 0; 557 reg_autoneg_adver.s.advert_10base_tx_full = 0; 558 reg_autoneg_adver.s.advert_10base_tx_half = 0; 559 reg_autoneg_adver.s.advert_100base_tx_full = 0; 560 reg_autoneg_adver.s.advert_100base_tx_half = 0; 561 if (reg_status.s.capable_extended_status) { 562 reg_control_1000.u16 = 563 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 564 CVMX_MDIO_PHY_REG_CONTROL_1000); 565 reg_control_1000.s.advert_1000base_t_full = 0; 566 reg_control_1000.s.advert_1000base_t_half = 0; 567 } 568 switch (link_info.s.speed) { 569 case 10: 570 reg_autoneg_adver.s.advert_10base_tx_full = 571 link_info.s.full_duplex; 572 reg_autoneg_adver.s.advert_10base_tx_half = 573 !link_info.s.full_duplex; 574 break; 575 case 100: 576 reg_autoneg_adver.s.advert_100base_tx_full = 577 link_info.s.full_duplex; 578 reg_autoneg_adver.s.advert_100base_tx_half = 579 !link_info.s.full_duplex; 580 break; 581 case 1000: 582 reg_control_1000.s.advert_1000base_t_full = 583 link_info.s.full_duplex; 584 reg_control_1000.s.advert_1000base_t_half = 585 !link_info.s.full_duplex; 586 break; 587 } 588 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 589 CVMX_MDIO_PHY_REG_AUTONEG_ADVER, 590 reg_autoneg_adver.u16); 591 if (reg_status.s.capable_extended_status) 592 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 593 CVMX_MDIO_PHY_REG_CONTROL_1000, 594 reg_control_1000.u16); 595 reg_control.u16 = 596 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 597 CVMX_MDIO_PHY_REG_CONTROL); 598 reg_control.s.autoneg_enable = 1; 599 reg_control.s.restart_autoneg = 1; 600 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 601 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 602 } else { 603 cvmx_mdio_phy_reg_control_t reg_control; 604 reg_control.u16 = 605 cvmx_mdio_read(phy_addr >> 8, phy_addr & 0xff, 606 CVMX_MDIO_PHY_REG_CONTROL); 607 reg_control.s.autoneg_enable = 0; 608 reg_control.s.restart_autoneg = 1; 609 reg_control.s.duplex = link_info.s.full_duplex; 610 if (link_info.s.speed == 1000) { 611 reg_control.s.speed_msb = 1; 612 reg_control.s.speed_lsb = 0; 613 } else if (link_info.s.speed == 100) { 614 reg_control.s.speed_msb = 0; 615 reg_control.s.speed_lsb = 1; 616 } else if (link_info.s.speed == 10) { 617 reg_control.s.speed_msb = 0; 618 reg_control.s.speed_lsb = 0; 619 } 620 cvmx_mdio_write(phy_addr >> 8, phy_addr & 0xff, 621 CVMX_MDIO_PHY_REG_CONTROL, reg_control.u16); 622 } 623 return 0; 624 } 625 626 /** 627 * This function is called by cvmx_helper_interface_probe() after it 628 * determines the number of ports Octeon can support on a specific 629 * interface. This function is the per board location to override 630 * this value. It is called with the number of ports Octeon might 631 * support and should return the number of actual ports on the 632 * board. 633 * 634 * This function must be modifed for every new Octeon board. 635 * Internally it uses switch statements based on the cvmx_sysinfo 636 * data to determine board types and revisions. It relys on the 637 * fact that every Octeon board receives a unique board type 638 * enumeration from the bootloader. 639 * 640 * @interface: Interface to probe 641 * @supported_ports: 642 * Number of ports Octeon supports. 643 * 644 * Returns Number of ports the actual board supports. Many times this will 645 * simple be "support_ports". 646 */ 647 int __cvmx_helper_board_interface_probe(int interface, int supported_ports) 648 { 649 switch (cvmx_sysinfo_get()->board_type) { 650 case CVMX_BOARD_TYPE_CN3005_EVB_HS5: 651 if (interface == 0) 652 return 2; 653 break; 654 case CVMX_BOARD_TYPE_BBGW_REF: 655 if (interface == 0) 656 return 2; 657 break; 658 case CVMX_BOARD_TYPE_NIC_XLE_4G: 659 if (interface == 0) 660 return 0; 661 break; 662 /* The 2nd interface on the EBH5600 is connected to the Marvel switch, 663 which we don't support. Disable ports connected to it */ 664 case CVMX_BOARD_TYPE_EBH5600: 665 if (interface == 1) 666 return 0; 667 break; 668 } 669 return supported_ports; 670 } 671 672 /** 673 * Enable packet input/output from the hardware. This function is 674 * called after by cvmx_helper_packet_hardware_enable() to 675 * perform board specific initialization. For most boards 676 * nothing is needed. 677 * 678 * @interface: Interface to enable 679 * 680 * Returns Zero on success, negative on failure 681 */ 682 int __cvmx_helper_board_hardware_enable(int interface) 683 { 684 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5) { 685 if (interface == 0) { 686 /* Different config for switch port */ 687 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0); 688 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 689 /* 690 * Boards with gigabit WAN ports need a 691 * different setting that is compatible with 692 * 100 Mbit settings 693 */ 694 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 695 0xc); 696 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 697 0xc); 698 } 699 } else if (cvmx_sysinfo_get()->board_type == 700 CVMX_BOARD_TYPE_CN3010_EVB_HS5) { 701 /* 702 * Broadcom PHYs require differnet ASX 703 * clocks. Unfortunately many boards don't define a 704 * new board Id and simply mangle the 705 * CN3010_EVB_HS5 706 */ 707 if (interface == 0) { 708 /* 709 * Some boards use a hacked up bootloader that 710 * identifies them as CN3010_EVB_HS5 711 * evaluation boards. This leads to all kinds 712 * of configuration problems. Detect one 713 * case, and print warning, while trying to do 714 * the right thing. 715 */ 716 int phy_addr = cvmx_helper_board_get_mii_address(0); 717 if (phy_addr != -1) { 718 int phy_identifier = 719 cvmx_mdio_read(phy_addr >> 8, 720 phy_addr & 0xff, 0x2); 721 /* Is it a Broadcom PHY? */ 722 if (phy_identifier == 0x0143) { 723 cvmx_dprintf("\n"); 724 cvmx_dprintf("ERROR:\n"); 725 cvmx_dprintf 726 ("ERROR: Board type is CVMX_BOARD_TYPE_CN3010_EVB_HS5, but Broadcom PHY found.\n"); 727 cvmx_dprintf 728 ("ERROR: The board type is mis-configured, and software malfunctions are likely.\n"); 729 cvmx_dprintf 730 ("ERROR: All boards require a unique board type to identify them.\n"); 731 cvmx_dprintf("ERROR:\n"); 732 cvmx_dprintf("\n"); 733 cvmx_wait(1000000000); 734 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX 735 (0, interface), 5); 736 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX 737 (0, interface), 5); 738 } 739 } 740 } 741 } else if (cvmx_sysinfo_get()->board_type == 742 CVMX_BOARD_TYPE_UBNT_E100) { 743 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(0, interface), 0); 744 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(0, interface), 0x10); 745 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(1, interface), 0); 746 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(1, interface), 0x10); 747 cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(2, interface), 0); 748 cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(2, interface), 0x10); 749 } 750 return 0; 751 } 752 753 /** 754 * Get the clock type used for the USB block based on board type. 755 * Used by the USB code for auto configuration of clock type. 756 * 757 * Return USB clock type enumeration 758 */ 759 enum cvmx_helper_board_usb_clock_types __cvmx_helper_board_usb_get_clock_type(void) 760 { 761 switch (cvmx_sysinfo_get()->board_type) { 762 case CVMX_BOARD_TYPE_BBGW_REF: 763 case CVMX_BOARD_TYPE_LANAI2_A: 764 case CVMX_BOARD_TYPE_LANAI2_U: 765 case CVMX_BOARD_TYPE_LANAI2_G: 766 case CVMX_BOARD_TYPE_NIC10E_66: 767 case CVMX_BOARD_TYPE_UBNT_E100: 768 case CVMX_BOARD_TYPE_CUST_DSR1000N: 769 return USB_CLOCK_TYPE_CRYSTAL_12; 770 case CVMX_BOARD_TYPE_NIC10E: 771 return USB_CLOCK_TYPE_REF_12; 772 default: 773 break; 774 } 775 /* Most boards except NIC10e use a 12MHz crystal */ 776 if (OCTEON_IS_OCTEON2()) 777 return USB_CLOCK_TYPE_CRYSTAL_12; 778 return USB_CLOCK_TYPE_REF_48; 779 } 780