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