xref: /linux/arch/mips/cavium-octeon/executive/cvmx-helper.c (revision ce4126cbe3d90cd00cb62f75b3b15f8e9260a301)
1af866496SDavid Daney /***********************license start***************
2af866496SDavid Daney  * Author: Cavium Networks
3af866496SDavid Daney  *
4af866496SDavid Daney  * Contact: support@caviumnetworks.com
5af866496SDavid Daney  * This file is part of the OCTEON SDK
6af866496SDavid Daney  *
7af866496SDavid Daney  * Copyright (c) 2003-2008 Cavium Networks
8af866496SDavid Daney  *
9af866496SDavid Daney  * This file is free software; you can redistribute it and/or modify
10af866496SDavid Daney  * it under the terms of the GNU General Public License, Version 2, as
11af866496SDavid Daney  * published by the Free Software Foundation.
12af866496SDavid Daney  *
13af866496SDavid Daney  * This file is distributed in the hope that it will be useful, but
14af866496SDavid Daney  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15af866496SDavid Daney  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16af866496SDavid Daney  * NONINFRINGEMENT.  See the GNU General Public License for more
17af866496SDavid Daney  * details.
18af866496SDavid Daney  *
19af866496SDavid Daney  * You should have received a copy of the GNU General Public License
20af866496SDavid Daney  * along with this file; if not, write to the Free Software
21af866496SDavid Daney  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22af866496SDavid Daney  * or visit http://www.gnu.org/licenses/.
23af866496SDavid Daney  *
24af866496SDavid Daney  * This file may also be available under a different license from Cavium.
25af866496SDavid Daney  * Contact Cavium Networks for more information
26af866496SDavid Daney  ***********************license end**************************************/
27af866496SDavid Daney 
28af866496SDavid Daney /*
29af866496SDavid Daney  *
30af866496SDavid Daney  * Helper functions for common, but complicated tasks.
31af866496SDavid Daney  *
32af866496SDavid Daney  */
33af866496SDavid Daney #include <asm/octeon/octeon.h>
34af866496SDavid Daney 
35af866496SDavid Daney #include <asm/octeon/cvmx-config.h>
36af866496SDavid Daney 
37af866496SDavid Daney #include <asm/octeon/cvmx-fpa.h>
38af866496SDavid Daney #include <asm/octeon/cvmx-pip.h>
39af866496SDavid Daney #include <asm/octeon/cvmx-pko.h>
40af866496SDavid Daney #include <asm/octeon/cvmx-ipd.h>
41af866496SDavid Daney #include <asm/octeon/cvmx-spi.h>
42af866496SDavid Daney #include <asm/octeon/cvmx-helper.h>
43af866496SDavid Daney #include <asm/octeon/cvmx-helper-board.h>
44af866496SDavid Daney 
45af866496SDavid Daney #include <asm/octeon/cvmx-pip-defs.h>
46af866496SDavid Daney #include <asm/octeon/cvmx-smix-defs.h>
47af866496SDavid Daney #include <asm/octeon/cvmx-asxx-defs.h>
48af866496SDavid Daney 
49af866496SDavid Daney /**
50af866496SDavid Daney  * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
51af866496SDavid Daney  * priorities[16]) is a function pointer. It is meant to allow
52af866496SDavid Daney  * customization of the PKO queue priorities based on the port
53af866496SDavid Daney  * number. Users should set this pointer to a function before
54af866496SDavid Daney  * calling any cvmx-helper operations.
55af866496SDavid Daney  */
56af866496SDavid Daney void (*cvmx_override_pko_queue_priority) (int pko_port,
57af866496SDavid Daney 					  uint64_t priorities[16]);
58af866496SDavid Daney 
59af866496SDavid Daney /**
60af866496SDavid Daney  * cvmx_override_ipd_port_setup(int ipd_port) is a function
61af866496SDavid Daney  * pointer. It is meant to allow customization of the IPD port
62af866496SDavid Daney  * setup before packet input/output comes online. It is called
63af866496SDavid Daney  * after cvmx-helper does the default IPD configuration, but
64af866496SDavid Daney  * before IPD is enabled. Users should set this pointer to a
65af866496SDavid Daney  * function before calling any cvmx-helper operations.
66af866496SDavid Daney  */
67af866496SDavid Daney void (*cvmx_override_ipd_port_setup) (int ipd_port);
68af866496SDavid Daney 
69af866496SDavid Daney /* Port count per interface */
708b75e770SAaro Koskinen static int interface_port_count[5];
71af866496SDavid Daney 
72af866496SDavid Daney /* Port last configured link info index by IPD/PKO port */
73af866496SDavid Daney static cvmx_helper_link_info_t
74af866496SDavid Daney     port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
75af866496SDavid Daney 
76af866496SDavid Daney /**
77af866496SDavid Daney  * Return the number of interfaces the chip has. Each interface
78af866496SDavid Daney  * may have multiple ports. Most chips support two interfaces,
79af866496SDavid Daney  * but the CNX0XX and CNX1XX are exceptions. These only support
80af866496SDavid Daney  * one interface.
81af866496SDavid Daney  *
82af866496SDavid Daney  * Returns Number of interfaces on chip
83af866496SDavid Daney  */
84af866496SDavid Daney int cvmx_helper_get_number_of_interfaces(void)
85af866496SDavid Daney {
86af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
87af866496SDavid Daney 		return 4;
88af866496SDavid Daney 	else
89af866496SDavid Daney 		return 3;
90af866496SDavid Daney }
91*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
92af866496SDavid Daney 
93af866496SDavid Daney /**
94af866496SDavid Daney  * Return the number of ports on an interface. Depending on the
95af866496SDavid Daney  * chip and configuration, this can be 1-16. A value of 0
96af866496SDavid Daney  * specifies that the interface doesn't exist or isn't usable.
97af866496SDavid Daney  *
98af866496SDavid Daney  * @interface: Interface to get the port count for
99af866496SDavid Daney  *
100af866496SDavid Daney  * Returns Number of ports on interface. Can be Zero.
101af866496SDavid Daney  */
102af866496SDavid Daney int cvmx_helper_ports_on_interface(int interface)
103af866496SDavid Daney {
104af866496SDavid Daney 	return interface_port_count[interface];
105af866496SDavid Daney }
106*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
107af866496SDavid Daney 
108af866496SDavid Daney /**
109af866496SDavid Daney  * Get the operating mode of an interface. Depending on the Octeon
110af866496SDavid Daney  * chip and configuration, this function returns an enumeration
111af866496SDavid Daney  * of the type of packet I/O supported by an interface.
112af866496SDavid Daney  *
113af866496SDavid Daney  * @interface: Interface to probe
114af866496SDavid Daney  *
115af866496SDavid Daney  * Returns Mode of the interface. Unknown or unsupported interfaces return
116af866496SDavid Daney  *	   DISABLED.
117af866496SDavid Daney  */
118af866496SDavid Daney cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
119af866496SDavid Daney {
120af866496SDavid Daney 	union cvmx_gmxx_inf_mode mode;
121af866496SDavid Daney 	if (interface == 2)
122af866496SDavid Daney 		return CVMX_HELPER_INTERFACE_MODE_NPI;
123af866496SDavid Daney 
124af866496SDavid Daney 	if (interface == 3) {
125af866496SDavid Daney 		if (OCTEON_IS_MODEL(OCTEON_CN56XX)
126af866496SDavid Daney 		    || OCTEON_IS_MODEL(OCTEON_CN52XX))
127af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_LOOP;
128af866496SDavid Daney 		else
129af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
130af866496SDavid Daney 	}
131af866496SDavid Daney 
132af866496SDavid Daney 	if (interface == 0
133af866496SDavid Daney 	    && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
134af866496SDavid Daney 	    && cvmx_sysinfo_get()->board_rev_major == 1) {
135af866496SDavid Daney 		/*
136af866496SDavid Daney 		 * Lie about interface type of CN3005 board.  This
137af866496SDavid Daney 		 * board has a switch on port 1 like the other
138af866496SDavid Daney 		 * evaluation boards, but it is connected over RGMII
139af866496SDavid Daney 		 * instead of GMII.  Report GMII mode so that the
140af866496SDavid Daney 		 * speed is forced to 1 Gbit full duplex.  Other than
141af866496SDavid Daney 		 * some initial configuration (which does not use the
142af866496SDavid Daney 		 * output of this function) there is no difference in
143af866496SDavid Daney 		 * setup between GMII and RGMII modes.
144af866496SDavid Daney 		 */
145af866496SDavid Daney 		return CVMX_HELPER_INTERFACE_MODE_GMII;
146af866496SDavid Daney 	}
147af866496SDavid Daney 
148af866496SDavid Daney 	/* Interface 1 is always disabled on CN31XX and CN30XX */
149af866496SDavid Daney 	if ((interface == 1)
150af866496SDavid Daney 	    && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
151af866496SDavid Daney 		|| OCTEON_IS_MODEL(OCTEON_CN50XX)
152af866496SDavid Daney 		|| OCTEON_IS_MODEL(OCTEON_CN52XX)))
153af866496SDavid Daney 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
154af866496SDavid Daney 
155af866496SDavid Daney 	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
156af866496SDavid Daney 
157af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
158af866496SDavid Daney 		switch (mode.cn56xx.mode) {
159af866496SDavid Daney 		case 0:
160af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
161af866496SDavid Daney 		case 1:
162af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
163af866496SDavid Daney 		case 2:
164af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
165af866496SDavid Daney 		case 3:
166af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_PICMG;
167af866496SDavid Daney 		default:
168af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
169af866496SDavid Daney 		}
170af866496SDavid Daney 	} else {
171af866496SDavid Daney 		if (!mode.s.en)
172af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
173af866496SDavid Daney 
174af866496SDavid Daney 		if (mode.s.type) {
175af866496SDavid Daney 			if (OCTEON_IS_MODEL(OCTEON_CN38XX)
176af866496SDavid Daney 			    || OCTEON_IS_MODEL(OCTEON_CN58XX))
177af866496SDavid Daney 				return CVMX_HELPER_INTERFACE_MODE_SPI;
178af866496SDavid Daney 			else
179af866496SDavid Daney 				return CVMX_HELPER_INTERFACE_MODE_GMII;
180af866496SDavid Daney 		} else
181af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_RGMII;
182af866496SDavid Daney 	}
183af866496SDavid Daney }
184*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
185af866496SDavid Daney 
186af866496SDavid Daney /**
187af866496SDavid Daney  * Configure the IPD/PIP tagging and QoS options for a specific
188af866496SDavid Daney  * port. This function determines the POW work queue entry
189af866496SDavid Daney  * contents for a port. The setup performed here is controlled by
190af866496SDavid Daney  * the defines in executive-config.h.
191af866496SDavid Daney  *
192af866496SDavid Daney  * @ipd_port: Port to configure. This follows the IPD numbering, not the
193af866496SDavid Daney  *		   per interface numbering
194af866496SDavid Daney  *
195af866496SDavid Daney  * Returns Zero on success, negative on failure
196af866496SDavid Daney  */
197af866496SDavid Daney static int __cvmx_helper_port_setup_ipd(int ipd_port)
198af866496SDavid Daney {
199af866496SDavid Daney 	union cvmx_pip_prt_cfgx port_config;
200af866496SDavid Daney 	union cvmx_pip_prt_tagx tag_config;
201af866496SDavid Daney 
202af866496SDavid Daney 	port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
203af866496SDavid Daney 	tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
204af866496SDavid Daney 
205af866496SDavid Daney 	/* Have each port go to a different POW queue */
206af866496SDavid Daney 	port_config.s.qos = ipd_port & 0x7;
207af866496SDavid Daney 
208af866496SDavid Daney 	/* Process the headers and place the IP header in the work queue */
209af866496SDavid Daney 	port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
210af866496SDavid Daney 
211af866496SDavid Daney 	tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
212af866496SDavid Daney 	tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
213af866496SDavid Daney 	tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
214af866496SDavid Daney 	tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
215af866496SDavid Daney 	tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
216af866496SDavid Daney 	tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
217af866496SDavid Daney 	tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
218af866496SDavid Daney 	tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
219af866496SDavid Daney 	tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
220af866496SDavid Daney 	tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
221af866496SDavid Daney 	tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
222af866496SDavid Daney 	tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
223af866496SDavid Daney 	tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
224af866496SDavid Daney 	tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
225af866496SDavid Daney 	tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
226af866496SDavid Daney 	tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
227af866496SDavid Daney 	/* Put all packets in group 0. Other groups can be used by the app */
228af866496SDavid Daney 	tag_config.s.grp = 0;
229af866496SDavid Daney 
230af866496SDavid Daney 	cvmx_pip_config_port(ipd_port, port_config, tag_config);
231af866496SDavid Daney 
232af866496SDavid Daney 	/* Give the user a chance to override our setting for each port */
233af866496SDavid Daney 	if (cvmx_override_ipd_port_setup)
234af866496SDavid Daney 		cvmx_override_ipd_port_setup(ipd_port);
235af866496SDavid Daney 
236af866496SDavid Daney 	return 0;
237af866496SDavid Daney }
238af866496SDavid Daney 
239af866496SDavid Daney /**
24037d3bfd9SDavid Daney  * This function sets the interface_port_count[interface] correctly,
24137d3bfd9SDavid Daney  * without modifying any hardware configuration.  Hardware setup of
24237d3bfd9SDavid Daney  * the ports will be performed later.
24337d3bfd9SDavid Daney  *
24437d3bfd9SDavid Daney  * @interface: Interface to probe
24537d3bfd9SDavid Daney  *
24637d3bfd9SDavid Daney  * Returns Zero on success, negative on failure
24737d3bfd9SDavid Daney  */
24837d3bfd9SDavid Daney int cvmx_helper_interface_enumerate(int interface)
24937d3bfd9SDavid Daney {
25037d3bfd9SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
25137d3bfd9SDavid Daney 		/* These types don't support ports to IPD/PKO */
25237d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
25337d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
25437d3bfd9SDavid Daney 		interface_port_count[interface] = 0;
25537d3bfd9SDavid Daney 		break;
25637d3bfd9SDavid Daney 		/* XAUI is a single high speed port */
25737d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
25837d3bfd9SDavid Daney 		interface_port_count[interface] =
25937d3bfd9SDavid Daney 		    __cvmx_helper_xaui_enumerate(interface);
26037d3bfd9SDavid Daney 		break;
26137d3bfd9SDavid Daney 		/*
26237d3bfd9SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
26337d3bfd9SDavid Daney 		 * functions refer to these ports as RGMII.
26437d3bfd9SDavid Daney 		 */
26537d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
26637d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
26737d3bfd9SDavid Daney 		interface_port_count[interface] =
26837d3bfd9SDavid Daney 		    __cvmx_helper_rgmii_enumerate(interface);
26937d3bfd9SDavid Daney 		break;
27037d3bfd9SDavid Daney 		/*
27137d3bfd9SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
27237d3bfd9SDavid Daney 		 * the other end.
27337d3bfd9SDavid Daney 		 */
27437d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
27537d3bfd9SDavid Daney 		interface_port_count[interface] =
27637d3bfd9SDavid Daney 		    __cvmx_helper_spi_enumerate(interface);
27737d3bfd9SDavid Daney 		break;
27837d3bfd9SDavid Daney 		/*
27937d3bfd9SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
28037d3bfd9SDavid Daney 		 * hooked up.
28137d3bfd9SDavid Daney 		 */
28237d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
28337d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
28437d3bfd9SDavid Daney 		interface_port_count[interface] =
28537d3bfd9SDavid Daney 		    __cvmx_helper_sgmii_enumerate(interface);
28637d3bfd9SDavid Daney 		break;
28737d3bfd9SDavid Daney 		/* PCI target Network Packet Interface */
28837d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
28937d3bfd9SDavid Daney 		interface_port_count[interface] =
29037d3bfd9SDavid Daney 		    __cvmx_helper_npi_enumerate(interface);
29137d3bfd9SDavid Daney 		break;
29237d3bfd9SDavid Daney 		/*
29337d3bfd9SDavid Daney 		 * Special loopback only ports. These are not the same
29437d3bfd9SDavid Daney 		 * as other ports in loopback mode.
29537d3bfd9SDavid Daney 		 */
29637d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
29737d3bfd9SDavid Daney 		interface_port_count[interface] =
29837d3bfd9SDavid Daney 		    __cvmx_helper_loop_enumerate(interface);
29937d3bfd9SDavid Daney 		break;
30037d3bfd9SDavid Daney 	}
30137d3bfd9SDavid Daney 
30237d3bfd9SDavid Daney 	interface_port_count[interface] =
30337d3bfd9SDavid Daney 	    __cvmx_helper_board_interface_probe(interface,
30437d3bfd9SDavid Daney 						interface_port_count
30537d3bfd9SDavid Daney 						[interface]);
30637d3bfd9SDavid Daney 
30737d3bfd9SDavid Daney 	/* Make sure all global variables propagate to other cores */
30837d3bfd9SDavid Daney 	CVMX_SYNCWS;
30937d3bfd9SDavid Daney 
31037d3bfd9SDavid Daney 	return 0;
31137d3bfd9SDavid Daney }
31237d3bfd9SDavid Daney 
31337d3bfd9SDavid Daney /**
314af866496SDavid Daney  * This function probes an interface to determine the actual
315af866496SDavid Daney  * number of hardware ports connected to it. It doesn't setup the
316af866496SDavid Daney  * ports or enable them. The main goal here is to set the global
317af866496SDavid Daney  * interface_port_count[interface] correctly. Hardware setup of the
318af866496SDavid Daney  * ports will be performed later.
319af866496SDavid Daney  *
320af866496SDavid Daney  * @interface: Interface to probe
321af866496SDavid Daney  *
322af866496SDavid Daney  * Returns Zero on success, negative on failure
323af866496SDavid Daney  */
324af866496SDavid Daney int cvmx_helper_interface_probe(int interface)
325af866496SDavid Daney {
32637d3bfd9SDavid Daney 	cvmx_helper_interface_enumerate(interface);
327af866496SDavid Daney 	/* At this stage in the game we don't want packets to be moving yet.
328af866496SDavid Daney 	   The following probe calls should perform hardware setup
329af866496SDavid Daney 	   needed to determine port counts. Receive must still be disabled */
330af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
331af866496SDavid Daney 		/* These types don't support ports to IPD/PKO */
332af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
333af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
334af866496SDavid Daney 		break;
335af866496SDavid Daney 		/* XAUI is a single high speed port */
336af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
337af866496SDavid Daney 		__cvmx_helper_xaui_probe(interface);
338af866496SDavid Daney 		break;
339af866496SDavid Daney 		/*
340af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
341af866496SDavid Daney 		 * functions refer to these ports as RGMII.
342af866496SDavid Daney 		 */
343af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
344af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
345af866496SDavid Daney 		__cvmx_helper_rgmii_probe(interface);
346af866496SDavid Daney 		break;
347af866496SDavid Daney 		/*
348af866496SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
349af866496SDavid Daney 		 * the other end.
350af866496SDavid Daney 		 */
351af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
352af866496SDavid Daney 		__cvmx_helper_spi_probe(interface);
353af866496SDavid Daney 		break;
354af866496SDavid Daney 		/*
355af866496SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
356af866496SDavid Daney 		 * hooked up.
357af866496SDavid Daney 		 */
358af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
359af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
360af866496SDavid Daney 		__cvmx_helper_sgmii_probe(interface);
361af866496SDavid Daney 		break;
362af866496SDavid Daney 		/* PCI target Network Packet Interface */
363af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
364af866496SDavid Daney 		__cvmx_helper_npi_probe(interface);
365af866496SDavid Daney 		break;
366af866496SDavid Daney 		/*
367af866496SDavid Daney 		 * Special loopback only ports. These are not the same
368af866496SDavid Daney 		 * as other ports in loopback mode.
369af866496SDavid Daney 		 */
370af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
371af866496SDavid Daney 		__cvmx_helper_loop_probe(interface);
372af866496SDavid Daney 		break;
373af866496SDavid Daney 	}
374af866496SDavid Daney 
375af866496SDavid Daney 	/* Make sure all global variables propagate to other cores */
376af866496SDavid Daney 	CVMX_SYNCWS;
377af866496SDavid Daney 
378af866496SDavid Daney 	return 0;
379af866496SDavid Daney }
380af866496SDavid Daney 
381af866496SDavid Daney /**
382af866496SDavid Daney  * Setup the IPD/PIP for the ports on an interface. Packet
383af866496SDavid Daney  * classification and tagging are set for every port on the
384af866496SDavid Daney  * interface. The number of ports on the interface must already
385af866496SDavid Daney  * have been probed.
386af866496SDavid Daney  *
387af866496SDavid Daney  * @interface: Interface to setup IPD/PIP for
388af866496SDavid Daney  *
389af866496SDavid Daney  * Returns Zero on success, negative on failure
390af866496SDavid Daney  */
391af866496SDavid Daney static int __cvmx_helper_interface_setup_ipd(int interface)
392af866496SDavid Daney {
393af866496SDavid Daney 	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
394af866496SDavid Daney 	int num_ports = interface_port_count[interface];
395af866496SDavid Daney 
396af866496SDavid Daney 	while (num_ports--) {
397af866496SDavid Daney 		__cvmx_helper_port_setup_ipd(ipd_port);
398af866496SDavid Daney 		ipd_port++;
399af866496SDavid Daney 	}
400af866496SDavid Daney 	return 0;
401af866496SDavid Daney }
402af866496SDavid Daney 
403af866496SDavid Daney /**
404af866496SDavid Daney  * Setup global setting for IPD/PIP not related to a specific
405af866496SDavid Daney  * interface or port. This must be called before IPD is enabled.
406af866496SDavid Daney  *
407af866496SDavid Daney  * Returns Zero on success, negative on failure.
408af866496SDavid Daney  */
409af866496SDavid Daney static int __cvmx_helper_global_setup_ipd(void)
410af866496SDavid Daney {
411af866496SDavid Daney 	/* Setup the global packet input options */
412af866496SDavid Daney 	cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
413af866496SDavid Daney 			CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
414af866496SDavid Daney 			CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
415af866496SDavid Daney 			/* The +8 is to account for the next ptr */
416af866496SDavid Daney 			(CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
417af866496SDavid Daney 			/* The +8 is to account for the next ptr */
418af866496SDavid Daney 			(CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
419af866496SDavid Daney 			CVMX_FPA_WQE_POOL,
420af866496SDavid Daney 			CVMX_IPD_OPC_MODE_STT,
421af866496SDavid Daney 			CVMX_HELPER_ENABLE_BACK_PRESSURE);
422af866496SDavid Daney 	return 0;
423af866496SDavid Daney }
424af866496SDavid Daney 
425af866496SDavid Daney /**
426af866496SDavid Daney  * Setup the PKO for the ports on an interface. The number of
427af866496SDavid Daney  * queues per port and the priority of each PKO output queue
428af866496SDavid Daney  * is set here. PKO must be disabled when this function is called.
429af866496SDavid Daney  *
430af866496SDavid Daney  * @interface: Interface to setup PKO for
431af866496SDavid Daney  *
432af866496SDavid Daney  * Returns Zero on success, negative on failure
433af866496SDavid Daney  */
434af866496SDavid Daney static int __cvmx_helper_interface_setup_pko(int interface)
435af866496SDavid Daney {
436af866496SDavid Daney 	/*
437af866496SDavid Daney 	 * Each packet output queue has an associated priority. The
438af866496SDavid Daney 	 * higher the priority, the more often it can send a packet. A
439af866496SDavid Daney 	 * priority of 8 means it can send in all 8 rounds of
440af866496SDavid Daney 	 * contention. We're going to make each queue one less than
441af866496SDavid Daney 	 * the last.  The vector of priorities has been extended to
442af866496SDavid Daney 	 * support CN5xxx CPUs, where up to 16 queues can be
443af866496SDavid Daney 	 * associated to a port.  To keep backward compatibility we
444af866496SDavid Daney 	 * don't change the initial 8 priorities and replicate them in
445af866496SDavid Daney 	 * the second half.  With per-core PKO queues (PKO lockless
446af866496SDavid Daney 	 * operation) all queues have the same priority.
447af866496SDavid Daney 	 */
448af866496SDavid Daney 	uint64_t priorities[16] =
449af866496SDavid Daney 	    { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
450af866496SDavid Daney 
451af866496SDavid Daney 	/*
452af866496SDavid Daney 	 * Setup the IPD/PIP and PKO for the ports discovered
453af866496SDavid Daney 	 * above. Here packet classification, tagging and output
454af866496SDavid Daney 	 * priorities are set.
455af866496SDavid Daney 	 */
456af866496SDavid Daney 	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
457af866496SDavid Daney 	int num_ports = interface_port_count[interface];
458af866496SDavid Daney 	while (num_ports--) {
459af866496SDavid Daney 		/*
460af866496SDavid Daney 		 * Give the user a chance to override the per queue
461af866496SDavid Daney 		 * priorities.
462af866496SDavid Daney 		 */
463af866496SDavid Daney 		if (cvmx_override_pko_queue_priority)
464af866496SDavid Daney 			cvmx_override_pko_queue_priority(ipd_port, priorities);
465af866496SDavid Daney 
466af866496SDavid Daney 		cvmx_pko_config_port(ipd_port,
467af866496SDavid Daney 				     cvmx_pko_get_base_queue_per_core(ipd_port,
468af866496SDavid Daney 								      0),
469af866496SDavid Daney 				     cvmx_pko_get_num_queues(ipd_port),
470af866496SDavid Daney 				     priorities);
471af866496SDavid Daney 		ipd_port++;
472af866496SDavid Daney 	}
473af866496SDavid Daney 	return 0;
474af866496SDavid Daney }
475af866496SDavid Daney 
476af866496SDavid Daney /**
477af866496SDavid Daney  * Setup global setting for PKO not related to a specific
478af866496SDavid Daney  * interface or port. This must be called before PKO is enabled.
479af866496SDavid Daney  *
480af866496SDavid Daney  * Returns Zero on success, negative on failure.
481af866496SDavid Daney  */
482af866496SDavid Daney static int __cvmx_helper_global_setup_pko(void)
483af866496SDavid Daney {
484af866496SDavid Daney 	/*
485af866496SDavid Daney 	 * Disable tagwait FAU timeout. This needs to be done before
486af866496SDavid Daney 	 * anyone might start packet output using tags.
487af866496SDavid Daney 	 */
488af866496SDavid Daney 	union cvmx_iob_fau_timeout fau_to;
489af866496SDavid Daney 	fau_to.u64 = 0;
490af866496SDavid Daney 	fau_to.s.tout_val = 0xfff;
491af866496SDavid Daney 	fau_to.s.tout_enb = 0;
492af866496SDavid Daney 	cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
493af866496SDavid Daney 	return 0;
494af866496SDavid Daney }
495af866496SDavid Daney 
496af866496SDavid Daney /**
497af866496SDavid Daney  * Setup global backpressure setting.
498af866496SDavid Daney  *
499af866496SDavid Daney  * Returns Zero on success, negative on failure
500af866496SDavid Daney  */
501af866496SDavid Daney static int __cvmx_helper_global_setup_backpressure(void)
502af866496SDavid Daney {
503af866496SDavid Daney #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
504af866496SDavid Daney 	/* Disable backpressure if configured to do so */
505af866496SDavid Daney 	/* Disable backpressure (pause frame) generation */
506af866496SDavid Daney 	int num_interfaces = cvmx_helper_get_number_of_interfaces();
507af866496SDavid Daney 	int interface;
508af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
509af866496SDavid Daney 		switch (cvmx_helper_interface_get_mode(interface)) {
510af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_DISABLED:
511af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_PCIE:
512af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_NPI:
513af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_LOOP:
514af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_XAUI:
515af866496SDavid Daney 			break;
516af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_RGMII:
517af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_GMII:
518af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_SPI:
519af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_SGMII:
520af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_PICMG:
521af866496SDavid Daney 			cvmx_gmx_set_backpressure_override(interface, 0xf);
522af866496SDavid Daney 			break;
523af866496SDavid Daney 		}
524af866496SDavid Daney 	}
525af866496SDavid Daney #endif
526af866496SDavid Daney 
527af866496SDavid Daney 	return 0;
528af866496SDavid Daney }
529af866496SDavid Daney 
530af866496SDavid Daney /**
531af866496SDavid Daney  * Enable packet input/output from the hardware. This function is
532af866496SDavid Daney  * called after all internal setup is complete and IPD is enabled.
533af866496SDavid Daney  * After this function completes, packets will be accepted from the
534af866496SDavid Daney  * hardware ports. PKO should still be disabled to make sure packets
535af866496SDavid Daney  * aren't sent out partially setup hardware.
536af866496SDavid Daney  *
537af866496SDavid Daney  * @interface: Interface to enable
538af866496SDavid Daney  *
539af866496SDavid Daney  * Returns Zero on success, negative on failure
540af866496SDavid Daney  */
541af866496SDavid Daney static int __cvmx_helper_packet_hardware_enable(int interface)
542af866496SDavid Daney {
543af866496SDavid Daney 	int result = 0;
544af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
545af866496SDavid Daney 		/* These types don't support ports to IPD/PKO */
546af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
547af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
548af866496SDavid Daney 		/* Nothing to do */
549af866496SDavid Daney 		break;
550af866496SDavid Daney 		/* XAUI is a single high speed port */
551af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
552af866496SDavid Daney 		result = __cvmx_helper_xaui_enable(interface);
553af866496SDavid Daney 		break;
554af866496SDavid Daney 		/*
555af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
556af866496SDavid Daney 		 * functions refer to these ports as RGMII
557af866496SDavid Daney 		 */
558af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
559af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
560af866496SDavid Daney 		result = __cvmx_helper_rgmii_enable(interface);
561af866496SDavid Daney 		break;
562af866496SDavid Daney 		/*
563af866496SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
564af866496SDavid Daney 		 * the other end
565af866496SDavid Daney 		 */
566af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
567af866496SDavid Daney 		result = __cvmx_helper_spi_enable(interface);
568af866496SDavid Daney 		break;
569af866496SDavid Daney 		/*
570af866496SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
571af866496SDavid Daney 		 * hooked up
572af866496SDavid Daney 		 */
573af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
574af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
575af866496SDavid Daney 		result = __cvmx_helper_sgmii_enable(interface);
576af866496SDavid Daney 		break;
577af866496SDavid Daney 		/* PCI target Network Packet Interface */
578af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
579af866496SDavid Daney 		result = __cvmx_helper_npi_enable(interface);
580af866496SDavid Daney 		break;
581af866496SDavid Daney 		/*
582af866496SDavid Daney 		 * Special loopback only ports. These are not the same
583af866496SDavid Daney 		 * as other ports in loopback mode
584af866496SDavid Daney 		 */
585af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
586af866496SDavid Daney 		result = __cvmx_helper_loop_enable(interface);
587af866496SDavid Daney 		break;
588af866496SDavid Daney 	}
589af866496SDavid Daney 	result |= __cvmx_helper_board_hardware_enable(interface);
590af866496SDavid Daney 	return result;
591af866496SDavid Daney }
592af866496SDavid Daney 
593af866496SDavid Daney /**
594af866496SDavid Daney  * Function to adjust internal IPD pointer alignments
595af866496SDavid Daney  *
596af866496SDavid Daney  * Returns 0 on success
597af866496SDavid Daney  *	   !0 on failure
598af866496SDavid Daney  */
599af866496SDavid Daney int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
600af866496SDavid Daney {
601af866496SDavid Daney #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
602af866496SDavid Daney      (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
603af866496SDavid Daney #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
604af866496SDavid Daney 	(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
605af866496SDavid Daney #define FIX_IPD_OUTPORT 0
606af866496SDavid Daney 	/* Ports 0-15 are interface 0, 16-31 are interface 1 */
607af866496SDavid Daney #define INTERFACE(port) (port >> 4)
608af866496SDavid Daney #define INDEX(port) (port & 0xf)
609af866496SDavid Daney 	uint64_t *p64;
610af866496SDavid Daney 	cvmx_pko_command_word0_t pko_command;
611af866496SDavid Daney 	union cvmx_buf_ptr g_buffer, pkt_buffer;
612af866496SDavid Daney 	cvmx_wqe_t *work;
613af866496SDavid Daney 	int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
614af866496SDavid Daney 	union cvmx_gmxx_prtx_cfg gmx_cfg;
615af866496SDavid Daney 	int retry_cnt;
616af866496SDavid Daney 	int retry_loop_cnt;
617af866496SDavid Daney 	int i;
618af866496SDavid Daney 	cvmx_helper_link_info_t link_info;
619af866496SDavid Daney 
620af866496SDavid Daney 	/* Save values for restore at end */
621af866496SDavid Daney 	uint64_t prtx_cfg =
622af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
623af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
624af866496SDavid Daney 	uint64_t tx_ptr_en =
625af866496SDavid Daney 	    cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
626af866496SDavid Daney 	uint64_t rx_ptr_en =
627af866496SDavid Daney 	    cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
628af866496SDavid Daney 	uint64_t rxx_jabber =
629af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_RXX_JABBER
630af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
631af866496SDavid Daney 	uint64_t frame_max =
632af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
633af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
634af866496SDavid Daney 
635af866496SDavid Daney 	/* Configure port to gig FDX as required for loopback mode */
636af866496SDavid Daney 	cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
637af866496SDavid Daney 
638af866496SDavid Daney 	/*
639af866496SDavid Daney 	 * Disable reception on all ports so if traffic is present it
640af866496SDavid Daney 	 * will not interfere.
641af866496SDavid Daney 	 */
642af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
643af866496SDavid Daney 
644af866496SDavid Daney 	cvmx_wait(100000000ull);
645af866496SDavid Daney 
646af866496SDavid Daney 	for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
647af866496SDavid Daney 		retry_cnt = 100000;
648af866496SDavid Daney 		wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
649af866496SDavid Daney 		pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
650af866496SDavid Daney 		wqe_pcnt &= 0x7f;
651af866496SDavid Daney 
652af866496SDavid Daney 		num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
653af866496SDavid Daney 
654af866496SDavid Daney 		if (num_segs == 0)
655af866496SDavid Daney 			goto fix_ipd_exit;
656af866496SDavid Daney 
657af866496SDavid Daney 		num_segs += 1;
658af866496SDavid Daney 
659af866496SDavid Daney 		size =
660af866496SDavid Daney 		    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
661af866496SDavid Daney 		    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
662af866496SDavid Daney 		    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
663af866496SDavid Daney 
664af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
665af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
666af866496SDavid Daney 		CVMX_SYNC;
667af866496SDavid Daney 
668af866496SDavid Daney 		g_buffer.u64 = 0;
669af866496SDavid Daney 		g_buffer.s.addr =
670af866496SDavid Daney 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
671af866496SDavid Daney 		if (g_buffer.s.addr == 0) {
672af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
673af866496SDavid Daney 				     "buffer allocation failure.\n");
674af866496SDavid Daney 			goto fix_ipd_exit;
675af866496SDavid Daney 		}
676af866496SDavid Daney 
677af866496SDavid Daney 		g_buffer.s.pool = CVMX_FPA_WQE_POOL;
678af866496SDavid Daney 		g_buffer.s.size = num_segs;
679af866496SDavid Daney 
680af866496SDavid Daney 		pkt_buffer.u64 = 0;
681af866496SDavid Daney 		pkt_buffer.s.addr =
682af866496SDavid Daney 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
683af866496SDavid Daney 		if (pkt_buffer.s.addr == 0) {
684af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
685af866496SDavid Daney 				     "buffer allocation failure.\n");
686af866496SDavid Daney 			goto fix_ipd_exit;
687af866496SDavid Daney 		}
688af866496SDavid Daney 		pkt_buffer.s.i = 1;
689af866496SDavid Daney 		pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
690af866496SDavid Daney 		pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
691af866496SDavid Daney 
692af866496SDavid Daney 		p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
693af866496SDavid Daney 		p64[0] = 0xffffffffffff0000ull;
694af866496SDavid Daney 		p64[1] = 0x08004510ull;
695af866496SDavid Daney 		p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
696af866496SDavid Daney 		p64[3] = 0x3a5fc0a81073c0a8ull;
697af866496SDavid Daney 
698af866496SDavid Daney 		for (i = 0; i < num_segs; i++) {
699af866496SDavid Daney 			if (i > 0)
700af866496SDavid Daney 				pkt_buffer.s.size =
701af866496SDavid Daney 				    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
702af866496SDavid Daney 
703af866496SDavid Daney 			if (i == (num_segs - 1))
704af866496SDavid Daney 				pkt_buffer.s.i = 0;
705af866496SDavid Daney 
706af866496SDavid Daney 			*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
707af866496SDavid Daney 						       8 * i) = pkt_buffer.u64;
708af866496SDavid Daney 		}
709af866496SDavid Daney 
710af866496SDavid Daney 		/* Build the PKO command */
711af866496SDavid Daney 		pko_command.u64 = 0;
712af866496SDavid Daney 		pko_command.s.segs = num_segs;
713af866496SDavid Daney 		pko_command.s.total_bytes = size;
714af866496SDavid Daney 		pko_command.s.dontfree = 0;
715af866496SDavid Daney 		pko_command.s.gather = 1;
716af866496SDavid Daney 
717af866496SDavid Daney 		gmx_cfg.u64 =
718af866496SDavid Daney 		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
719af866496SDavid Daney 				  (INDEX(FIX_IPD_OUTPORT),
720af866496SDavid Daney 				   INTERFACE(FIX_IPD_OUTPORT)));
721af866496SDavid Daney 		gmx_cfg.s.en = 1;
722af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_PRTX_CFG
723af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
724af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
725af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
726af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
727af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
728af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
729af866496SDavid Daney 
730af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_RXX_JABBER
731af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
732af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
733af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
734af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
735af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
736af866496SDavid Daney 
737af866496SDavid Daney 		cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
738af866496SDavid Daney 					     cvmx_pko_get_base_queue
739af866496SDavid Daney 					     (FIX_IPD_OUTPORT),
740af866496SDavid Daney 					     CVMX_PKO_LOCK_CMD_QUEUE);
741af866496SDavid Daney 		cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
742af866496SDavid Daney 					    cvmx_pko_get_base_queue
743af866496SDavid Daney 					    (FIX_IPD_OUTPORT), pko_command,
744af866496SDavid Daney 					    g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
745af866496SDavid Daney 
746af866496SDavid Daney 		CVMX_SYNC;
747af866496SDavid Daney 
748af866496SDavid Daney 		do {
749af866496SDavid Daney 			work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
750af866496SDavid Daney 			retry_cnt--;
751af866496SDavid Daney 		} while ((work == NULL) && (retry_cnt > 0));
752af866496SDavid Daney 
753af866496SDavid Daney 		if (!retry_cnt)
754af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
755af866496SDavid Daney 				     "get_work() timeout occurred.\n");
756af866496SDavid Daney 
757af866496SDavid Daney 		/* Free packet */
758af866496SDavid Daney 		if (work)
759af866496SDavid Daney 			cvmx_helper_free_packet_data(work);
760af866496SDavid Daney 	}
761af866496SDavid Daney 
762af866496SDavid Daney fix_ipd_exit:
763af866496SDavid Daney 
764af866496SDavid Daney 	/* Return CSR configs to saved values */
765af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_PRTX_CFG
766af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
767af866496SDavid Daney 		       prtx_cfg);
768af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
769af866496SDavid Daney 		       tx_ptr_en);
770af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
771af866496SDavid Daney 		       rx_ptr_en);
772af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_RXX_JABBER
773af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
774af866496SDavid Daney 		       rxx_jabber);
775af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
776af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
777af866496SDavid Daney 		       frame_max);
778af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
779af866496SDavid Daney 	/* Set link to down so autonegotiation will set it up again */
780af866496SDavid Daney 	link_info.u64 = 0;
781af866496SDavid Daney 	cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info);
782af866496SDavid Daney 
783af866496SDavid Daney 	/*
784af866496SDavid Daney 	 * Bring the link back up as autonegotiation is not done in
785af866496SDavid Daney 	 * user applications.
786af866496SDavid Daney 	 */
787af866496SDavid Daney 	cvmx_helper_link_autoconf(FIX_IPD_OUTPORT);
788af866496SDavid Daney 
789af866496SDavid Daney 	CVMX_SYNC;
790af866496SDavid Daney 	if (num_segs)
791af866496SDavid Daney 		cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
792af866496SDavid Daney 
793af866496SDavid Daney 	return !!num_segs;
794af866496SDavid Daney 
795af866496SDavid Daney }
796af866496SDavid Daney 
797af866496SDavid Daney /**
798af866496SDavid Daney  * Called after all internal packet IO paths are setup. This
799af866496SDavid Daney  * function enables IPD/PIP and begins packet input and output.
800af866496SDavid Daney  *
801af866496SDavid Daney  * Returns Zero on success, negative on failure
802af866496SDavid Daney  */
803af866496SDavid Daney int cvmx_helper_ipd_and_packet_input_enable(void)
804af866496SDavid Daney {
805af866496SDavid Daney 	int num_interfaces;
806af866496SDavid Daney 	int interface;
807af866496SDavid Daney 
808af866496SDavid Daney 	/* Enable IPD */
809af866496SDavid Daney 	cvmx_ipd_enable();
810af866496SDavid Daney 
811af866496SDavid Daney 	/*
812af866496SDavid Daney 	 * Time to enable hardware ports packet input and output. Note
813af866496SDavid Daney 	 * that at this point IPD/PIP must be fully functional and PKO
814af866496SDavid Daney 	 * must be disabled
815af866496SDavid Daney 	 */
816af866496SDavid Daney 	num_interfaces = cvmx_helper_get_number_of_interfaces();
817af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
818af866496SDavid Daney 		if (cvmx_helper_ports_on_interface(interface) > 0)
819af866496SDavid Daney 			__cvmx_helper_packet_hardware_enable(interface);
820af866496SDavid Daney 	}
821af866496SDavid Daney 
822af866496SDavid Daney 	/* Finally enable PKO now that the entire path is up and running */
823af866496SDavid Daney 	cvmx_pko_enable();
824af866496SDavid Daney 
825af866496SDavid Daney 	if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
826af866496SDavid Daney 	     || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
827af866496SDavid Daney 	    && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
828af866496SDavid Daney 		__cvmx_helper_errata_fix_ipd_ptr_alignment();
829af866496SDavid Daney 	return 0;
830af866496SDavid Daney }
831*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
832af866496SDavid Daney 
833af866496SDavid Daney /**
834af866496SDavid Daney  * Initialize the PIP, IPD, and PKO hardware to support
835af866496SDavid Daney  * simple priority based queues for the ethernet ports. Each
836af866496SDavid Daney  * port is configured with a number of priority queues based
837af866496SDavid Daney  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
838af866496SDavid Daney  * priority than the previous.
839af866496SDavid Daney  *
840af866496SDavid Daney  * Returns Zero on success, non-zero on failure
841af866496SDavid Daney  */
842af866496SDavid Daney int cvmx_helper_initialize_packet_io_global(void)
843af866496SDavid Daney {
844af866496SDavid Daney 	int result = 0;
845af866496SDavid Daney 	int interface;
846af866496SDavid Daney 	union cvmx_l2c_cfg l2c_cfg;
847af866496SDavid Daney 	union cvmx_smix_en smix_en;
848af866496SDavid Daney 	const int num_interfaces = cvmx_helper_get_number_of_interfaces();
849af866496SDavid Daney 
850af866496SDavid Daney 	/*
851af866496SDavid Daney 	 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
852af866496SDavid Daney 	 * be disabled.
853af866496SDavid Daney 	 */
854af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
855af866496SDavid Daney 		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
856af866496SDavid Daney 
857af866496SDavid Daney 	/*
858af866496SDavid Daney 	 * Tell L2 to give the IOB statically higher priority compared
859af866496SDavid Daney 	 * to the cores. This avoids conditions where IO blocks might
860af866496SDavid Daney 	 * be starved under very high L2 loads.
861af866496SDavid Daney 	 */
862af866496SDavid Daney 	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
863af866496SDavid Daney 	l2c_cfg.s.lrf_arb_mode = 0;
864af866496SDavid Daney 	l2c_cfg.s.rfb_arb_mode = 0;
865af866496SDavid Daney 	cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
866af866496SDavid Daney 
867af866496SDavid Daney 	/* Make sure SMI/MDIO is enabled so we can query PHYs */
868af866496SDavid Daney 	smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
869af866496SDavid Daney 	if (!smix_en.s.en) {
870af866496SDavid Daney 		smix_en.s.en = 1;
871af866496SDavid Daney 		cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
872af866496SDavid Daney 	}
873af866496SDavid Daney 
874af866496SDavid Daney 	/* Newer chips actually have two SMI/MDIO interfaces */
875af866496SDavid Daney 	if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
876af866496SDavid Daney 	    !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
877af866496SDavid Daney 	    !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
878af866496SDavid Daney 		smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
879af866496SDavid Daney 		if (!smix_en.s.en) {
880af866496SDavid Daney 			smix_en.s.en = 1;
881af866496SDavid Daney 			cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
882af866496SDavid Daney 		}
883af866496SDavid Daney 	}
884af866496SDavid Daney 
885af866496SDavid Daney 	cvmx_pko_initialize_global();
886af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
887af866496SDavid Daney 		result |= cvmx_helper_interface_probe(interface);
888af866496SDavid Daney 		if (cvmx_helper_ports_on_interface(interface) > 0)
889af866496SDavid Daney 			cvmx_dprintf("Interface %d has %d ports (%s)\n",
890af866496SDavid Daney 				     interface,
891af866496SDavid Daney 				     cvmx_helper_ports_on_interface(interface),
892af866496SDavid Daney 				     cvmx_helper_interface_mode_to_string
893af866496SDavid Daney 				     (cvmx_helper_interface_get_mode
894af866496SDavid Daney 				      (interface)));
895af866496SDavid Daney 		result |= __cvmx_helper_interface_setup_ipd(interface);
896af866496SDavid Daney 		result |= __cvmx_helper_interface_setup_pko(interface);
897af866496SDavid Daney 	}
898af866496SDavid Daney 
899af866496SDavid Daney 	result |= __cvmx_helper_global_setup_ipd();
900af866496SDavid Daney 	result |= __cvmx_helper_global_setup_pko();
901af866496SDavid Daney 
902af866496SDavid Daney 	/* Enable any flow control and backpressure */
903af866496SDavid Daney 	result |= __cvmx_helper_global_setup_backpressure();
904af866496SDavid Daney 
905af866496SDavid Daney #if CVMX_HELPER_ENABLE_IPD
906af866496SDavid Daney 	result |= cvmx_helper_ipd_and_packet_input_enable();
907af866496SDavid Daney #endif
908af866496SDavid Daney 	return result;
909af866496SDavid Daney }
910*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
911af866496SDavid Daney 
912af866496SDavid Daney /**
913af866496SDavid Daney  * Does core local initialization for packet io
914af866496SDavid Daney  *
915af866496SDavid Daney  * Returns Zero on success, non-zero on failure
916af866496SDavid Daney  */
917af866496SDavid Daney int cvmx_helper_initialize_packet_io_local(void)
918af866496SDavid Daney {
919af866496SDavid Daney 	return cvmx_pko_initialize_local();
920af866496SDavid Daney }
921af866496SDavid Daney 
922af866496SDavid Daney /**
923af866496SDavid Daney  * Auto configure an IPD/PKO port link state and speed. This
924af866496SDavid Daney  * function basically does the equivalent of:
925af866496SDavid Daney  * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
926af866496SDavid Daney  *
927af866496SDavid Daney  * @ipd_port: IPD/PKO port to auto configure
928af866496SDavid Daney  *
929af866496SDavid Daney  * Returns Link state after configure
930af866496SDavid Daney  */
931af866496SDavid Daney cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
932af866496SDavid Daney {
933af866496SDavid Daney 	cvmx_helper_link_info_t link_info;
934af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
935af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
936af866496SDavid Daney 
937af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface)) {
938af866496SDavid Daney 		link_info.u64 = 0;
939af866496SDavid Daney 		return link_info;
940af866496SDavid Daney 	}
941af866496SDavid Daney 
942af866496SDavid Daney 	link_info = cvmx_helper_link_get(ipd_port);
943af866496SDavid Daney 	if (link_info.u64 == port_link_info[ipd_port].u64)
944af866496SDavid Daney 		return link_info;
945af866496SDavid Daney 
946af866496SDavid Daney 	/* If we fail to set the link speed, port_link_info will not change */
947af866496SDavid Daney 	cvmx_helper_link_set(ipd_port, link_info);
948af866496SDavid Daney 
949af866496SDavid Daney 	/*
950af866496SDavid Daney 	 * port_link_info should be the current value, which will be
951af866496SDavid Daney 	 * different than expect if cvmx_helper_link_set() failed.
952af866496SDavid Daney 	 */
953af866496SDavid Daney 	return port_link_info[ipd_port];
954af866496SDavid Daney }
955*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_link_autoconf);
956af866496SDavid Daney 
957af866496SDavid Daney /**
958af866496SDavid Daney  * Return the link state of an IPD/PKO port as returned by
959af866496SDavid Daney  * auto negotiation. The result of this function may not match
960af866496SDavid Daney  * Octeon's link config if auto negotiation has changed since
961af866496SDavid Daney  * the last call to cvmx_helper_link_set().
962af866496SDavid Daney  *
963af866496SDavid Daney  * @ipd_port: IPD/PKO port to query
964af866496SDavid Daney  *
965af866496SDavid Daney  * Returns Link state
966af866496SDavid Daney  */
967af866496SDavid Daney cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
968af866496SDavid Daney {
969af866496SDavid Daney 	cvmx_helper_link_info_t result;
970af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
971af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
972af866496SDavid Daney 
973af866496SDavid Daney 	/* The default result will be a down link unless the code below
974af866496SDavid Daney 	   changes it */
975af866496SDavid Daney 	result.u64 = 0;
976af866496SDavid Daney 
977af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface))
978af866496SDavid Daney 		return result;
979af866496SDavid Daney 
980af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
981af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
982af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
983af866496SDavid Daney 		/* Network links are not supported */
984af866496SDavid Daney 		break;
985af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
986af866496SDavid Daney 		result = __cvmx_helper_xaui_link_get(ipd_port);
987af866496SDavid Daney 		break;
988af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
989af866496SDavid Daney 		if (index == 0)
990af866496SDavid Daney 			result = __cvmx_helper_rgmii_link_get(ipd_port);
991af866496SDavid Daney 		else {
992af866496SDavid Daney 			result.s.full_duplex = 1;
993af866496SDavid Daney 			result.s.link_up = 1;
994af866496SDavid Daney 			result.s.speed = 1000;
995af866496SDavid Daney 		}
996af866496SDavid Daney 		break;
997af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
998af866496SDavid Daney 		result = __cvmx_helper_rgmii_link_get(ipd_port);
999af866496SDavid Daney 		break;
1000af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1001af866496SDavid Daney 		result = __cvmx_helper_spi_link_get(ipd_port);
1002af866496SDavid Daney 		break;
1003af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1004af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1005af866496SDavid Daney 		result = __cvmx_helper_sgmii_link_get(ipd_port);
1006af866496SDavid Daney 		break;
1007af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1008af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1009af866496SDavid Daney 		/* Network links are not supported */
1010af866496SDavid Daney 		break;
1011af866496SDavid Daney 	}
1012af866496SDavid Daney 	return result;
1013af866496SDavid Daney }
1014*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1015af866496SDavid Daney 
1016af866496SDavid Daney /**
1017af866496SDavid Daney  * Configure an IPD/PKO port for the specified link state. This
1018af866496SDavid Daney  * function does not influence auto negotiation at the PHY level.
1019af866496SDavid Daney  * The passed link state must always match the link state returned
1020af866496SDavid Daney  * by cvmx_helper_link_get(). It is normally best to use
1021af866496SDavid Daney  * cvmx_helper_link_autoconf() instead.
1022af866496SDavid Daney  *
1023af866496SDavid Daney  * @ipd_port:  IPD/PKO port to configure
1024af866496SDavid Daney  * @link_info: The new link state
1025af866496SDavid Daney  *
1026af866496SDavid Daney  * Returns Zero on success, negative on failure
1027af866496SDavid Daney  */
1028af866496SDavid Daney int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1029af866496SDavid Daney {
1030af866496SDavid Daney 	int result = -1;
1031af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
1032af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1033af866496SDavid Daney 
1034af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface))
1035af866496SDavid Daney 		return -1;
1036af866496SDavid Daney 
1037af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
1038af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1039af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1040af866496SDavid Daney 		break;
1041af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1042af866496SDavid Daney 		result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1043af866496SDavid Daney 		break;
1044af866496SDavid Daney 		/*
1045af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
1046af866496SDavid Daney 		 * functions refer to these ports as RGMII.
1047af866496SDavid Daney 		 */
1048af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1049af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1050af866496SDavid Daney 		result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1051af866496SDavid Daney 		break;
1052af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1053af866496SDavid Daney 		result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1054af866496SDavid Daney 		break;
1055af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1056af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1057af866496SDavid Daney 		result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1058af866496SDavid Daney 		break;
1059af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1060af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1061af866496SDavid Daney 		break;
1062af866496SDavid Daney 	}
1063af866496SDavid Daney 	/* Set the port_link_info here so that the link status is updated
1064af866496SDavid Daney 	   no matter how cvmx_helper_link_set is called. We don't change
1065af866496SDavid Daney 	   the value if link_set failed */
1066af866496SDavid Daney 	if (result == 0)
1067af866496SDavid Daney 		port_link_info[ipd_port].u64 = link_info.u64;
1068af866496SDavid Daney 	return result;
1069af866496SDavid Daney }
1070*ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1071af866496SDavid Daney 
1072af866496SDavid Daney /**
1073af866496SDavid Daney  * Configure a port for internal and/or external loopback. Internal loopback
1074af866496SDavid Daney  * causes packets sent by the port to be received by Octeon. External loopback
1075af866496SDavid Daney  * causes packets received from the wire to sent out again.
1076af866496SDavid Daney  *
1077af866496SDavid Daney  * @ipd_port: IPD/PKO port to loopback.
1078af866496SDavid Daney  * @enable_internal:
1079af866496SDavid Daney  *		   Non zero if you want internal loopback
1080af866496SDavid Daney  * @enable_external:
1081af866496SDavid Daney  *		   Non zero if you want external loopback
1082af866496SDavid Daney  *
1083af866496SDavid Daney  * Returns Zero on success, negative on failure.
1084af866496SDavid Daney  */
1085af866496SDavid Daney int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1086af866496SDavid Daney 				   int enable_external)
1087af866496SDavid Daney {
1088af866496SDavid Daney 	int result = -1;
1089af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
1090af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1091af866496SDavid Daney 
1092af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface))
1093af866496SDavid Daney 		return -1;
1094af866496SDavid Daney 
1095af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
1096af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1097af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1098af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1099af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1100af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1101af866496SDavid Daney 		break;
1102af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1103af866496SDavid Daney 		result =
1104af866496SDavid Daney 		    __cvmx_helper_xaui_configure_loopback(ipd_port,
1105af866496SDavid Daney 							  enable_internal,
1106af866496SDavid Daney 							  enable_external);
1107af866496SDavid Daney 		break;
1108af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1109af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1110af866496SDavid Daney 		result =
1111af866496SDavid Daney 		    __cvmx_helper_rgmii_configure_loopback(ipd_port,
1112af866496SDavid Daney 							   enable_internal,
1113af866496SDavid Daney 							   enable_external);
1114af866496SDavid Daney 		break;
1115af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1116af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1117af866496SDavid Daney 		result =
1118af866496SDavid Daney 		    __cvmx_helper_sgmii_configure_loopback(ipd_port,
1119af866496SDavid Daney 							   enable_internal,
1120af866496SDavid Daney 							   enable_external);
1121af866496SDavid Daney 		break;
1122af866496SDavid Daney 	}
1123af866496SDavid Daney 	return result;
1124af866496SDavid Daney }
1125