Linux Audio

Check our new training course

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