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