xref: /linux/arch/mips/cavium-octeon/executive/cvmx-helper.c (revision e5a52fd2b8cdb700b3c07b030e050a49ef3156b9)
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 */
50 static 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  */
60 int 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 }
71 EXPORT_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  */
82 int cvmx_helper_ports_on_interface(int interface)
83 {
84 	return interface_port_count[interface];
85 }
86 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
87 
88 /**
89  * @INTERNAL
90  * Return interface mode for CN68xx.
91  */
92 static 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  */
144 static 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  */
244 static 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  */
286 cvmx_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 }
356 EXPORT_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  */
369 static 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  */
416 int 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  */
492 int 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  */
559 static 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  */
577 static 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  */
602 static 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  */
643 static 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  */
677 static 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  */
717 static 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  */
774 static 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 
936 fix_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  */
968 int 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 }
996 EXPORT_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  */
1007 int 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 }
1056 EXPORT_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  */
1063 int 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  */
1078 union 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(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 }
1126 EXPORT_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  */
1139 int 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 }
1176 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1177