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);
1173