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