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