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