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