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