linux/arch/mips/cavium-octeon/executive/cvmx-helper.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 for common, but complicated tasks.
  31 *
  32 */
  33#include <asm/octeon/octeon.h>
  34
  35#include <asm/octeon/cvmx-config.h>
  36
  37#include <asm/octeon/cvmx-fpa.h>
  38#include <asm/octeon/cvmx-pip.h>
  39#include <asm/octeon/cvmx-pko.h>
  40#include <asm/octeon/cvmx-ipd.h>
  41#include <asm/octeon/cvmx-spi.h>
  42#include <asm/octeon/cvmx-helper.h>
  43#include <asm/octeon/cvmx-helper-board.h>
  44
  45#include <asm/octeon/cvmx-pip-defs.h>
  46#include <asm/octeon/cvmx-smix-defs.h>
  47#include <asm/octeon/cvmx-asxx-defs.h>
  48
  49/**
  50 * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
  51 * priorities[16]) is a function pointer. It is meant to allow
  52 * customization of the PKO queue priorities based on the port
  53 * number. Users should set this pointer to a function before
  54 * calling any cvmx-helper operations.
  55 */
  56void (*cvmx_override_pko_queue_priority) (int pko_port,
  57                                          uint64_t priorities[16]);
  58
  59/**
  60 * cvmx_override_ipd_port_setup(int ipd_port) is a function
  61 * pointer. It is meant to allow customization of the IPD port
  62 * setup before packet input/output comes online. It is called
  63 * after cvmx-helper does the default IPD configuration, but
  64 * before IPD is enabled. Users should set this pointer to a
  65 * function before calling any cvmx-helper operations.
  66 */
  67void (*cvmx_override_ipd_port_setup) (int ipd_port);
  68
  69/* Port count per interface */
  70static int interface_port_count[4] = { 0, 0, 0, 0 };
  71
  72/* Port last configured link info index by IPD/PKO port */
  73static cvmx_helper_link_info_t
  74    port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
  75
  76/**
  77 * Return the number of interfaces the chip has. Each interface
  78 * may have multiple ports. Most chips support two interfaces,
  79 * but the CNX0XX and CNX1XX are exceptions. These only support
  80 * one interface.
  81 *
  82 * Returns Number of interfaces on chip
  83 */
  84int cvmx_helper_get_number_of_interfaces(void)
  85{
  86        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
  87                return 4;
  88        else
  89                return 3;
  90}
  91
  92/**
  93 * Return the number of ports on an interface. Depending on the
  94 * chip and configuration, this can be 1-16. A value of 0
  95 * specifies that the interface doesn't exist or isn't usable.
  96 *
  97 * @interface: Interface to get the port count for
  98 *
  99 * Returns Number of ports on interface. Can be Zero.
 100 */
 101int cvmx_helper_ports_on_interface(int interface)
 102{
 103        return interface_port_count[interface];
 104}
 105
 106/**
 107 * Get the operating mode of an interface. Depending on the Octeon
 108 * chip and configuration, this function returns an enumeration
 109 * of the type of packet I/O supported by an interface.
 110 *
 111 * @interface: Interface to probe
 112 *
 113 * Returns Mode of the interface. Unknown or unsupported interfaces return
 114 *         DISABLED.
 115 */
 116cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
 117{
 118        union cvmx_gmxx_inf_mode mode;
 119        if (interface == 2)
 120                return CVMX_HELPER_INTERFACE_MODE_NPI;
 121
 122        if (interface == 3) {
 123                if (OCTEON_IS_MODEL(OCTEON_CN56XX)
 124                    || OCTEON_IS_MODEL(OCTEON_CN52XX))
 125                        return CVMX_HELPER_INTERFACE_MODE_LOOP;
 126                else
 127                        return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 128        }
 129
 130        if (interface == 0
 131            && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
 132            && cvmx_sysinfo_get()->board_rev_major == 1) {
 133                /*
 134                 * Lie about interface type of CN3005 board.  This
 135                 * board has a switch on port 1 like the other
 136                 * evaluation boards, but it is connected over RGMII
 137                 * instead of GMII.  Report GMII mode so that the
 138                 * speed is forced to 1 Gbit full duplex.  Other than
 139                 * some initial configuration (which does not use the
 140                 * output of this function) there is no difference in
 141                 * setup between GMII and RGMII modes.
 142                 */
 143                return CVMX_HELPER_INTERFACE_MODE_GMII;
 144        }
 145
 146        /* Interface 1 is always disabled on CN31XX and CN30XX */
 147        if ((interface == 1)
 148            && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
 149                || OCTEON_IS_MODEL(OCTEON_CN50XX)
 150                || OCTEON_IS_MODEL(OCTEON_CN52XX)))
 151                return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 152
 153        mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
 154
 155        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
 156                switch (mode.cn56xx.mode) {
 157                case 0:
 158                        return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 159                case 1:
 160                        return CVMX_HELPER_INTERFACE_MODE_XAUI;
 161                case 2:
 162                        return CVMX_HELPER_INTERFACE_MODE_SGMII;
 163                case 3:
 164                        return CVMX_HELPER_INTERFACE_MODE_PICMG;
 165                default:
 166                        return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 167                }
 168        } else {
 169                if (!mode.s.en)
 170                        return CVMX_HELPER_INTERFACE_MODE_DISABLED;
 171
 172                if (mode.s.type) {
 173                        if (OCTEON_IS_MODEL(OCTEON_CN38XX)
 174                            || OCTEON_IS_MODEL(OCTEON_CN58XX))
 175                                return CVMX_HELPER_INTERFACE_MODE_SPI;
 176                        else
 177                                return CVMX_HELPER_INTERFACE_MODE_GMII;
 178                } else
 179                        return CVMX_HELPER_INTERFACE_MODE_RGMII;
 180        }
 181}
 182
 183/**
 184 * Configure the IPD/PIP tagging and QoS options for a specific
 185 * port. This function determines the POW work queue entry
 186 * contents for a port. The setup performed here is controlled by
 187 * the defines in executive-config.h.
 188 *
 189 * @ipd_port: Port to configure. This follows the IPD numbering, not the
 190 *                 per interface numbering
 191 *
 192 * Returns Zero on success, negative on failure
 193 */
 194static int __cvmx_helper_port_setup_ipd(int ipd_port)
 195{
 196        union cvmx_pip_prt_cfgx port_config;
 197        union cvmx_pip_prt_tagx tag_config;
 198
 199        port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
 200        tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
 201
 202        /* Have each port go to a different POW queue */
 203        port_config.s.qos = ipd_port & 0x7;
 204
 205        /* Process the headers and place the IP header in the work queue */
 206        port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
 207
 208        tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
 209        tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
 210        tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
 211        tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
 212        tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
 213        tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
 214        tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
 215        tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
 216        tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
 217        tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
 218        tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
 219        tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
 220        tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
 221        tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
 222        tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
 223        tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
 224        /* Put all packets in group 0. Other groups can be used by the app */
 225        tag_config.s.grp = 0;
 226
 227        cvmx_pip_config_port(ipd_port, port_config, tag_config);
 228
 229        /* Give the user a chance to override our setting for each port */
 230        if (cvmx_override_ipd_port_setup)
 231                cvmx_override_ipd_port_setup(ipd_port);
 232
 233        return 0;
 234}
 235
 236/**
 237 * This function sets the interface_port_count[interface] correctly,
 238 * without modifying any hardware configuration.  Hardware setup of
 239 * the ports will be performed later.
 240 *
 241 * @interface: Interface to probe
 242 *
 243 * Returns Zero on success, negative on failure
 244 */
 245int cvmx_helper_interface_enumerate(int interface)
 246{
 247        switch (cvmx_helper_interface_get_mode(interface)) {
 248                /* These types don't support ports to IPD/PKO */
 249        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
 250        case CVMX_HELPER_INTERFACE_MODE_PCIE:
 251                interface_port_count[interface] = 0;
 252                break;
 253                /* XAUI is a single high speed port */
 254        case CVMX_HELPER_INTERFACE_MODE_XAUI:
 255                interface_port_count[interface] =
 256                    __cvmx_helper_xaui_enumerate(interface);
 257                break;
 258                /*
 259                 * RGMII/GMII/MII are all treated about the same. Most
 260                 * functions refer to these ports as RGMII.
 261                 */
 262        case CVMX_HELPER_INTERFACE_MODE_RGMII:
 263        case CVMX_HELPER_INTERFACE_MODE_GMII:
 264                interface_port_count[interface] =
 265                    __cvmx_helper_rgmii_enumerate(interface);
 266                break;
 267                /*
 268                 * SPI4 can have 1-16 ports depending on the device at
 269                 * the other end.
 270                 */
 271        case CVMX_HELPER_INTERFACE_MODE_SPI:
 272                interface_port_count[interface] =
 273                    __cvmx_helper_spi_enumerate(interface);
 274                break;
 275                /*
 276                 * SGMII can have 1-4 ports depending on how many are
 277                 * hooked up.
 278                 */
 279        case CVMX_HELPER_INTERFACE_MODE_SGMII:
 280        case CVMX_HELPER_INTERFACE_MODE_PICMG:
 281                interface_port_count[interface] =
 282                    __cvmx_helper_sgmii_enumerate(interface);
 283                break;
 284                /* PCI target Network Packet Interface */
 285        case CVMX_HELPER_INTERFACE_MODE_NPI:
 286                interface_port_count[interface] =
 287                    __cvmx_helper_npi_enumerate(interface);
 288                break;
 289                /*
 290                 * Special loopback only ports. These are not the same
 291                 * as other ports in loopback mode.
 292                 */
 293        case CVMX_HELPER_INTERFACE_MODE_LOOP:
 294                interface_port_count[interface] =
 295                    __cvmx_helper_loop_enumerate(interface);
 296                break;
 297        }
 298
 299        interface_port_count[interface] =
 300            __cvmx_helper_board_interface_probe(interface,
 301                                                interface_port_count
 302                                                [interface]);
 303
 304        /* Make sure all global variables propagate to other cores */
 305        CVMX_SYNCWS;
 306
 307        return 0;
 308}
 309
 310/**
 311 * This function probes an interface to determine the actual
 312 * number of hardware ports connected to it. It doesn't setup the
 313 * ports or enable them. The main goal here is to set the global
 314 * interface_port_count[interface] correctly. Hardware setup of the
 315 * ports will be performed later.
 316 *
 317 * @interface: Interface to probe
 318 *
 319 * Returns Zero on success, negative on failure
 320 */
 321int cvmx_helper_interface_probe(int interface)
 322{
 323        cvmx_helper_interface_enumerate(interface);
 324        /* At this stage in the game we don't want packets to be moving yet.
 325           The following probe calls should perform hardware setup
 326           needed to determine port counts. Receive must still be disabled */
 327        switch (cvmx_helper_interface_get_mode(interface)) {
 328                /* These types don't support ports to IPD/PKO */
 329        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
 330        case CVMX_HELPER_INTERFACE_MODE_PCIE:
 331                break;
 332                /* XAUI is a single high speed port */
 333        case CVMX_HELPER_INTERFACE_MODE_XAUI:
 334                __cvmx_helper_xaui_probe(interface);
 335                break;
 336                /*
 337                 * RGMII/GMII/MII are all treated about the same. Most
 338                 * functions refer to these ports as RGMII.
 339                 */
 340        case CVMX_HELPER_INTERFACE_MODE_RGMII:
 341        case CVMX_HELPER_INTERFACE_MODE_GMII:
 342                __cvmx_helper_rgmii_probe(interface);
 343                break;
 344                /*
 345                 * SPI4 can have 1-16 ports depending on the device at
 346                 * the other end.
 347                 */
 348        case CVMX_HELPER_INTERFACE_MODE_SPI:
 349                __cvmx_helper_spi_probe(interface);
 350                break;
 351                /*
 352                 * SGMII can have 1-4 ports depending on how many are
 353                 * hooked up.
 354                 */
 355        case CVMX_HELPER_INTERFACE_MODE_SGMII:
 356        case CVMX_HELPER_INTERFACE_MODE_PICMG:
 357                __cvmx_helper_sgmii_probe(interface);
 358                break;
 359                /* PCI target Network Packet Interface */
 360        case CVMX_HELPER_INTERFACE_MODE_NPI:
 361                __cvmx_helper_npi_probe(interface);
 362                break;
 363                /*
 364                 * Special loopback only ports. These are not the same
 365                 * as other ports in loopback mode.
 366                 */
 367        case CVMX_HELPER_INTERFACE_MODE_LOOP:
 368                __cvmx_helper_loop_probe(interface);
 369                break;
 370        }
 371
 372        /* Make sure all global variables propagate to other cores */
 373        CVMX_SYNCWS;
 374
 375        return 0;
 376}
 377
 378/**
 379 * Setup the IPD/PIP for the ports on an interface. Packet
 380 * classification and tagging are set for every port on the
 381 * interface. The number of ports on the interface must already
 382 * have been probed.
 383 *
 384 * @interface: Interface to setup IPD/PIP for
 385 *
 386 * Returns Zero on success, negative on failure
 387 */
 388static int __cvmx_helper_interface_setup_ipd(int interface)
 389{
 390        int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
 391        int num_ports = interface_port_count[interface];
 392
 393        while (num_ports--) {
 394                __cvmx_helper_port_setup_ipd(ipd_port);
 395                ipd_port++;
 396        }
 397        return 0;
 398}
 399
 400/**
 401 * Setup global setting for IPD/PIP not related to a specific
 402 * interface or port. This must be called before IPD is enabled.
 403 *
 404 * Returns Zero on success, negative on failure.
 405 */
 406static int __cvmx_helper_global_setup_ipd(void)
 407{
 408        /* Setup the global packet input options */
 409        cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
 410                        CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
 411                        CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
 412                        /* The +8 is to account for the next ptr */
 413                        (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
 414                        /* The +8 is to account for the next ptr */
 415                        (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
 416                        CVMX_FPA_WQE_POOL,
 417                        CVMX_IPD_OPC_MODE_STT,
 418                        CVMX_HELPER_ENABLE_BACK_PRESSURE);
 419        return 0;
 420}
 421
 422/**
 423 * Setup the PKO for the ports on an interface. The number of
 424 * queues per port and the priority of each PKO output queue
 425 * is set here. PKO must be disabled when this function is called.
 426 *
 427 * @interface: Interface to setup PKO for
 428 *
 429 * Returns Zero on success, negative on failure
 430 */
 431static int __cvmx_helper_interface_setup_pko(int interface)
 432{
 433        /*
 434         * Each packet output queue has an associated priority. The
 435         * higher the priority, the more often it can send a packet. A
 436         * priority of 8 means it can send in all 8 rounds of
 437         * contention. We're going to make each queue one less than
 438         * the last.  The vector of priorities has been extended to
 439         * support CN5xxx CPUs, where up to 16 queues can be
 440         * associated to a port.  To keep backward compatibility we
 441         * don't change the initial 8 priorities and replicate them in
 442         * the second half.  With per-core PKO queues (PKO lockless
 443         * operation) all queues have the same priority.
 444         */
 445        uint64_t priorities[16] =
 446            { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
 447
 448        /*
 449         * Setup the IPD/PIP and PKO for the ports discovered
 450         * above. Here packet classification, tagging and output
 451         * priorities are set.
 452         */
 453        int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
 454        int num_ports = interface_port_count[interface];
 455        while (num_ports--) {
 456                /*
 457                 * Give the user a chance to override the per queue
 458                 * priorities.
 459                 */
 460                if (cvmx_override_pko_queue_priority)
 461                        cvmx_override_pko_queue_priority(ipd_port, priorities);
 462
 463                cvmx_pko_config_port(ipd_port,
 464                                     cvmx_pko_get_base_queue_per_core(ipd_port,
 465                                                                      0),
 466                                     cvmx_pko_get_num_queues(ipd_port),
 467                                     priorities);
 468                ipd_port++;
 469        }
 470        return 0;
 471}
 472
 473/**
 474 * Setup global setting for PKO not related to a specific
 475 * interface or port. This must be called before PKO is enabled.
 476 *
 477 * Returns Zero on success, negative on failure.
 478 */
 479static int __cvmx_helper_global_setup_pko(void)
 480{
 481        /*
 482         * Disable tagwait FAU timeout. This needs to be done before
 483         * anyone might start packet output using tags.
 484         */
 485        union cvmx_iob_fau_timeout fau_to;
 486        fau_to.u64 = 0;
 487        fau_to.s.tout_val = 0xfff;
 488        fau_to.s.tout_enb = 0;
 489        cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
 490        return 0;
 491}
 492
 493/**
 494 * Setup global backpressure setting.
 495 *
 496 * Returns Zero on success, negative on failure
 497 */
 498static int __cvmx_helper_global_setup_backpressure(void)
 499{
 500#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
 501        /* Disable backpressure if configured to do so */
 502        /* Disable backpressure (pause frame) generation */
 503        int num_interfaces = cvmx_helper_get_number_of_interfaces();
 504        int interface;
 505        for (interface = 0; interface < num_interfaces; interface++) {
 506                switch (cvmx_helper_interface_get_mode(interface)) {
 507                case CVMX_HELPER_INTERFACE_MODE_DISABLED:
 508                case CVMX_HELPER_INTERFACE_MODE_PCIE:
 509                case CVMX_HELPER_INTERFACE_MODE_NPI:
 510                case CVMX_HELPER_INTERFACE_MODE_LOOP:
 511                case CVMX_HELPER_INTERFACE_MODE_XAUI:
 512                        break;
 513                case CVMX_HELPER_INTERFACE_MODE_RGMII:
 514                case CVMX_HELPER_INTERFACE_MODE_GMII:
 515                case CVMX_HELPER_INTERFACE_MODE_SPI:
 516                case CVMX_HELPER_INTERFACE_MODE_SGMII:
 517                case CVMX_HELPER_INTERFACE_MODE_PICMG:
 518                        cvmx_gmx_set_backpressure_override(interface, 0xf);
 519                        break;
 520                }
 521        }
 522#endif
 523
 524        return 0;
 525}
 526
 527/**
 528 * Enable packet input/output from the hardware. This function is
 529 * called after all internal setup is complete and IPD is enabled.
 530 * After this function completes, packets will be accepted from the
 531 * hardware ports. PKO should still be disabled to make sure packets
 532 * aren't sent out partially setup hardware.
 533 *
 534 * @interface: Interface to enable
 535 *
 536 * Returns Zero on success, negative on failure
 537 */
 538static int __cvmx_helper_packet_hardware_enable(int interface)
 539{
 540        int result = 0;
 541        switch (cvmx_helper_interface_get_mode(interface)) {
 542                /* These types don't support ports to IPD/PKO */
 543        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
 544        case CVMX_HELPER_INTERFACE_MODE_PCIE:
 545                /* Nothing to do */
 546                break;
 547                /* XAUI is a single high speed port */
 548        case CVMX_HELPER_INTERFACE_MODE_XAUI:
 549                result = __cvmx_helper_xaui_enable(interface);
 550                break;
 551                /*
 552                 * RGMII/GMII/MII are all treated about the same. Most
 553                 * functions refer to these ports as RGMII
 554                 */
 555        case CVMX_HELPER_INTERFACE_MODE_RGMII:
 556        case CVMX_HELPER_INTERFACE_MODE_GMII:
 557                result = __cvmx_helper_rgmii_enable(interface);
 558                break;
 559                /*
 560                 * SPI4 can have 1-16 ports depending on the device at
 561                 * the other end
 562                 */
 563        case CVMX_HELPER_INTERFACE_MODE_SPI:
 564                result = __cvmx_helper_spi_enable(interface);
 565                break;
 566                /*
 567                 * SGMII can have 1-4 ports depending on how many are
 568                 * hooked up
 569                 */
 570        case CVMX_HELPER_INTERFACE_MODE_SGMII:
 571        case CVMX_HELPER_INTERFACE_MODE_PICMG:
 572                result = __cvmx_helper_sgmii_enable(interface);
 573                break;
 574                /* PCI target Network Packet Interface */
 575        case CVMX_HELPER_INTERFACE_MODE_NPI:
 576                result = __cvmx_helper_npi_enable(interface);
 577                break;
 578                /*
 579                 * Special loopback only ports. These are not the same
 580                 * as other ports in loopback mode
 581                 */
 582        case CVMX_HELPER_INTERFACE_MODE_LOOP:
 583                result = __cvmx_helper_loop_enable(interface);
 584                break;
 585        }
 586        result |= __cvmx_helper_board_hardware_enable(interface);
 587        return result;
 588}
 589
 590/**
 591 * Function to adjust internal IPD pointer alignments
 592 *
 593 * Returns 0 on success
 594 *         !0 on failure
 595 */
 596int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
 597{
 598#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
 599     (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
 600#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
 601        (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
 602#define FIX_IPD_OUTPORT 0
 603        /* Ports 0-15 are interface 0, 16-31 are interface 1 */
 604#define INTERFACE(port) (port >> 4)
 605#define INDEX(port) (port & 0xf)
 606        uint64_t *p64;
 607        cvmx_pko_command_word0_t pko_command;
 608        union cvmx_buf_ptr g_buffer, pkt_buffer;
 609        cvmx_wqe_t *work;
 610        int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
 611        union cvmx_gmxx_prtx_cfg gmx_cfg;
 612        int retry_cnt;
 613        int retry_loop_cnt;
 614        int i;
 615        cvmx_helper_link_info_t link_info;
 616
 617        /* Save values for restore at end */
 618        uint64_t prtx_cfg =
 619            cvmx_read_csr(CVMX_GMXX_PRTX_CFG
 620                          (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
 621        uint64_t tx_ptr_en =
 622            cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
 623        uint64_t rx_ptr_en =
 624            cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
 625        uint64_t rxx_jabber =
 626            cvmx_read_csr(CVMX_GMXX_RXX_JABBER
 627                          (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
 628        uint64_t frame_max =
 629            cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
 630                          (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
 631
 632        /* Configure port to gig FDX as required for loopback mode */
 633        cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
 634
 635        /*
 636         * Disable reception on all ports so if traffic is present it
 637         * will not interfere.
 638         */
 639        cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
 640
 641        cvmx_wait(100000000ull);
 642
 643        for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
 644                retry_cnt = 100000;
 645                wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
 646                pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
 647                wqe_pcnt &= 0x7f;
 648
 649                num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
 650
 651                if (num_segs == 0)
 652                        goto fix_ipd_exit;
 653
 654                num_segs += 1;
 655
 656                size =
 657                    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
 658                    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
 659                    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
 660
 661                cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
 662                               1 << INDEX(FIX_IPD_OUTPORT));
 663                CVMX_SYNC;
 664
 665                g_buffer.u64 = 0;
 666                g_buffer.s.addr =
 667                    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
 668                if (g_buffer.s.addr == 0) {
 669                        cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
 670                                     "buffer allocation failure.\n");
 671                        goto fix_ipd_exit;
 672                }
 673
 674                g_buffer.s.pool = CVMX_FPA_WQE_POOL;
 675                g_buffer.s.size = num_segs;
 676
 677                pkt_buffer.u64 = 0;
 678                pkt_buffer.s.addr =
 679                    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
 680                if (pkt_buffer.s.addr == 0) {
 681                        cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
 682                                     "buffer allocation failure.\n");
 683                        goto fix_ipd_exit;
 684                }
 685                pkt_buffer.s.i = 1;
 686                pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
 687                pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
 688
 689                p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
 690                p64[0] = 0xffffffffffff0000ull;
 691                p64[1] = 0x08004510ull;
 692                p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
 693                p64[3] = 0x3a5fc0a81073c0a8ull;
 694
 695                for (i = 0; i < num_segs; i++) {
 696                        if (i > 0)
 697                                pkt_buffer.s.size =
 698                                    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
 699
 700                        if (i == (num_segs - 1))
 701                                pkt_buffer.s.i = 0;
 702
 703                        *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
 704                                                       8 * i) = pkt_buffer.u64;
 705                }
 706
 707                /* Build the PKO command */
 708                pko_command.u64 = 0;
 709                pko_command.s.segs = num_segs;
 710                pko_command.s.total_bytes = size;
 711                pko_command.s.dontfree = 0;
 712                pko_command.s.gather = 1;
 713
 714                gmx_cfg.u64 =
 715                    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
 716                                  (INDEX(FIX_IPD_OUTPORT),
 717                                   INTERFACE(FIX_IPD_OUTPORT)));
 718                gmx_cfg.s.en = 1;
 719                cvmx_write_csr(CVMX_GMXX_PRTX_CFG
 720                               (INDEX(FIX_IPD_OUTPORT),
 721                                INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
 722                cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
 723                               1 << INDEX(FIX_IPD_OUTPORT));
 724                cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
 725                               1 << INDEX(FIX_IPD_OUTPORT));
 726
 727                cvmx_write_csr(CVMX_GMXX_RXX_JABBER
 728                               (INDEX(FIX_IPD_OUTPORT),
 729                                INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
 730                cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
 731                               (INDEX(FIX_IPD_OUTPORT),
 732                                INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
 733
 734                cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
 735                                             cvmx_pko_get_base_queue
 736                                             (FIX_IPD_OUTPORT),
 737                                             CVMX_PKO_LOCK_CMD_QUEUE);
 738                cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
 739                                            cvmx_pko_get_base_queue
 740                                            (FIX_IPD_OUTPORT), pko_command,
 741                                            g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
 742
 743                CVMX_SYNC;
 744
 745                do {
 746                        work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
 747                        retry_cnt--;
 748                } while ((work == NULL) && (retry_cnt > 0));
 749
 750                if (!retry_cnt)
 751                        cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
 752                                     "get_work() timeout occurred.\n");
 753
 754                /* Free packet */
 755                if (work)
 756                        cvmx_helper_free_packet_data(work);
 757        }
 758
 759fix_ipd_exit:
 760
 761        /* Return CSR configs to saved values */
 762        cvmx_write_csr(CVMX_GMXX_PRTX_CFG
 763                       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
 764                       prtx_cfg);
 765        cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
 766                       tx_ptr_en);
 767        cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
 768                       rx_ptr_en);
 769        cvmx_write_csr(CVMX_GMXX_RXX_JABBER
 770                       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
 771                       rxx_jabber);
 772        cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
 773                       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
 774                       frame_max);
 775        cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
 776        /* Set link to down so autonegotiation will set it up again */
 777        link_info.u64 = 0;
 778        cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info);
 779
 780        /*
 781         * Bring the link back up as autonegotiation is not done in
 782         * user applications.
 783         */
 784        cvmx_helper_link_autoconf(FIX_IPD_OUTPORT);
 785
 786        CVMX_SYNC;
 787        if (num_segs)
 788                cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
 789
 790        return !!num_segs;
 791
 792}
 793
 794/**
 795 * Called after all internal packet IO paths are setup. This
 796 * function enables IPD/PIP and begins packet input and output.
 797 *
 798 * Returns Zero on success, negative on failure
 799 */
 800int cvmx_helper_ipd_and_packet_input_enable(void)
 801{
 802        int num_interfaces;
 803        int interface;
 804
 805        /* Enable IPD */
 806        cvmx_ipd_enable();
 807
 808        /*
 809         * Time to enable hardware ports packet input and output. Note
 810         * that at this point IPD/PIP must be fully functional and PKO
 811         * must be disabled
 812         */
 813        num_interfaces = cvmx_helper_get_number_of_interfaces();
 814        for (interface = 0; interface < num_interfaces; interface++) {
 815                if (cvmx_helper_ports_on_interface(interface) > 0)
 816                        __cvmx_helper_packet_hardware_enable(interface);
 817        }
 818
 819        /* Finally enable PKO now that the entire path is up and running */
 820        cvmx_pko_enable();
 821
 822        if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
 823             || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
 824            && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
 825                __cvmx_helper_errata_fix_ipd_ptr_alignment();
 826        return 0;
 827}
 828
 829/**
 830 * Initialize the PIP, IPD, and PKO hardware to support
 831 * simple priority based queues for the ethernet ports. Each
 832 * port is configured with a number of priority queues based
 833 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
 834 * priority than the previous.
 835 *
 836 * Returns Zero on success, non-zero on failure
 837 */
 838int cvmx_helper_initialize_packet_io_global(void)
 839{
 840        int result = 0;
 841        int interface;
 842        union cvmx_l2c_cfg l2c_cfg;
 843        union cvmx_smix_en smix_en;
 844        const int num_interfaces = cvmx_helper_get_number_of_interfaces();
 845
 846        /*
 847         * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
 848         * be disabled.
 849         */
 850        if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
 851                __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
 852
 853        /*
 854         * Tell L2 to give the IOB statically higher priority compared
 855         * to the cores. This avoids conditions where IO blocks might
 856         * be starved under very high L2 loads.
 857         */
 858        l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
 859        l2c_cfg.s.lrf_arb_mode = 0;
 860        l2c_cfg.s.rfb_arb_mode = 0;
 861        cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
 862
 863        /* Make sure SMI/MDIO is enabled so we can query PHYs */
 864        smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
 865        if (!smix_en.s.en) {
 866                smix_en.s.en = 1;
 867                cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
 868        }
 869
 870        /* Newer chips actually have two SMI/MDIO interfaces */
 871        if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
 872            !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
 873            !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
 874                smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
 875                if (!smix_en.s.en) {
 876                        smix_en.s.en = 1;
 877                        cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
 878                }
 879        }
 880
 881        cvmx_pko_initialize_global();
 882        for (interface = 0; interface < num_interfaces; interface++) {
 883                result |= cvmx_helper_interface_probe(interface);
 884                if (cvmx_helper_ports_on_interface(interface) > 0)
 885                        cvmx_dprintf("Interface %d has %d ports (%s)\n",
 886                                     interface,
 887                                     cvmx_helper_ports_on_interface(interface),
 888                                     cvmx_helper_interface_mode_to_string
 889                                     (cvmx_helper_interface_get_mode
 890                                      (interface)));
 891                result |= __cvmx_helper_interface_setup_ipd(interface);
 892                result |= __cvmx_helper_interface_setup_pko(interface);
 893        }
 894
 895        result |= __cvmx_helper_global_setup_ipd();
 896        result |= __cvmx_helper_global_setup_pko();
 897
 898        /* Enable any flow control and backpressure */
 899        result |= __cvmx_helper_global_setup_backpressure();
 900
 901#if CVMX_HELPER_ENABLE_IPD
 902        result |= cvmx_helper_ipd_and_packet_input_enable();
 903#endif
 904        return result;
 905}
 906
 907/**
 908 * Does core local initialization for packet io
 909 *
 910 * Returns Zero on success, non-zero on failure
 911 */
 912int cvmx_helper_initialize_packet_io_local(void)
 913{
 914        return cvmx_pko_initialize_local();
 915}
 916
 917/**
 918 * Auto configure an IPD/PKO port link state and speed. This
 919 * function basically does the equivalent of:
 920 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
 921 *
 922 * @ipd_port: IPD/PKO port to auto configure
 923 *
 924 * Returns Link state after configure
 925 */
 926cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
 927{
 928        cvmx_helper_link_info_t link_info;
 929        int interface = cvmx_helper_get_interface_num(ipd_port);
 930        int index = cvmx_helper_get_interface_index_num(ipd_port);
 931
 932        if (index >= cvmx_helper_ports_on_interface(interface)) {
 933                link_info.u64 = 0;
 934                return link_info;
 935        }
 936
 937        link_info = cvmx_helper_link_get(ipd_port);
 938        if (link_info.u64 == port_link_info[ipd_port].u64)
 939                return link_info;
 940
 941        /* If we fail to set the link speed, port_link_info will not change */
 942        cvmx_helper_link_set(ipd_port, link_info);
 943
 944        /*
 945         * port_link_info should be the current value, which will be
 946         * different than expect if cvmx_helper_link_set() failed.
 947         */
 948        return port_link_info[ipd_port];
 949}
 950
 951/**
 952 * Return the link state of an IPD/PKO port as returned by
 953 * auto negotiation. The result of this function may not match
 954 * Octeon's link config if auto negotiation has changed since
 955 * the last call to cvmx_helper_link_set().
 956 *
 957 * @ipd_port: IPD/PKO port to query
 958 *
 959 * Returns Link state
 960 */
 961cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
 962{
 963        cvmx_helper_link_info_t result;
 964        int interface = cvmx_helper_get_interface_num(ipd_port);
 965        int index = cvmx_helper_get_interface_index_num(ipd_port);
 966
 967        /* The default result will be a down link unless the code below
 968           changes it */
 969        result.u64 = 0;
 970
 971        if (index >= cvmx_helper_ports_on_interface(interface))
 972                return result;
 973
 974        switch (cvmx_helper_interface_get_mode(interface)) {
 975        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
 976        case CVMX_HELPER_INTERFACE_MODE_PCIE:
 977                /* Network links are not supported */
 978                break;
 979        case CVMX_HELPER_INTERFACE_MODE_XAUI:
 980                result = __cvmx_helper_xaui_link_get(ipd_port);
 981                break;
 982        case CVMX_HELPER_INTERFACE_MODE_GMII:
 983                if (index == 0)
 984                        result = __cvmx_helper_rgmii_link_get(ipd_port);
 985                else {
 986                        result.s.full_duplex = 1;
 987                        result.s.link_up = 1;
 988                        result.s.speed = 1000;
 989                }
 990                break;
 991        case CVMX_HELPER_INTERFACE_MODE_RGMII:
 992                result = __cvmx_helper_rgmii_link_get(ipd_port);
 993                break;
 994        case CVMX_HELPER_INTERFACE_MODE_SPI:
 995                result = __cvmx_helper_spi_link_get(ipd_port);
 996                break;
 997        case CVMX_HELPER_INTERFACE_MODE_SGMII:
 998        case CVMX_HELPER_INTERFACE_MODE_PICMG:
 999                result = __cvmx_helper_sgmii_link_get(ipd_port);
1000                break;
1001        case CVMX_HELPER_INTERFACE_MODE_NPI:
1002        case CVMX_HELPER_INTERFACE_MODE_LOOP:
1003                /* Network links are not supported */
1004                break;
1005        }
1006        return result;
1007}
1008
1009/**
1010 * Configure an IPD/PKO port for the specified link state. This
1011 * function does not influence auto negotiation at the PHY level.
1012 * The passed link state must always match the link state returned
1013 * by cvmx_helper_link_get(). It is normally best to use
1014 * cvmx_helper_link_autoconf() instead.
1015 *
1016 * @ipd_port:  IPD/PKO port to configure
1017 * @link_info: The new link state
1018 *
1019 * Returns Zero on success, negative on failure
1020 */
1021int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1022{
1023        int result = -1;
1024        int interface = cvmx_helper_get_interface_num(ipd_port);
1025        int index = cvmx_helper_get_interface_index_num(ipd_port);
1026
1027        if (index >= cvmx_helper_ports_on_interface(interface))
1028                return -1;
1029
1030        switch (cvmx_helper_interface_get_mode(interface)) {
1031        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1032        case CVMX_HELPER_INTERFACE_MODE_PCIE:
1033                break;
1034        case CVMX_HELPER_INTERFACE_MODE_XAUI:
1035                result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1036                break;
1037                /*
1038                 * RGMII/GMII/MII are all treated about the same. Most
1039                 * functions refer to these ports as RGMII.
1040                 */
1041        case CVMX_HELPER_INTERFACE_MODE_RGMII:
1042        case CVMX_HELPER_INTERFACE_MODE_GMII:
1043                result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1044                break;
1045        case CVMX_HELPER_INTERFACE_MODE_SPI:
1046                result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1047                break;
1048        case CVMX_HELPER_INTERFACE_MODE_SGMII:
1049        case CVMX_HELPER_INTERFACE_MODE_PICMG:
1050                result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1051                break;
1052        case CVMX_HELPER_INTERFACE_MODE_NPI:
1053        case CVMX_HELPER_INTERFACE_MODE_LOOP:
1054                break;
1055        }
1056        /* Set the port_link_info here so that the link status is updated
1057           no matter how cvmx_helper_link_set is called. We don't change
1058           the value if link_set failed */
1059        if (result == 0)
1060                port_link_info[ipd_port].u64 = link_info.u64;
1061        return result;
1062}
1063
1064/**
1065 * Configure a port for internal and/or external loopback. Internal loopback
1066 * causes packets sent by the port to be received by Octeon. External loopback
1067 * causes packets received from the wire to sent out again.
1068 *
1069 * @ipd_port: IPD/PKO port to loopback.
1070 * @enable_internal:
1071 *                 Non zero if you want internal loopback
1072 * @enable_external:
1073 *                 Non zero if you want external loopback
1074 *
1075 * Returns Zero on success, negative on failure.
1076 */
1077int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1078                                   int enable_external)
1079{
1080        int result = -1;
1081        int interface = cvmx_helper_get_interface_num(ipd_port);
1082        int index = cvmx_helper_get_interface_index_num(ipd_port);
1083
1084        if (index >= cvmx_helper_ports_on_interface(interface))
1085                return -1;
1086
1087        switch (cvmx_helper_interface_get_mode(interface)) {
1088        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1089        case CVMX_HELPER_INTERFACE_MODE_PCIE:
1090        case CVMX_HELPER_INTERFACE_MODE_SPI:
1091        case CVMX_HELPER_INTERFACE_MODE_NPI:
1092        case CVMX_HELPER_INTERFACE_MODE_LOOP:
1093                break;
1094        case CVMX_HELPER_INTERFACE_MODE_XAUI:
1095                result =
1096                    __cvmx_helper_xaui_configure_loopback(ipd_port,
1097                                                          enable_internal,
1098                                                          enable_external);
1099                break;
1100        case CVMX_HELPER_INTERFACE_MODE_RGMII:
1101        case CVMX_HELPER_INTERFACE_MODE_GMII:
1102                result =
1103                    __cvmx_helper_rgmii_configure_loopback(ipd_port,
1104                                                           enable_internal,
1105                                                           enable_external);
1106                break;
1107        case CVMX_HELPER_INTERFACE_MODE_SGMII:
1108        case CVMX_HELPER_INTERFACE_MODE_PICMG:
1109                result =
1110                    __cvmx_helper_sgmii_configure_loopback(ipd_port,
1111                                                           enable_internal,
1112                                                           enable_external);
1113                break;
1114        }
1115        return result;
1116}
1117