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