File Index
Files and directories
Sign in
FILE

cvmx-helper.c

File preview with syntax highlighting.

linux-6.19.14/arch/mips/cavium-octeon/executive/cvmx-helper.c C
   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_ONCE(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);
~/ Read-only file preview.