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