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