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