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