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