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