Back to home page

OSCL-LXR

 
 

    


0001 /***********************license start***************
0002  * Author: Cavium Networks
0003  *
0004  * Contact: support@caviumnetworks.com
0005  * This file is part of the OCTEON SDK
0006  *
0007  * Copyright (c) 2003-2008 Cavium Networks
0008  *
0009  * This file is free software; you can redistribute it and/or modify
0010  * it under the terms of the GNU General Public License, Version 2, as
0011  * published by the Free Software Foundation.
0012  *
0013  * This file is distributed in the hope that it will be useful, but
0014  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
0015  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
0016  * NONINFRINGEMENT.  See the GNU General Public License for more
0017  * details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this file; if not, write to the Free Software
0021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
0022  * or visit http://www.gnu.org/licenses/.
0023  *
0024  * This file may also be available under a different license from Cavium.
0025  * Contact Cavium Networks for more information
0026  ***********************license end**************************************/
0027 
0028 /*
0029  *
0030  * Helper functions for common, but complicated tasks.
0031  *
0032  */
0033 #include <linux/bug.h>
0034 #include <asm/octeon/octeon.h>
0035 
0036 #include <asm/octeon/cvmx-config.h>
0037 
0038 #include <asm/octeon/cvmx-fpa.h>
0039 #include <asm/octeon/cvmx-pip.h>
0040 #include <asm/octeon/cvmx-pko.h>
0041 #include <asm/octeon/cvmx-ipd.h>
0042 #include <asm/octeon/cvmx-spi.h>
0043 #include <asm/octeon/cvmx-helper.h>
0044 #include <asm/octeon/cvmx-helper-board.h>
0045 
0046 #include <asm/octeon/cvmx-pip-defs.h>
0047 #include <asm/octeon/cvmx-asxx-defs.h>
0048 
0049 /* Port count per interface */
0050 static int interface_port_count[9];
0051 
0052 /**
0053  * Return the number of interfaces the chip has. Each interface
0054  * may have multiple ports. Most chips support two interfaces,
0055  * but the CNX0XX and CNX1XX are exceptions. These only support
0056  * one interface.
0057  *
0058  * Returns Number of interfaces on chip
0059  */
0060 int cvmx_helper_get_number_of_interfaces(void)
0061 {
0062     if (OCTEON_IS_MODEL(OCTEON_CN68XX))
0063         return 9;
0064     if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
0065         if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
0066             return 7;
0067         else
0068             return 8;
0069     }
0070     if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
0071         return 4;
0072     if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
0073         return 5;
0074     else
0075         return 3;
0076 }
0077 EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
0078 
0079 /**
0080  * Return the number of ports on an interface. Depending on the
0081  * chip and configuration, this can be 1-16. A value of 0
0082  * specifies that the interface doesn't exist or isn't usable.
0083  *
0084  * @interface: Interface to get the port count for
0085  *
0086  * Returns Number of ports on interface. Can be Zero.
0087  */
0088 int cvmx_helper_ports_on_interface(int interface)
0089 {
0090     return interface_port_count[interface];
0091 }
0092 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
0093 
0094 /**
0095  * @INTERNAL
0096  * Return interface mode for CN68xx.
0097  */
0098 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
0099 {
0100     union cvmx_mio_qlmx_cfg qlm_cfg;
0101     switch (interface) {
0102     case 0:
0103         qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
0104         /* QLM is disabled when QLM SPD is 15. */
0105         if (qlm_cfg.s.qlm_spd == 15)
0106             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0107 
0108         if (qlm_cfg.s.qlm_cfg == 2)
0109             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0110         else if (qlm_cfg.s.qlm_cfg == 3)
0111             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0112         else
0113             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0114     case 2:
0115     case 3:
0116     case 4:
0117         qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
0118         /* QLM is disabled when QLM SPD is 15. */
0119         if (qlm_cfg.s.qlm_spd == 15)
0120             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0121 
0122         if (qlm_cfg.s.qlm_cfg == 2)
0123             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0124         else if (qlm_cfg.s.qlm_cfg == 3)
0125             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0126         else
0127             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0128     case 7:
0129         qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
0130         /* QLM is disabled when QLM SPD is 15. */
0131         if (qlm_cfg.s.qlm_spd == 15) {
0132             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0133         } else if (qlm_cfg.s.qlm_cfg != 0) {
0134             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
0135             if (qlm_cfg.s.qlm_cfg != 0)
0136                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0137         }
0138         return CVMX_HELPER_INTERFACE_MODE_NPI;
0139     case 8:
0140         return CVMX_HELPER_INTERFACE_MODE_LOOP;
0141     default:
0142         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0143     }
0144 }
0145 
0146 /**
0147  * @INTERNAL
0148  * Return interface mode for an Octeon II
0149  */
0150 static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
0151 {
0152     union cvmx_gmxx_inf_mode mode;
0153 
0154     if (OCTEON_IS_MODEL(OCTEON_CN68XX))
0155         return __cvmx_get_mode_cn68xx(interface);
0156 
0157     if (interface == 2)
0158         return CVMX_HELPER_INTERFACE_MODE_NPI;
0159 
0160     if (interface == 3)
0161         return CVMX_HELPER_INTERFACE_MODE_LOOP;
0162 
0163     /* Only present in CN63XX & CN66XX Octeon model */
0164     if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
0165          (interface == 4 || interface == 5)) ||
0166         (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
0167          interface >= 4 && interface <= 7)) {
0168         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0169     }
0170 
0171     if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
0172         union cvmx_mio_qlmx_cfg mio_qlm_cfg;
0173 
0174         /* QLM2 is SGMII0 and QLM1 is SGMII1 */
0175         if (interface == 0)
0176             mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
0177         else if (interface == 1)
0178             mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
0179         else
0180             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0181 
0182         if (mio_qlm_cfg.s.qlm_spd == 15)
0183             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0184 
0185         if (mio_qlm_cfg.s.qlm_cfg == 9)
0186             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0187         else if (mio_qlm_cfg.s.qlm_cfg == 11)
0188             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0189         else
0190             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0191     } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
0192         union cvmx_mio_qlmx_cfg qlm_cfg;
0193 
0194         if (interface == 0) {
0195             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
0196             if (qlm_cfg.s.qlm_cfg == 2)
0197                 return CVMX_HELPER_INTERFACE_MODE_SGMII;
0198             else if (qlm_cfg.s.qlm_cfg == 3)
0199                 return CVMX_HELPER_INTERFACE_MODE_XAUI;
0200             else
0201                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0202         } else if (interface == 1) {
0203             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
0204             if (qlm_cfg.s.qlm_cfg == 2)
0205                 return CVMX_HELPER_INTERFACE_MODE_SGMII;
0206             else if (qlm_cfg.s.qlm_cfg == 3)
0207                 return CVMX_HELPER_INTERFACE_MODE_XAUI;
0208             else
0209                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0210         }
0211     } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
0212         if (interface == 0) {
0213             union cvmx_mio_qlmx_cfg qlm_cfg;
0214             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
0215             if (qlm_cfg.s.qlm_cfg == 2)
0216                 return CVMX_HELPER_INTERFACE_MODE_SGMII;
0217         }
0218         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0219     }
0220 
0221     if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
0222         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0223 
0224     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
0225 
0226     if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
0227         switch (mode.cn61xx.mode) {
0228         case 0:
0229             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0230         case 1:
0231             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0232         default:
0233             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0234         }
0235     } else {
0236         if (!mode.s.en)
0237             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0238 
0239         if (mode.s.type)
0240             return CVMX_HELPER_INTERFACE_MODE_GMII;
0241         else
0242             return CVMX_HELPER_INTERFACE_MODE_RGMII;
0243     }
0244 }
0245 
0246 /**
0247  * @INTERNAL
0248  * Return interface mode for CN7XXX.
0249  */
0250 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
0251 {
0252     union cvmx_gmxx_inf_mode mode;
0253 
0254     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
0255 
0256     switch (interface) {
0257     case 0:
0258     case 1:
0259         switch (mode.cn68xx.mode) {
0260         case 0:
0261             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0262         case 1:
0263         case 2:
0264             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0265         case 3:
0266             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0267         default:
0268             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0269         }
0270     case 2:
0271         return CVMX_HELPER_INTERFACE_MODE_NPI;
0272     case 3:
0273         return CVMX_HELPER_INTERFACE_MODE_LOOP;
0274     case 4:
0275         /* TODO: Implement support for AGL (RGMII). */
0276         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0277     default:
0278         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0279     }
0280 }
0281 
0282 /**
0283  * Get the operating mode of an interface. Depending on the Octeon
0284  * chip and configuration, this function returns an enumeration
0285  * of the type of packet I/O supported by an interface.
0286  *
0287  * @interface: Interface to probe
0288  *
0289  * Returns Mode of the interface. Unknown or unsupported interfaces return
0290  *     DISABLED.
0291  */
0292 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
0293 {
0294     union cvmx_gmxx_inf_mode mode;
0295 
0296     if (interface < 0 ||
0297         interface >= cvmx_helper_get_number_of_interfaces())
0298         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0299 
0300     /*
0301      * OCTEON III models
0302      */
0303     if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
0304         return __cvmx_get_mode_cn7xxx(interface);
0305 
0306     /*
0307      * Octeon II models
0308      */
0309     if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
0310         return __cvmx_get_mode_octeon2(interface);
0311 
0312     /*
0313      * Octeon and Octeon Plus models
0314      */
0315     if (interface == 2)
0316         return CVMX_HELPER_INTERFACE_MODE_NPI;
0317 
0318     if (interface == 3) {
0319         if (OCTEON_IS_MODEL(OCTEON_CN56XX)
0320             || OCTEON_IS_MODEL(OCTEON_CN52XX))
0321             return CVMX_HELPER_INTERFACE_MODE_LOOP;
0322         else
0323             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0324     }
0325 
0326     /* Interface 1 is always disabled on CN31XX and CN30XX */
0327     if ((interface == 1)
0328         && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
0329         || OCTEON_IS_MODEL(OCTEON_CN50XX)
0330         || OCTEON_IS_MODEL(OCTEON_CN52XX)))
0331         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0332 
0333     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
0334 
0335     if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
0336         switch (mode.cn52xx.mode) {
0337         case 0:
0338             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0339         case 1:
0340             return CVMX_HELPER_INTERFACE_MODE_XAUI;
0341         case 2:
0342             return CVMX_HELPER_INTERFACE_MODE_SGMII;
0343         case 3:
0344             return CVMX_HELPER_INTERFACE_MODE_PICMG;
0345         default:
0346             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0347         }
0348     } else {
0349         if (!mode.s.en)
0350             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
0351 
0352         if (mode.s.type) {
0353             if (OCTEON_IS_MODEL(OCTEON_CN38XX)
0354                 || OCTEON_IS_MODEL(OCTEON_CN58XX))
0355                 return CVMX_HELPER_INTERFACE_MODE_SPI;
0356             else
0357                 return CVMX_HELPER_INTERFACE_MODE_GMII;
0358         } else
0359             return CVMX_HELPER_INTERFACE_MODE_RGMII;
0360     }
0361 }
0362 EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
0363 
0364 /**
0365  * Configure the IPD/PIP tagging and QoS options for a specific
0366  * port. This function determines the POW work queue entry
0367  * contents for a port. The setup performed here is controlled by
0368  * the defines in executive-config.h.
0369  *
0370  * @ipd_port: Port to configure. This follows the IPD numbering, not the
0371  *         per interface numbering
0372  *
0373  * Returns Zero on success, negative on failure
0374  */
0375 static int __cvmx_helper_port_setup_ipd(int ipd_port)
0376 {
0377     union cvmx_pip_prt_cfgx port_config;
0378     union cvmx_pip_prt_tagx tag_config;
0379 
0380     port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
0381     tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
0382 
0383     /* Have each port go to a different POW queue */
0384     port_config.s.qos = ipd_port & 0x7;
0385 
0386     /* Process the headers and place the IP header in the work queue */
0387     port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
0388 
0389     tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
0390     tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
0391     tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
0392     tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
0393     tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
0394     tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
0395     tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
0396     tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
0397     tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
0398     tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
0399     tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
0400     tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
0401     tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
0402     tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
0403     tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
0404     tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
0405     /* Put all packets in group 0. Other groups can be used by the app */
0406     tag_config.s.grp = 0;
0407 
0408     cvmx_pip_config_port(ipd_port, port_config, tag_config);
0409 
0410     return 0;
0411 }
0412 
0413 /**
0414  * This function sets the interface_port_count[interface] correctly,
0415  * without modifying any hardware configuration.  Hardware setup of
0416  * the ports will be performed later.
0417  *
0418  * @interface: Interface to probe
0419  *
0420  * Returns Zero on success, negative on failure
0421  */
0422 int cvmx_helper_interface_enumerate(int interface)
0423 {
0424     switch (cvmx_helper_interface_get_mode(interface)) {
0425         /* These types don't support ports to IPD/PKO */
0426     case CVMX_HELPER_INTERFACE_MODE_DISABLED:
0427     case CVMX_HELPER_INTERFACE_MODE_PCIE:
0428         interface_port_count[interface] = 0;
0429         break;
0430         /* XAUI is a single high speed port */
0431     case CVMX_HELPER_INTERFACE_MODE_XAUI:
0432         interface_port_count[interface] =
0433             __cvmx_helper_xaui_enumerate(interface);
0434         break;
0435         /*
0436          * RGMII/GMII/MII are all treated about the same. Most
0437          * functions refer to these ports as RGMII.
0438          */
0439     case CVMX_HELPER_INTERFACE_MODE_RGMII:
0440     case CVMX_HELPER_INTERFACE_MODE_GMII:
0441         interface_port_count[interface] =
0442             __cvmx_helper_rgmii_enumerate(interface);
0443         break;
0444         /*
0445          * SPI4 can have 1-16 ports depending on the device at
0446          * the other end.
0447          */
0448     case CVMX_HELPER_INTERFACE_MODE_SPI:
0449         interface_port_count[interface] =
0450             __cvmx_helper_spi_enumerate(interface);
0451         break;
0452         /*
0453          * SGMII can have 1-4 ports depending on how many are
0454          * hooked up.
0455          */
0456     case CVMX_HELPER_INTERFACE_MODE_SGMII:
0457     case CVMX_HELPER_INTERFACE_MODE_PICMG:
0458         interface_port_count[interface] =
0459             __cvmx_helper_sgmii_enumerate(interface);
0460         break;
0461         /* PCI target Network Packet Interface */
0462     case CVMX_HELPER_INTERFACE_MODE_NPI:
0463         interface_port_count[interface] =
0464             __cvmx_helper_npi_enumerate(interface);
0465         break;
0466         /*
0467          * Special loopback only ports. These are not the same
0468          * as other ports in loopback mode.
0469          */
0470     case CVMX_HELPER_INTERFACE_MODE_LOOP:
0471         interface_port_count[interface] =
0472             __cvmx_helper_loop_enumerate(interface);
0473         break;
0474     }
0475 
0476     interface_port_count[interface] =
0477         __cvmx_helper_board_interface_probe(interface,
0478                         interface_port_count
0479                         [interface]);
0480 
0481     /* Make sure all global variables propagate to other cores */
0482     CVMX_SYNCWS;
0483 
0484     return 0;
0485 }
0486 
0487 /**
0488  * This function probes an interface to determine the actual
0489  * number of hardware ports connected to it. It doesn't setup the
0490  * ports or enable them. The main goal here is to set the global
0491  * interface_port_count[interface] correctly. Hardware setup of the
0492  * ports will be performed later.
0493  *
0494  * @interface: Interface to probe
0495  *
0496  * Returns Zero on success, negative on failure
0497  */
0498 int cvmx_helper_interface_probe(int interface)
0499 {
0500     cvmx_helper_interface_enumerate(interface);
0501     /* At this stage in the game we don't want packets to be moving yet.
0502        The following probe calls should perform hardware setup
0503        needed to determine port counts. Receive must still be disabled */
0504     switch (cvmx_helper_interface_get_mode(interface)) {
0505         /* These types don't support ports to IPD/PKO */
0506     case CVMX_HELPER_INTERFACE_MODE_DISABLED:
0507     case CVMX_HELPER_INTERFACE_MODE_PCIE:
0508         break;
0509         /* XAUI is a single high speed port */
0510     case CVMX_HELPER_INTERFACE_MODE_XAUI:
0511         __cvmx_helper_xaui_probe(interface);
0512         break;
0513         /*
0514          * RGMII/GMII/MII are all treated about the same. Most
0515          * functions refer to these ports as RGMII.
0516          */
0517     case CVMX_HELPER_INTERFACE_MODE_RGMII:
0518     case CVMX_HELPER_INTERFACE_MODE_GMII:
0519         __cvmx_helper_rgmii_probe(interface);
0520         break;
0521         /*
0522          * SPI4 can have 1-16 ports depending on the device at
0523          * the other end.
0524          */
0525     case CVMX_HELPER_INTERFACE_MODE_SPI:
0526         __cvmx_helper_spi_probe(interface);
0527         break;
0528         /*
0529          * SGMII can have 1-4 ports depending on how many are
0530          * hooked up.
0531          */
0532     case CVMX_HELPER_INTERFACE_MODE_SGMII:
0533     case CVMX_HELPER_INTERFACE_MODE_PICMG:
0534         __cvmx_helper_sgmii_probe(interface);
0535         break;
0536         /* PCI target Network Packet Interface */
0537     case CVMX_HELPER_INTERFACE_MODE_NPI:
0538         __cvmx_helper_npi_probe(interface);
0539         break;
0540         /*
0541          * Special loopback only ports. These are not the same
0542          * as other ports in loopback mode.
0543          */
0544     case CVMX_HELPER_INTERFACE_MODE_LOOP:
0545         __cvmx_helper_loop_probe(interface);
0546         break;
0547     }
0548 
0549     /* Make sure all global variables propagate to other cores */
0550     CVMX_SYNCWS;
0551 
0552     return 0;
0553 }
0554 
0555 /**
0556  * Setup the IPD/PIP for the ports on an interface. Packet
0557  * classification and tagging are set for every port on the
0558  * interface. The number of ports on the interface must already
0559  * have been probed.
0560  *
0561  * @interface: Interface to setup IPD/PIP for
0562  *
0563  * Returns Zero on success, negative on failure
0564  */
0565 static int __cvmx_helper_interface_setup_ipd(int interface)
0566 {
0567     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
0568     int num_ports = interface_port_count[interface];
0569 
0570     while (num_ports--) {
0571         __cvmx_helper_port_setup_ipd(ipd_port);
0572         ipd_port++;
0573     }
0574     return 0;
0575 }
0576 
0577 /**
0578  * Setup global setting for IPD/PIP not related to a specific
0579  * interface or port. This must be called before IPD is enabled.
0580  *
0581  * Returns Zero on success, negative on failure.
0582  */
0583 static int __cvmx_helper_global_setup_ipd(void)
0584 {
0585     /* Setup the global packet input options */
0586     cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
0587             CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
0588             CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
0589             /* The +8 is to account for the next ptr */
0590             (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
0591             /* The +8 is to account for the next ptr */
0592             (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
0593             CVMX_FPA_WQE_POOL,
0594             CVMX_IPD_OPC_MODE_STT,
0595             CVMX_HELPER_ENABLE_BACK_PRESSURE);
0596     return 0;
0597 }
0598 
0599 /**
0600  * Setup the PKO for the ports on an interface. The number of
0601  * queues per port and the priority of each PKO output queue
0602  * is set here. PKO must be disabled when this function is called.
0603  *
0604  * @interface: Interface to setup PKO for
0605  *
0606  * Returns Zero on success, negative on failure
0607  */
0608 static int __cvmx_helper_interface_setup_pko(int interface)
0609 {
0610     /*
0611      * Each packet output queue has an associated priority. The
0612      * higher the priority, the more often it can send a packet. A
0613      * priority of 8 means it can send in all 8 rounds of
0614      * contention. We're going to make each queue one less than
0615      * the last.  The vector of priorities has been extended to
0616      * support CN5xxx CPUs, where up to 16 queues can be
0617      * associated to a port.  To keep backward compatibility we
0618      * don't change the initial 8 priorities and replicate them in
0619      * the second half.  With per-core PKO queues (PKO lockless
0620      * operation) all queues have the same priority.
0621      */
0622     uint64_t priorities[16] =
0623         { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
0624 
0625     /*
0626      * Setup the IPD/PIP and PKO for the ports discovered
0627      * above. Here packet classification, tagging and output
0628      * priorities are set.
0629      */
0630     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
0631     int num_ports = interface_port_count[interface];
0632     while (num_ports--) {
0633         cvmx_pko_config_port(ipd_port,
0634                      cvmx_pko_get_base_queue_per_core(ipd_port,
0635                                       0),
0636                      cvmx_pko_get_num_queues(ipd_port),
0637                      priorities);
0638         ipd_port++;
0639     }
0640     return 0;
0641 }
0642 
0643 /**
0644  * Setup global setting for PKO not related to a specific
0645  * interface or port. This must be called before PKO is enabled.
0646  *
0647  * Returns Zero on success, negative on failure.
0648  */
0649 static int __cvmx_helper_global_setup_pko(void)
0650 {
0651     /*
0652      * Disable tagwait FAU timeout. This needs to be done before
0653      * anyone might start packet output using tags.
0654      */
0655     union cvmx_iob_fau_timeout fau_to;
0656     fau_to.u64 = 0;
0657     fau_to.s.tout_val = 0xfff;
0658     fau_to.s.tout_enb = 0;
0659     cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
0660 
0661     if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
0662         union cvmx_pko_reg_min_pkt min_pkt;
0663 
0664         min_pkt.u64 = 0;
0665         min_pkt.s.size1 = 59;
0666         min_pkt.s.size2 = 59;
0667         min_pkt.s.size3 = 59;
0668         min_pkt.s.size4 = 59;
0669         min_pkt.s.size5 = 59;
0670         min_pkt.s.size6 = 59;
0671         min_pkt.s.size7 = 59;
0672         cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
0673     }
0674 
0675     return 0;
0676 }
0677 
0678 /**
0679  * Setup global backpressure setting.
0680  *
0681  * Returns Zero on success, negative on failure
0682  */
0683 static int __cvmx_helper_global_setup_backpressure(void)
0684 {
0685 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
0686     /* Disable backpressure if configured to do so */
0687     /* Disable backpressure (pause frame) generation */
0688     int num_interfaces = cvmx_helper_get_number_of_interfaces();
0689     int interface;
0690     for (interface = 0; interface < num_interfaces; interface++) {
0691         switch (cvmx_helper_interface_get_mode(interface)) {
0692         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
0693         case CVMX_HELPER_INTERFACE_MODE_PCIE:
0694         case CVMX_HELPER_INTERFACE_MODE_NPI:
0695         case CVMX_HELPER_INTERFACE_MODE_LOOP:
0696         case CVMX_HELPER_INTERFACE_MODE_XAUI:
0697             break;
0698         case CVMX_HELPER_INTERFACE_MODE_RGMII:
0699         case CVMX_HELPER_INTERFACE_MODE_GMII:
0700         case CVMX_HELPER_INTERFACE_MODE_SPI:
0701         case CVMX_HELPER_INTERFACE_MODE_SGMII:
0702         case CVMX_HELPER_INTERFACE_MODE_PICMG:
0703             cvmx_gmx_set_backpressure_override(interface, 0xf);
0704             break;
0705         }
0706     }
0707 #endif
0708 
0709     return 0;
0710 }
0711 
0712 /**
0713  * Enable packet input/output from the hardware. This function is
0714  * called after all internal setup is complete and IPD is enabled.
0715  * After this function completes, packets will be accepted from the
0716  * hardware ports. PKO should still be disabled to make sure packets
0717  * aren't sent out partially setup hardware.
0718  *
0719  * @interface: Interface to enable
0720  *
0721  * Returns Zero on success, negative on failure
0722  */
0723 static int __cvmx_helper_packet_hardware_enable(int interface)
0724 {
0725     int result = 0;
0726     switch (cvmx_helper_interface_get_mode(interface)) {
0727         /* These types don't support ports to IPD/PKO */
0728     case CVMX_HELPER_INTERFACE_MODE_DISABLED:
0729     case CVMX_HELPER_INTERFACE_MODE_PCIE:
0730         /* Nothing to do */
0731         break;
0732         /* XAUI is a single high speed port */
0733     case CVMX_HELPER_INTERFACE_MODE_XAUI:
0734         result = __cvmx_helper_xaui_enable(interface);
0735         break;
0736         /*
0737          * RGMII/GMII/MII are all treated about the same. Most
0738          * functions refer to these ports as RGMII
0739          */
0740     case CVMX_HELPER_INTERFACE_MODE_RGMII:
0741     case CVMX_HELPER_INTERFACE_MODE_GMII:
0742         result = __cvmx_helper_rgmii_enable(interface);
0743         break;
0744         /*
0745          * SPI4 can have 1-16 ports depending on the device at
0746          * the other end
0747          */
0748     case CVMX_HELPER_INTERFACE_MODE_SPI:
0749         result = __cvmx_helper_spi_enable(interface);
0750         break;
0751         /*
0752          * SGMII can have 1-4 ports depending on how many are
0753          * hooked up
0754          */
0755     case CVMX_HELPER_INTERFACE_MODE_SGMII:
0756     case CVMX_HELPER_INTERFACE_MODE_PICMG:
0757         result = __cvmx_helper_sgmii_enable(interface);
0758         break;
0759         /* PCI target Network Packet Interface */
0760     case CVMX_HELPER_INTERFACE_MODE_NPI:
0761         result = __cvmx_helper_npi_enable(interface);
0762         break;
0763         /*
0764          * Special loopback only ports. These are not the same
0765          * as other ports in loopback mode
0766          */
0767     case CVMX_HELPER_INTERFACE_MODE_LOOP:
0768         result = __cvmx_helper_loop_enable(interface);
0769         break;
0770     }
0771     return result;
0772 }
0773 
0774 /**
0775  * Function to adjust internal IPD pointer alignments
0776  *
0777  * Returns 0 on success
0778  *     !0 on failure
0779  */
0780 static int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
0781 {
0782 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
0783      (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
0784 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
0785     (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
0786 #define FIX_IPD_OUTPORT 0
0787     /* Ports 0-15 are interface 0, 16-31 are interface 1 */
0788 #define INTERFACE(port) (port >> 4)
0789 #define INDEX(port) (port & 0xf)
0790     uint64_t *p64;
0791     union cvmx_pko_command_word0 pko_command;
0792     union cvmx_buf_ptr g_buffer, pkt_buffer;
0793     struct cvmx_wqe *work;
0794     int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
0795     union cvmx_gmxx_prtx_cfg gmx_cfg;
0796     int retry_cnt;
0797     int retry_loop_cnt;
0798     int i;
0799 
0800     /* Save values for restore at end */
0801     uint64_t prtx_cfg =
0802         cvmx_read_csr(CVMX_GMXX_PRTX_CFG
0803               (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
0804     uint64_t tx_ptr_en =
0805         cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
0806     uint64_t rx_ptr_en =
0807         cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
0808     uint64_t rxx_jabber =
0809         cvmx_read_csr(CVMX_GMXX_RXX_JABBER
0810               (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
0811     uint64_t frame_max =
0812         cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
0813               (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
0814 
0815     /* Configure port to gig FDX as required for loopback mode */
0816     cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
0817 
0818     /*
0819      * Disable reception on all ports so if traffic is present it
0820      * will not interfere.
0821      */
0822     cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
0823 
0824     __delay(100000000ull);
0825 
0826     for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
0827         retry_cnt = 100000;
0828         wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
0829         pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
0830         wqe_pcnt &= 0x7f;
0831 
0832         num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
0833 
0834         if (num_segs == 0)
0835             goto fix_ipd_exit;
0836 
0837         num_segs += 1;
0838 
0839         size =
0840             FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
0841             ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
0842             (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
0843 
0844         cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
0845                    1 << INDEX(FIX_IPD_OUTPORT));
0846         CVMX_SYNC;
0847 
0848         g_buffer.u64 = 0;
0849         g_buffer.s.addr =
0850             cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
0851         if (g_buffer.s.addr == 0) {
0852             cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
0853                      "buffer allocation failure.\n");
0854             goto fix_ipd_exit;
0855         }
0856 
0857         g_buffer.s.pool = CVMX_FPA_WQE_POOL;
0858         g_buffer.s.size = num_segs;
0859 
0860         pkt_buffer.u64 = 0;
0861         pkt_buffer.s.addr =
0862             cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
0863         if (pkt_buffer.s.addr == 0) {
0864             cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
0865                      "buffer allocation failure.\n");
0866             goto fix_ipd_exit;
0867         }
0868         pkt_buffer.s.i = 1;
0869         pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
0870         pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
0871 
0872         p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
0873         p64[0] = 0xffffffffffff0000ull;
0874         p64[1] = 0x08004510ull;
0875         p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
0876         p64[3] = 0x3a5fc0a81073c0a8ull;
0877 
0878         for (i = 0; i < num_segs; i++) {
0879             if (i > 0)
0880                 pkt_buffer.s.size =
0881                     FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
0882 
0883             if (i == (num_segs - 1))
0884                 pkt_buffer.s.i = 0;
0885 
0886             *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
0887                                8 * i) = pkt_buffer.u64;
0888         }
0889 
0890         /* Build the PKO command */
0891         pko_command.u64 = 0;
0892         pko_command.s.segs = num_segs;
0893         pko_command.s.total_bytes = size;
0894         pko_command.s.dontfree = 0;
0895         pko_command.s.gather = 1;
0896 
0897         gmx_cfg.u64 =
0898             cvmx_read_csr(CVMX_GMXX_PRTX_CFG
0899                   (INDEX(FIX_IPD_OUTPORT),
0900                    INTERFACE(FIX_IPD_OUTPORT)));
0901         gmx_cfg.s.en = 1;
0902         cvmx_write_csr(CVMX_GMXX_PRTX_CFG
0903                    (INDEX(FIX_IPD_OUTPORT),
0904                 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
0905         cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
0906                    1 << INDEX(FIX_IPD_OUTPORT));
0907         cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
0908                    1 << INDEX(FIX_IPD_OUTPORT));
0909 
0910         cvmx_write_csr(CVMX_GMXX_RXX_JABBER
0911                    (INDEX(FIX_IPD_OUTPORT),
0912                 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
0913         cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
0914                    (INDEX(FIX_IPD_OUTPORT),
0915                 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
0916 
0917         cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
0918                          cvmx_pko_get_base_queue
0919                          (FIX_IPD_OUTPORT),
0920                          CVMX_PKO_LOCK_CMD_QUEUE);
0921         cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
0922                         cvmx_pko_get_base_queue
0923                         (FIX_IPD_OUTPORT), pko_command,
0924                         g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
0925 
0926         CVMX_SYNC;
0927 
0928         do {
0929             work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
0930             retry_cnt--;
0931         } while ((work == NULL) && (retry_cnt > 0));
0932 
0933         if (!retry_cnt)
0934             cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
0935                      "get_work() timeout occurred.\n");
0936 
0937         /* Free packet */
0938         if (work)
0939             cvmx_helper_free_packet_data(work);
0940     }
0941 
0942 fix_ipd_exit:
0943 
0944     /* Return CSR configs to saved values */
0945     cvmx_write_csr(CVMX_GMXX_PRTX_CFG
0946                (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
0947                prtx_cfg);
0948     cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
0949                tx_ptr_en);
0950     cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
0951                rx_ptr_en);
0952     cvmx_write_csr(CVMX_GMXX_RXX_JABBER
0953                (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
0954                rxx_jabber);
0955     cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
0956                (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
0957                frame_max);
0958     cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
0959 
0960     CVMX_SYNC;
0961     if (num_segs)
0962         cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
0963 
0964     return !!num_segs;
0965 
0966 }
0967 
0968 /**
0969  * Called after all internal packet IO paths are setup. This
0970  * function enables IPD/PIP and begins packet input and output.
0971  *
0972  * Returns Zero on success, negative on failure
0973  */
0974 int cvmx_helper_ipd_and_packet_input_enable(void)
0975 {
0976     int num_interfaces;
0977     int interface;
0978 
0979     /* Enable IPD */
0980     cvmx_ipd_enable();
0981 
0982     /*
0983      * Time to enable hardware ports packet input and output. Note
0984      * that at this point IPD/PIP must be fully functional and PKO
0985      * must be disabled
0986      */
0987     num_interfaces = cvmx_helper_get_number_of_interfaces();
0988     for (interface = 0; interface < num_interfaces; interface++) {
0989         if (cvmx_helper_ports_on_interface(interface) > 0)
0990             __cvmx_helper_packet_hardware_enable(interface);
0991     }
0992 
0993     /* Finally enable PKO now that the entire path is up and running */
0994     cvmx_pko_enable();
0995 
0996     if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
0997          || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
0998         && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
0999         __cvmx_helper_errata_fix_ipd_ptr_alignment();
1000     return 0;
1001 }
1002 EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
1003 
1004 /**
1005  * Initialize the PIP, IPD, and PKO hardware to support
1006  * simple priority based queues for the ethernet ports. Each
1007  * port is configured with a number of priority queues based
1008  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1009  * priority than the previous.
1010  *
1011  * Returns Zero on success, non-zero on failure
1012  */
1013 int cvmx_helper_initialize_packet_io_global(void)
1014 {
1015     int result = 0;
1016     int interface;
1017     union cvmx_l2c_cfg l2c_cfg;
1018     const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1019 
1020     /*
1021      * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1022      * be disabled.
1023      */
1024     if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1025         __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1026 
1027     /*
1028      * Tell L2 to give the IOB statically higher priority compared
1029      * to the cores. This avoids conditions where IO blocks might
1030      * be starved under very high L2 loads.
1031      */
1032     l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1033     l2c_cfg.s.lrf_arb_mode = 0;
1034     l2c_cfg.s.rfb_arb_mode = 0;
1035     cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1036 
1037     cvmx_pko_initialize_global();
1038     for (interface = 0; interface < num_interfaces; interface++) {
1039         result |= cvmx_helper_interface_probe(interface);
1040         if (cvmx_helper_ports_on_interface(interface) > 0)
1041             cvmx_dprintf("Interface %d has %d ports (%s)\n",
1042                      interface,
1043                      cvmx_helper_ports_on_interface(interface),
1044                      cvmx_helper_interface_mode_to_string
1045                      (cvmx_helper_interface_get_mode
1046                       (interface)));
1047         result |= __cvmx_helper_interface_setup_ipd(interface);
1048         result |= __cvmx_helper_interface_setup_pko(interface);
1049     }
1050 
1051     result |= __cvmx_helper_global_setup_ipd();
1052     result |= __cvmx_helper_global_setup_pko();
1053 
1054     /* Enable any flow control and backpressure */
1055     result |= __cvmx_helper_global_setup_backpressure();
1056 
1057 #if CVMX_HELPER_ENABLE_IPD
1058     result |= cvmx_helper_ipd_and_packet_input_enable();
1059 #endif
1060     return result;
1061 }
1062 EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1063 
1064 /**
1065  * Return the link state of an IPD/PKO port as returned by
1066  * auto negotiation. The result of this function may not match
1067  * Octeon's link config if auto negotiation has changed since
1068  * the last call to cvmx_helper_link_set().
1069  *
1070  * @ipd_port: IPD/PKO port to query
1071  *
1072  * Returns Link state
1073  */
1074 union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
1075 {
1076     union cvmx_helper_link_info result;
1077     int interface = cvmx_helper_get_interface_num(ipd_port);
1078     int index = cvmx_helper_get_interface_index_num(ipd_port);
1079 
1080     /* The default result will be a down link unless the code below
1081        changes it */
1082     result.u64 = 0;
1083 
1084     if (index >= cvmx_helper_ports_on_interface(interface))
1085         return result;
1086 
1087     switch (cvmx_helper_interface_get_mode(interface)) {
1088     case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1089     case CVMX_HELPER_INTERFACE_MODE_PCIE:
1090         /* Network links are not supported */
1091         break;
1092     case CVMX_HELPER_INTERFACE_MODE_XAUI:
1093         result = __cvmx_helper_xaui_link_get(ipd_port);
1094         break;
1095     case CVMX_HELPER_INTERFACE_MODE_GMII:
1096         if (index == 0)
1097             result = __cvmx_helper_rgmii_link_get(ipd_port);
1098         else {
1099             WARN(1, "Using deprecated link status - please update your DT");
1100             result.s.full_duplex = 1;
1101             result.s.link_up = 1;
1102             result.s.speed = 1000;
1103         }
1104         break;
1105     case CVMX_HELPER_INTERFACE_MODE_RGMII:
1106         result = __cvmx_helper_rgmii_link_get(ipd_port);
1107         break;
1108     case CVMX_HELPER_INTERFACE_MODE_SPI:
1109         result = __cvmx_helper_spi_link_get(ipd_port);
1110         break;
1111     case CVMX_HELPER_INTERFACE_MODE_SGMII:
1112     case CVMX_HELPER_INTERFACE_MODE_PICMG:
1113         result = __cvmx_helper_sgmii_link_get(ipd_port);
1114         break;
1115     case CVMX_HELPER_INTERFACE_MODE_NPI:
1116     case CVMX_HELPER_INTERFACE_MODE_LOOP:
1117         /* Network links are not supported */
1118         break;
1119     }
1120     return result;
1121 }
1122 EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1123 
1124 /**
1125  * Configure an IPD/PKO port for the specified link state. This
1126  * function does not influence auto negotiation at the PHY level.
1127  * The passed link state must always match the link state returned
1128  * by cvmx_helper_link_get().
1129  *
1130  * @ipd_port:  IPD/PKO port to configure
1131  * @link_info: The new link state
1132  *
1133  * Returns Zero on success, negative on failure
1134  */
1135 int cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)
1136 {
1137     int result = -1;
1138     int interface = cvmx_helper_get_interface_num(ipd_port);
1139     int index = cvmx_helper_get_interface_index_num(ipd_port);
1140 
1141     if (index >= cvmx_helper_ports_on_interface(interface))
1142         return -1;
1143 
1144     switch (cvmx_helper_interface_get_mode(interface)) {
1145     case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1146     case CVMX_HELPER_INTERFACE_MODE_PCIE:
1147         break;
1148     case CVMX_HELPER_INTERFACE_MODE_XAUI:
1149         result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1150         break;
1151         /*
1152          * RGMII/GMII/MII are all treated about the same. Most
1153          * functions refer to these ports as RGMII.
1154          */
1155     case CVMX_HELPER_INTERFACE_MODE_RGMII:
1156     case CVMX_HELPER_INTERFACE_MODE_GMII:
1157         result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1158         break;
1159     case CVMX_HELPER_INTERFACE_MODE_SPI:
1160         result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1161         break;
1162     case CVMX_HELPER_INTERFACE_MODE_SGMII:
1163     case CVMX_HELPER_INTERFACE_MODE_PICMG:
1164         result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1165         break;
1166     case CVMX_HELPER_INTERFACE_MODE_NPI:
1167     case CVMX_HELPER_INTERFACE_MODE_LOOP:
1168         break;
1169     }
1170     return result;
1171 }
1172 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);