cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cvmx-helper.c (35092B)


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