linux/drivers/staging/octeon/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 "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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.