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