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