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_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 }
77 EXPORT_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  */
88 int cvmx_helper_ports_on_interface(int interface)
89 {
90 	return interface_port_count[interface];
91 }
92 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
93 
94 /**
95  * @INTERNAL
96  * Return interface mode for CN68xx.
97  */
98 static 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  */
150 static 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  */
250 static 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  */
292 cvmx_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 }
362 EXPORT_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  */
375 static 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  */
422 int 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  */
498 int 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  */
565 static 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  */
583 static 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  */
608 static 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  */
649 static 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  */
683 static 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  */
723 static 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  */
780 static 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 
942 fix_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  */
974 int 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 }
1002 EXPORT_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  */
1013 int 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 }
1062 EXPORT_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  */
1074 union 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 }
1122 EXPORT_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  */
1135 int 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 }
1172 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1173