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 	cvmx_helper_link_info_t link_info;
845 
846 	/* Save values for restore at end */
847 	uint64_t prtx_cfg =
848 	    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
849 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
850 	uint64_t tx_ptr_en =
851 	    cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
852 	uint64_t rx_ptr_en =
853 	    cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
854 	uint64_t rxx_jabber =
855 	    cvmx_read_csr(CVMX_GMXX_RXX_JABBER
856 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
857 	uint64_t frame_max =
858 	    cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
859 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
860 
861 	/* Configure port to gig FDX as required for loopback mode */
862 	cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
863 
864 	/*
865 	 * Disable reception on all ports so if traffic is present it
866 	 * will not interfere.
867 	 */
868 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
869 
870 	cvmx_wait(100000000ull);
871 
872 	for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
873 		retry_cnt = 100000;
874 		wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
875 		pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
876 		wqe_pcnt &= 0x7f;
877 
878 		num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
879 
880 		if (num_segs == 0)
881 			goto fix_ipd_exit;
882 
883 		num_segs += 1;
884 
885 		size =
886 		    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
887 		    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
888 		    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
889 
890 		cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
891 			       1 << INDEX(FIX_IPD_OUTPORT));
892 		CVMX_SYNC;
893 
894 		g_buffer.u64 = 0;
895 		g_buffer.s.addr =
896 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
897 		if (g_buffer.s.addr == 0) {
898 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
899 				     "buffer allocation failure.\n");
900 			goto fix_ipd_exit;
901 		}
902 
903 		g_buffer.s.pool = CVMX_FPA_WQE_POOL;
904 		g_buffer.s.size = num_segs;
905 
906 		pkt_buffer.u64 = 0;
907 		pkt_buffer.s.addr =
908 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
909 		if (pkt_buffer.s.addr == 0) {
910 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
911 				     "buffer allocation failure.\n");
912 			goto fix_ipd_exit;
913 		}
914 		pkt_buffer.s.i = 1;
915 		pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
916 		pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
917 
918 		p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
919 		p64[0] = 0xffffffffffff0000ull;
920 		p64[1] = 0x08004510ull;
921 		p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
922 		p64[3] = 0x3a5fc0a81073c0a8ull;
923 
924 		for (i = 0; i < num_segs; i++) {
925 			if (i > 0)
926 				pkt_buffer.s.size =
927 				    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
928 
929 			if (i == (num_segs - 1))
930 				pkt_buffer.s.i = 0;
931 
932 			*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
933 						       8 * i) = pkt_buffer.u64;
934 		}
935 
936 		/* Build the PKO command */
937 		pko_command.u64 = 0;
938 		pko_command.s.segs = num_segs;
939 		pko_command.s.total_bytes = size;
940 		pko_command.s.dontfree = 0;
941 		pko_command.s.gather = 1;
942 
943 		gmx_cfg.u64 =
944 		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
945 				  (INDEX(FIX_IPD_OUTPORT),
946 				   INTERFACE(FIX_IPD_OUTPORT)));
947 		gmx_cfg.s.en = 1;
948 		cvmx_write_csr(CVMX_GMXX_PRTX_CFG
949 			       (INDEX(FIX_IPD_OUTPORT),
950 				INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
951 		cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
952 			       1 << INDEX(FIX_IPD_OUTPORT));
953 		cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
954 			       1 << INDEX(FIX_IPD_OUTPORT));
955 
956 		cvmx_write_csr(CVMX_GMXX_RXX_JABBER
957 			       (INDEX(FIX_IPD_OUTPORT),
958 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
959 		cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
960 			       (INDEX(FIX_IPD_OUTPORT),
961 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
962 
963 		cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
964 					     cvmx_pko_get_base_queue
965 					     (FIX_IPD_OUTPORT),
966 					     CVMX_PKO_LOCK_CMD_QUEUE);
967 		cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
968 					    cvmx_pko_get_base_queue
969 					    (FIX_IPD_OUTPORT), pko_command,
970 					    g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
971 
972 		CVMX_SYNC;
973 
974 		do {
975 			work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
976 			retry_cnt--;
977 		} while ((work == NULL) && (retry_cnt > 0));
978 
979 		if (!retry_cnt)
980 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
981 				     "get_work() timeout occurred.\n");
982 
983 		/* Free packet */
984 		if (work)
985 			cvmx_helper_free_packet_data(work);
986 	}
987 
988 fix_ipd_exit:
989 
990 	/* Return CSR configs to saved values */
991 	cvmx_write_csr(CVMX_GMXX_PRTX_CFG
992 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
993 		       prtx_cfg);
994 	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
995 		       tx_ptr_en);
996 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
997 		       rx_ptr_en);
998 	cvmx_write_csr(CVMX_GMXX_RXX_JABBER
999 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
1000 		       rxx_jabber);
1001 	cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
1002 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
1003 		       frame_max);
1004 	cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
1005 	/* Set link to down so autonegotiation will set it up again */
1006 	link_info.u64 = 0;
1007 	cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info);
1008 
1009 	/*
1010 	 * Bring the link back up as autonegotiation is not done in
1011 	 * user applications.
1012 	 */
1013 	cvmx_helper_link_autoconf(FIX_IPD_OUTPORT);
1014 
1015 	CVMX_SYNC;
1016 	if (num_segs)
1017 		cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
1018 
1019 	return !!num_segs;
1020 
1021 }
1022 
1023 /**
1024  * Called after all internal packet IO paths are setup. This
1025  * function enables IPD/PIP and begins packet input and output.
1026  *
1027  * Returns Zero on success, negative on failure
1028  */
1029 int cvmx_helper_ipd_and_packet_input_enable(void)
1030 {
1031 	int num_interfaces;
1032 	int interface;
1033 
1034 	/* Enable IPD */
1035 	cvmx_ipd_enable();
1036 
1037 	/*
1038 	 * Time to enable hardware ports packet input and output. Note
1039 	 * that at this point IPD/PIP must be fully functional and PKO
1040 	 * must be disabled
1041 	 */
1042 	num_interfaces = cvmx_helper_get_number_of_interfaces();
1043 	for (interface = 0; interface < num_interfaces; interface++) {
1044 		if (cvmx_helper_ports_on_interface(interface) > 0)
1045 			__cvmx_helper_packet_hardware_enable(interface);
1046 	}
1047 
1048 	/* Finally enable PKO now that the entire path is up and running */
1049 	cvmx_pko_enable();
1050 
1051 	if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
1052 	     || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
1053 	    && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
1054 		__cvmx_helper_errata_fix_ipd_ptr_alignment();
1055 	return 0;
1056 }
1057 EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
1058 
1059 /**
1060  * Initialize the PIP, IPD, and PKO hardware to support
1061  * simple priority based queues for the ethernet ports. Each
1062  * port is configured with a number of priority queues based
1063  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1064  * priority than the previous.
1065  *
1066  * Returns Zero on success, non-zero on failure
1067  */
1068 int cvmx_helper_initialize_packet_io_global(void)
1069 {
1070 	int result = 0;
1071 	int interface;
1072 	union cvmx_l2c_cfg l2c_cfg;
1073 	union cvmx_smix_en smix_en;
1074 	const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1075 
1076 	/*
1077 	 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1078 	 * be disabled.
1079 	 */
1080 	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1081 		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1082 
1083 	/*
1084 	 * Tell L2 to give the IOB statically higher priority compared
1085 	 * to the cores. This avoids conditions where IO blocks might
1086 	 * be starved under very high L2 loads.
1087 	 */
1088 	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1089 	l2c_cfg.s.lrf_arb_mode = 0;
1090 	l2c_cfg.s.rfb_arb_mode = 0;
1091 	cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1092 
1093 	/* Make sure SMI/MDIO is enabled so we can query PHYs */
1094 	smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
1095 	if (!smix_en.s.en) {
1096 		smix_en.s.en = 1;
1097 		cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
1098 	}
1099 
1100 	/* Newer chips actually have two SMI/MDIO interfaces */
1101 	if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
1102 	    !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
1103 	    !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
1104 		smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
1105 		if (!smix_en.s.en) {
1106 			smix_en.s.en = 1;
1107 			cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
1108 		}
1109 	}
1110 
1111 	cvmx_pko_initialize_global();
1112 	for (interface = 0; interface < num_interfaces; interface++) {
1113 		result |= cvmx_helper_interface_probe(interface);
1114 		if (cvmx_helper_ports_on_interface(interface) > 0)
1115 			cvmx_dprintf("Interface %d has %d ports (%s)\n",
1116 				     interface,
1117 				     cvmx_helper_ports_on_interface(interface),
1118 				     cvmx_helper_interface_mode_to_string
1119 				     (cvmx_helper_interface_get_mode
1120 				      (interface)));
1121 		result |= __cvmx_helper_interface_setup_ipd(interface);
1122 		result |= __cvmx_helper_interface_setup_pko(interface);
1123 	}
1124 
1125 	result |= __cvmx_helper_global_setup_ipd();
1126 	result |= __cvmx_helper_global_setup_pko();
1127 
1128 	/* Enable any flow control and backpressure */
1129 	result |= __cvmx_helper_global_setup_backpressure();
1130 
1131 #if CVMX_HELPER_ENABLE_IPD
1132 	result |= cvmx_helper_ipd_and_packet_input_enable();
1133 #endif
1134 	return result;
1135 }
1136 EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1137 
1138 /**
1139  * Does core local initialization for packet io
1140  *
1141  * Returns Zero on success, non-zero on failure
1142  */
1143 int cvmx_helper_initialize_packet_io_local(void)
1144 {
1145 	return cvmx_pko_initialize_local();
1146 }
1147 
1148 /**
1149  * Auto configure an IPD/PKO port link state and speed. This
1150  * function basically does the equivalent of:
1151  * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
1152  *
1153  * @ipd_port: IPD/PKO port to auto configure
1154  *
1155  * Returns Link state after configure
1156  */
1157 cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
1158 {
1159 	cvmx_helper_link_info_t link_info;
1160 	int interface = cvmx_helper_get_interface_num(ipd_port);
1161 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1162 
1163 	if (index >= cvmx_helper_ports_on_interface(interface)) {
1164 		link_info.u64 = 0;
1165 		return link_info;
1166 	}
1167 
1168 	link_info = cvmx_helper_link_get(ipd_port);
1169 	if (link_info.u64 == port_link_info[ipd_port].u64)
1170 		return link_info;
1171 
1172 	/* If we fail to set the link speed, port_link_info will not change */
1173 	cvmx_helper_link_set(ipd_port, link_info);
1174 
1175 	/*
1176 	 * port_link_info should be the current value, which will be
1177 	 * different than expect if cvmx_helper_link_set() failed.
1178 	 */
1179 	return port_link_info[ipd_port];
1180 }
1181 EXPORT_SYMBOL_GPL(cvmx_helper_link_autoconf);
1182 
1183 /**
1184  * Return the link state of an IPD/PKO port as returned by
1185  * auto negotiation. The result of this function may not match
1186  * Octeon's link config if auto negotiation has changed since
1187  * the last call to cvmx_helper_link_set().
1188  *
1189  * @ipd_port: IPD/PKO port to query
1190  *
1191  * Returns Link state
1192  */
1193 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1194 {
1195 	cvmx_helper_link_info_t result;
1196 	int interface = cvmx_helper_get_interface_num(ipd_port);
1197 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1198 
1199 	/* The default result will be a down link unless the code below
1200 	   changes it */
1201 	result.u64 = 0;
1202 
1203 	if (index >= cvmx_helper_ports_on_interface(interface))
1204 		return result;
1205 
1206 	switch (cvmx_helper_interface_get_mode(interface)) {
1207 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1208 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1209 		/* Network links are not supported */
1210 		break;
1211 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1212 		result = __cvmx_helper_xaui_link_get(ipd_port);
1213 		break;
1214 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1215 		if (index == 0)
1216 			result = __cvmx_helper_rgmii_link_get(ipd_port);
1217 		else {
1218 			result.s.full_duplex = 1;
1219 			result.s.link_up = 1;
1220 			result.s.speed = 1000;
1221 		}
1222 		break;
1223 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1224 		result = __cvmx_helper_rgmii_link_get(ipd_port);
1225 		break;
1226 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1227 		result = __cvmx_helper_spi_link_get(ipd_port);
1228 		break;
1229 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1230 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1231 		result = __cvmx_helper_sgmii_link_get(ipd_port);
1232 		break;
1233 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1234 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1235 		/* Network links are not supported */
1236 		break;
1237 	}
1238 	return result;
1239 }
1240 EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1241 
1242 /**
1243  * Configure an IPD/PKO port for the specified link state. This
1244  * function does not influence auto negotiation at the PHY level.
1245  * The passed link state must always match the link state returned
1246  * by cvmx_helper_link_get(). It is normally best to use
1247  * cvmx_helper_link_autoconf() instead.
1248  *
1249  * @ipd_port:  IPD/PKO port to configure
1250  * @link_info: The new link state
1251  *
1252  * Returns Zero on success, negative on failure
1253  */
1254 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1255 {
1256 	int result = -1;
1257 	int interface = cvmx_helper_get_interface_num(ipd_port);
1258 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1259 
1260 	if (index >= cvmx_helper_ports_on_interface(interface))
1261 		return -1;
1262 
1263 	switch (cvmx_helper_interface_get_mode(interface)) {
1264 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1265 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1266 		break;
1267 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1268 		result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1269 		break;
1270 		/*
1271 		 * RGMII/GMII/MII are all treated about the same. Most
1272 		 * functions refer to these ports as RGMII.
1273 		 */
1274 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1275 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1276 		result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1277 		break;
1278 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1279 		result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1280 		break;
1281 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1282 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1283 		result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1284 		break;
1285 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1286 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1287 		break;
1288 	}
1289 	/* Set the port_link_info here so that the link status is updated
1290 	   no matter how cvmx_helper_link_set is called. We don't change
1291 	   the value if link_set failed */
1292 	if (result == 0)
1293 		port_link_info[ipd_port].u64 = link_info.u64;
1294 	return result;
1295 }
1296 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1297 
1298 /**
1299  * Configure a port for internal and/or external loopback. Internal loopback
1300  * causes packets sent by the port to be received by Octeon. External loopback
1301  * causes packets received from the wire to sent out again.
1302  *
1303  * @ipd_port: IPD/PKO port to loopback.
1304  * @enable_internal:
1305  *		   Non zero if you want internal loopback
1306  * @enable_external:
1307  *		   Non zero if you want external loopback
1308  *
1309  * Returns Zero on success, negative on failure.
1310  */
1311 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1312 				   int enable_external)
1313 {
1314 	int result = -1;
1315 	int interface = cvmx_helper_get_interface_num(ipd_port);
1316 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1317 
1318 	if (index >= cvmx_helper_ports_on_interface(interface))
1319 		return -1;
1320 
1321 	switch (cvmx_helper_interface_get_mode(interface)) {
1322 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1323 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1324 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1325 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1326 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1327 		break;
1328 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1329 		result =
1330 		    __cvmx_helper_xaui_configure_loopback(ipd_port,
1331 							  enable_internal,
1332 							  enable_external);
1333 		break;
1334 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1335 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1336 		result =
1337 		    __cvmx_helper_rgmii_configure_loopback(ipd_port,
1338 							   enable_internal,
1339 							   enable_external);
1340 		break;
1341 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1342 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1343 		result =
1344 		    __cvmx_helper_sgmii_configure_loopback(ipd_port,
1345 							   enable_internal,
1346 							   enable_external);
1347 		break;
1348 	}
1349 	return result;
1350 }
1351