xref: /linux/arch/mips/cavium-octeon/executive/cvmx-helper.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
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  */
332c0756d3SAaro Koskinen #include <linux/bug.h>
34af866496SDavid Daney #include <asm/octeon/octeon.h>
35af866496SDavid Daney 
36af866496SDavid Daney #include <asm/octeon/cvmx-config.h>
37af866496SDavid Daney 
38af866496SDavid Daney #include <asm/octeon/cvmx-fpa.h>
39af866496SDavid Daney #include <asm/octeon/cvmx-pip.h>
40af866496SDavid Daney #include <asm/octeon/cvmx-pko.h>
41af866496SDavid Daney #include <asm/octeon/cvmx-ipd.h>
42af866496SDavid Daney #include <asm/octeon/cvmx-spi.h>
43af866496SDavid Daney #include <asm/octeon/cvmx-helper.h>
44af866496SDavid Daney #include <asm/octeon/cvmx-helper-board.h>
45af866496SDavid Daney 
46af866496SDavid Daney #include <asm/octeon/cvmx-pip-defs.h>
47af866496SDavid Daney #include <asm/octeon/cvmx-asxx-defs.h>
48af866496SDavid Daney 
49af866496SDavid Daney /* Port count per interface */
50c0fae7e2SAaro Koskinen static int interface_port_count[9];
51af866496SDavid Daney 
52af866496SDavid Daney /**
53af866496SDavid Daney  * Return the number of interfaces the chip has. Each interface
54af866496SDavid Daney  * may have multiple ports. Most chips support two interfaces,
55af866496SDavid Daney  * but the CNX0XX and CNX1XX are exceptions. These only support
56af866496SDavid Daney  * one interface.
57af866496SDavid Daney  *
58af866496SDavid Daney  * Returns Number of interfaces on chip
59af866496SDavid Daney  */
cvmx_helper_get_number_of_interfaces(void)60af866496SDavid Daney int cvmx_helper_get_number_of_interfaces(void)
61af866496SDavid Daney {
622c8c3f02SJanne Huttunen 	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
632c8c3f02SJanne Huttunen 		return 9;
64aa88b706SStijn Tintel 	if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
65aa88b706SStijn Tintel 		if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
66aa88b706SStijn Tintel 			return 7;
67aa88b706SStijn Tintel 		else
68aa88b706SStijn Tintel 			return 8;
69aa88b706SStijn Tintel 	}
70af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
71af866496SDavid Daney 		return 4;
72885872b7SZubair Lutfullah Kakakhel 	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
73885872b7SZubair Lutfullah Kakakhel 		return 5;
74af866496SDavid Daney 	else
75af866496SDavid Daney 		return 3;
76af866496SDavid Daney }
77ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
78af866496SDavid Daney 
79af866496SDavid Daney /**
80af866496SDavid Daney  * Return the number of ports on an interface. Depending on the
81af866496SDavid Daney  * chip and configuration, this can be 1-16. A value of 0
82af866496SDavid Daney  * specifies that the interface doesn't exist or isn't usable.
83af866496SDavid Daney  *
84af866496SDavid Daney  * @interface: Interface to get the port count for
85af866496SDavid Daney  *
86af866496SDavid Daney  * Returns Number of ports on interface. Can be Zero.
87af866496SDavid Daney  */
cvmx_helper_ports_on_interface(int interface)88af866496SDavid Daney int cvmx_helper_ports_on_interface(int interface)
89af866496SDavid Daney {
90af866496SDavid Daney 	return interface_port_count[interface];
91af866496SDavid Daney }
92ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
93af866496SDavid Daney 
94af866496SDavid Daney /**
95d8ce7593SAlex Smith  * @INTERNAL
96d8ce7593SAlex Smith  * Return interface mode for CN68xx.
97d8ce7593SAlex Smith  */
__cvmx_get_mode_cn68xx(int interface)98d8ce7593SAlex Smith static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
99d8ce7593SAlex Smith {
100d8ce7593SAlex Smith 	union cvmx_mio_qlmx_cfg qlm_cfg;
101d8ce7593SAlex Smith 	switch (interface) {
102d8ce7593SAlex Smith 	case 0:
103d8ce7593SAlex Smith 		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
104d8ce7593SAlex Smith 		/* QLM is disabled when QLM SPD is 15. */
105d8ce7593SAlex Smith 		if (qlm_cfg.s.qlm_spd == 15)
106d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
107d8ce7593SAlex Smith 
108d8ce7593SAlex Smith 		if (qlm_cfg.s.qlm_cfg == 2)
109d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
110d8ce7593SAlex Smith 		else if (qlm_cfg.s.qlm_cfg == 3)
111d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
112d8ce7593SAlex Smith 		else
113d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
114d8ce7593SAlex Smith 	case 2:
115d8ce7593SAlex Smith 	case 3:
116d8ce7593SAlex Smith 	case 4:
117d8ce7593SAlex Smith 		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
118d8ce7593SAlex Smith 		/* QLM is disabled when QLM SPD is 15. */
119d8ce7593SAlex Smith 		if (qlm_cfg.s.qlm_spd == 15)
120d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
121d8ce7593SAlex Smith 
122d8ce7593SAlex Smith 		if (qlm_cfg.s.qlm_cfg == 2)
123d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
124d8ce7593SAlex Smith 		else if (qlm_cfg.s.qlm_cfg == 3)
125d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
126d8ce7593SAlex Smith 		else
127d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
128d8ce7593SAlex Smith 	case 7:
129d8ce7593SAlex Smith 		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
130d8ce7593SAlex Smith 		/* QLM is disabled when QLM SPD is 15. */
131d8ce7593SAlex Smith 		if (qlm_cfg.s.qlm_spd == 15) {
132d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
133d8ce7593SAlex Smith 		} else if (qlm_cfg.s.qlm_cfg != 0) {
134d8ce7593SAlex Smith 			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
135d8ce7593SAlex Smith 			if (qlm_cfg.s.qlm_cfg != 0)
136d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
137d8ce7593SAlex Smith 		}
138d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_NPI;
139d8ce7593SAlex Smith 	case 8:
140d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_LOOP;
141d8ce7593SAlex Smith 	default:
142d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
143d8ce7593SAlex Smith 	}
144d8ce7593SAlex Smith }
145d8ce7593SAlex Smith 
146d8ce7593SAlex Smith /**
147d8ce7593SAlex Smith  * @INTERNAL
148d8ce7593SAlex Smith  * Return interface mode for an Octeon II
149d8ce7593SAlex Smith  */
__cvmx_get_mode_octeon2(int interface)150d8ce7593SAlex Smith static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
151d8ce7593SAlex Smith {
152d8ce7593SAlex Smith 	union cvmx_gmxx_inf_mode mode;
153d8ce7593SAlex Smith 
154d8ce7593SAlex Smith 	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
155d8ce7593SAlex Smith 		return __cvmx_get_mode_cn68xx(interface);
156d8ce7593SAlex Smith 
157d8ce7593SAlex Smith 	if (interface == 2)
158d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_NPI;
159d8ce7593SAlex Smith 
160d8ce7593SAlex Smith 	if (interface == 3)
161d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_LOOP;
162d8ce7593SAlex Smith 
163d8ce7593SAlex Smith 	/* Only present in CN63XX & CN66XX Octeon model */
164d8ce7593SAlex Smith 	if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
165d8ce7593SAlex Smith 	     (interface == 4 || interface == 5)) ||
166d8ce7593SAlex Smith 	    (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
167d8ce7593SAlex Smith 	     interface >= 4 && interface <= 7)) {
168d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
169d8ce7593SAlex Smith 	}
170d8ce7593SAlex Smith 
171d8ce7593SAlex Smith 	if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
172d8ce7593SAlex Smith 		union cvmx_mio_qlmx_cfg mio_qlm_cfg;
173d8ce7593SAlex Smith 
174d8ce7593SAlex Smith 		/* QLM2 is SGMII0 and QLM1 is SGMII1 */
175d8ce7593SAlex Smith 		if (interface == 0)
176d8ce7593SAlex Smith 			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
177d8ce7593SAlex Smith 		else if (interface == 1)
178d8ce7593SAlex Smith 			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
179d8ce7593SAlex Smith 		else
180d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
181d8ce7593SAlex Smith 
182d8ce7593SAlex Smith 		if (mio_qlm_cfg.s.qlm_spd == 15)
183d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
184d8ce7593SAlex Smith 
185d8ce7593SAlex Smith 		if (mio_qlm_cfg.s.qlm_cfg == 9)
186d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
187d8ce7593SAlex Smith 		else if (mio_qlm_cfg.s.qlm_cfg == 11)
188d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
189d8ce7593SAlex Smith 		else
190d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
191d8ce7593SAlex Smith 	} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
192d8ce7593SAlex Smith 		union cvmx_mio_qlmx_cfg qlm_cfg;
193d8ce7593SAlex Smith 
194d8ce7593SAlex Smith 		if (interface == 0) {
195d8ce7593SAlex Smith 			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
196d8ce7593SAlex Smith 			if (qlm_cfg.s.qlm_cfg == 2)
197d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_SGMII;
198d8ce7593SAlex Smith 			else if (qlm_cfg.s.qlm_cfg == 3)
199d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_XAUI;
200d8ce7593SAlex Smith 			else
201d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
202d8ce7593SAlex Smith 		} else if (interface == 1) {
203d8ce7593SAlex Smith 			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
204d8ce7593SAlex Smith 			if (qlm_cfg.s.qlm_cfg == 2)
205d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_SGMII;
206d8ce7593SAlex Smith 			else if (qlm_cfg.s.qlm_cfg == 3)
207d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_XAUI;
208d8ce7593SAlex Smith 			else
209d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
210d8ce7593SAlex Smith 		}
211d8ce7593SAlex Smith 	} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
212d8ce7593SAlex Smith 		if (interface == 0) {
213d8ce7593SAlex Smith 			union cvmx_mio_qlmx_cfg qlm_cfg;
214d8ce7593SAlex Smith 			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
215d8ce7593SAlex Smith 			if (qlm_cfg.s.qlm_cfg == 2)
216d8ce7593SAlex Smith 				return CVMX_HELPER_INTERFACE_MODE_SGMII;
217d8ce7593SAlex Smith 		}
218d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
219d8ce7593SAlex Smith 	}
220d8ce7593SAlex Smith 
221d8ce7593SAlex Smith 	if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
222d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
223d8ce7593SAlex Smith 
224d8ce7593SAlex Smith 	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
225d8ce7593SAlex Smith 
226d8ce7593SAlex Smith 	if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
227036d0823SAaro Koskinen 		switch (mode.cn61xx.mode) {
228d8ce7593SAlex Smith 		case 0:
229d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
230d8ce7593SAlex Smith 		case 1:
231d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
232d8ce7593SAlex Smith 		default:
233d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
234d8ce7593SAlex Smith 		}
235d8ce7593SAlex Smith 	} else {
236d8ce7593SAlex Smith 		if (!mode.s.en)
237d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
238d8ce7593SAlex Smith 
239d8ce7593SAlex Smith 		if (mode.s.type)
240d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_GMII;
241d8ce7593SAlex Smith 		else
242d8ce7593SAlex Smith 			return CVMX_HELPER_INTERFACE_MODE_RGMII;
243d8ce7593SAlex Smith 	}
244d8ce7593SAlex Smith }
245d8ce7593SAlex Smith 
246d8ce7593SAlex Smith /**
247885872b7SZubair Lutfullah Kakakhel  * @INTERNAL
248885872b7SZubair Lutfullah Kakakhel  * Return interface mode for CN7XXX.
249885872b7SZubair Lutfullah Kakakhel  */
__cvmx_get_mode_cn7xxx(int interface)250885872b7SZubair Lutfullah Kakakhel static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
251885872b7SZubair Lutfullah Kakakhel {
252885872b7SZubair Lutfullah Kakakhel 	union cvmx_gmxx_inf_mode mode;
253885872b7SZubair Lutfullah Kakakhel 
254885872b7SZubair Lutfullah Kakakhel 	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
255885872b7SZubair Lutfullah Kakakhel 
256885872b7SZubair Lutfullah Kakakhel 	switch (interface) {
257885872b7SZubair Lutfullah Kakakhel 	case 0:
258885872b7SZubair Lutfullah Kakakhel 	case 1:
259885872b7SZubair Lutfullah Kakakhel 		switch (mode.cn68xx.mode) {
260885872b7SZubair Lutfullah Kakakhel 		case 0:
261885872b7SZubair Lutfullah Kakakhel 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
262885872b7SZubair Lutfullah Kakakhel 		case 1:
263885872b7SZubair Lutfullah Kakakhel 		case 2:
264885872b7SZubair Lutfullah Kakakhel 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
265885872b7SZubair Lutfullah Kakakhel 		case 3:
266885872b7SZubair Lutfullah Kakakhel 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
267885872b7SZubair Lutfullah Kakakhel 		default:
268885872b7SZubair Lutfullah Kakakhel 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
269885872b7SZubair Lutfullah Kakakhel 		}
270885872b7SZubair Lutfullah Kakakhel 	case 2:
271885872b7SZubair Lutfullah Kakakhel 		return CVMX_HELPER_INTERFACE_MODE_NPI;
272885872b7SZubair Lutfullah Kakakhel 	case 3:
273885872b7SZubair Lutfullah Kakakhel 		return CVMX_HELPER_INTERFACE_MODE_LOOP;
274885872b7SZubair Lutfullah Kakakhel 	case 4:
275edefae94SAaro Koskinen 		/* TODO: Implement support for AGL (RGMII). */
276edefae94SAaro Koskinen 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
277885872b7SZubair Lutfullah Kakakhel 	default:
278885872b7SZubair Lutfullah Kakakhel 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
279885872b7SZubair Lutfullah Kakakhel 	}
280885872b7SZubair Lutfullah Kakakhel }
281885872b7SZubair Lutfullah Kakakhel 
282885872b7SZubair Lutfullah Kakakhel /**
283af866496SDavid Daney  * Get the operating mode of an interface. Depending on the Octeon
284af866496SDavid Daney  * chip and configuration, this function returns an enumeration
285af866496SDavid Daney  * of the type of packet I/O supported by an interface.
286af866496SDavid Daney  *
287af866496SDavid Daney  * @interface: Interface to probe
288af866496SDavid Daney  *
289af866496SDavid Daney  * Returns Mode of the interface. Unknown or unsupported interfaces return
290af866496SDavid Daney  *	   DISABLED.
291af866496SDavid Daney  */
cvmx_helper_interface_get_mode(int interface)292af866496SDavid Daney cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
293af866496SDavid Daney {
294af866496SDavid Daney 	union cvmx_gmxx_inf_mode mode;
295d8ce7593SAlex Smith 
296d8ce7593SAlex Smith 	if (interface < 0 ||
297d8ce7593SAlex Smith 	    interface >= cvmx_helper_get_number_of_interfaces())
298d8ce7593SAlex Smith 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
299d8ce7593SAlex Smith 
300d8ce7593SAlex Smith 	/*
301885872b7SZubair Lutfullah Kakakhel 	 * OCTEON III models
302885872b7SZubair Lutfullah Kakakhel 	 */
303885872b7SZubair Lutfullah Kakakhel 	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
304885872b7SZubair Lutfullah Kakakhel 		return __cvmx_get_mode_cn7xxx(interface);
305885872b7SZubair Lutfullah Kakakhel 
306885872b7SZubair Lutfullah Kakakhel 	/*
307d8ce7593SAlex Smith 	 * Octeon II models
308d8ce7593SAlex Smith 	 */
309d8ce7593SAlex Smith 	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
310d8ce7593SAlex Smith 		return __cvmx_get_mode_octeon2(interface);
311d8ce7593SAlex Smith 
312d8ce7593SAlex Smith 	/*
313d8ce7593SAlex Smith 	 * Octeon and Octeon Plus models
314d8ce7593SAlex Smith 	 */
315af866496SDavid Daney 	if (interface == 2)
316af866496SDavid Daney 		return CVMX_HELPER_INTERFACE_MODE_NPI;
317af866496SDavid Daney 
318af866496SDavid Daney 	if (interface == 3) {
319af866496SDavid Daney 		if (OCTEON_IS_MODEL(OCTEON_CN56XX)
320af866496SDavid Daney 		    || OCTEON_IS_MODEL(OCTEON_CN52XX))
321af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_LOOP;
322af866496SDavid Daney 		else
323af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
324af866496SDavid Daney 	}
325af866496SDavid Daney 
326af866496SDavid Daney 	/* Interface 1 is always disabled on CN31XX and CN30XX */
327af866496SDavid Daney 	if ((interface == 1)
328af866496SDavid Daney 	    && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
329af866496SDavid Daney 		|| OCTEON_IS_MODEL(OCTEON_CN50XX)
330af866496SDavid Daney 		|| OCTEON_IS_MODEL(OCTEON_CN52XX)))
331af866496SDavid Daney 		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
332af866496SDavid Daney 
333af866496SDavid Daney 	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
334af866496SDavid Daney 
335af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
336036d0823SAaro Koskinen 		switch (mode.cn52xx.mode) {
337af866496SDavid Daney 		case 0:
338af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
339af866496SDavid Daney 		case 1:
340af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_XAUI;
341af866496SDavid Daney 		case 2:
342af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_SGMII;
343af866496SDavid Daney 		case 3:
344af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_PICMG;
345af866496SDavid Daney 		default:
346af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
347af866496SDavid Daney 		}
348af866496SDavid Daney 	} else {
349af866496SDavid Daney 		if (!mode.s.en)
350af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
351af866496SDavid Daney 
352af866496SDavid Daney 		if (mode.s.type) {
353af866496SDavid Daney 			if (OCTEON_IS_MODEL(OCTEON_CN38XX)
354af866496SDavid Daney 			    || OCTEON_IS_MODEL(OCTEON_CN58XX))
355af866496SDavid Daney 				return CVMX_HELPER_INTERFACE_MODE_SPI;
356af866496SDavid Daney 			else
357af866496SDavid Daney 				return CVMX_HELPER_INTERFACE_MODE_GMII;
358af866496SDavid Daney 		} else
359af866496SDavid Daney 			return CVMX_HELPER_INTERFACE_MODE_RGMII;
360af866496SDavid Daney 	}
361af866496SDavid Daney }
362ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
363af866496SDavid Daney 
364af866496SDavid Daney /**
365af866496SDavid Daney  * Configure the IPD/PIP tagging and QoS options for a specific
366af866496SDavid Daney  * port. This function determines the POW work queue entry
367af866496SDavid Daney  * contents for a port. The setup performed here is controlled by
368af866496SDavid Daney  * the defines in executive-config.h.
369af866496SDavid Daney  *
370af866496SDavid Daney  * @ipd_port: Port to configure. This follows the IPD numbering, not the
371af866496SDavid Daney  *		   per interface numbering
372af866496SDavid Daney  *
373af866496SDavid Daney  * Returns Zero on success, negative on failure
374af866496SDavid Daney  */
__cvmx_helper_port_setup_ipd(int ipd_port)375af866496SDavid Daney static int __cvmx_helper_port_setup_ipd(int ipd_port)
376af866496SDavid Daney {
377af866496SDavid Daney 	union cvmx_pip_prt_cfgx port_config;
378af866496SDavid Daney 	union cvmx_pip_prt_tagx tag_config;
379af866496SDavid Daney 
380af866496SDavid Daney 	port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
381af866496SDavid Daney 	tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
382af866496SDavid Daney 
383af866496SDavid Daney 	/* Have each port go to a different POW queue */
384af866496SDavid Daney 	port_config.s.qos = ipd_port & 0x7;
385af866496SDavid Daney 
386af866496SDavid Daney 	/* Process the headers and place the IP header in the work queue */
387af866496SDavid Daney 	port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
388af866496SDavid Daney 
389af866496SDavid Daney 	tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
390af866496SDavid Daney 	tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
391af866496SDavid Daney 	tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
392af866496SDavid Daney 	tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
393af866496SDavid Daney 	tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
394af866496SDavid Daney 	tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
395af866496SDavid Daney 	tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
396af866496SDavid Daney 	tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
397af866496SDavid Daney 	tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
398af866496SDavid Daney 	tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
399af866496SDavid Daney 	tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
400af866496SDavid Daney 	tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
401af866496SDavid Daney 	tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
402af866496SDavid Daney 	tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
403af866496SDavid Daney 	tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
404af866496SDavid Daney 	tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
405af866496SDavid Daney 	/* Put all packets in group 0. Other groups can be used by the app */
406af866496SDavid Daney 	tag_config.s.grp = 0;
407af866496SDavid Daney 
408af866496SDavid Daney 	cvmx_pip_config_port(ipd_port, port_config, tag_config);
409af866496SDavid Daney 
410af866496SDavid Daney 	return 0;
411af866496SDavid Daney }
412af866496SDavid Daney 
413af866496SDavid Daney /**
41437d3bfd9SDavid Daney  * This function sets the interface_port_count[interface] correctly,
41537d3bfd9SDavid Daney  * without modifying any hardware configuration.  Hardware setup of
41637d3bfd9SDavid Daney  * the ports will be performed later.
41737d3bfd9SDavid Daney  *
41837d3bfd9SDavid Daney  * @interface: Interface to probe
41937d3bfd9SDavid Daney  *
42037d3bfd9SDavid Daney  * Returns Zero on success, negative on failure
42137d3bfd9SDavid Daney  */
cvmx_helper_interface_enumerate(int interface)42237d3bfd9SDavid Daney int cvmx_helper_interface_enumerate(int interface)
42337d3bfd9SDavid Daney {
42437d3bfd9SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
42537d3bfd9SDavid Daney 		/* These types don't support ports to IPD/PKO */
42637d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
42737d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
42837d3bfd9SDavid Daney 		interface_port_count[interface] = 0;
42937d3bfd9SDavid Daney 		break;
43037d3bfd9SDavid Daney 		/* XAUI is a single high speed port */
43137d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
43237d3bfd9SDavid Daney 		interface_port_count[interface] =
43337d3bfd9SDavid Daney 		    __cvmx_helper_xaui_enumerate(interface);
43437d3bfd9SDavid Daney 		break;
43537d3bfd9SDavid Daney 		/*
43637d3bfd9SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
43737d3bfd9SDavid Daney 		 * functions refer to these ports as RGMII.
43837d3bfd9SDavid Daney 		 */
43937d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
44037d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
44137d3bfd9SDavid Daney 		interface_port_count[interface] =
44237d3bfd9SDavid Daney 		    __cvmx_helper_rgmii_enumerate(interface);
44337d3bfd9SDavid Daney 		break;
44437d3bfd9SDavid Daney 		/*
44537d3bfd9SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
44637d3bfd9SDavid Daney 		 * the other end.
44737d3bfd9SDavid Daney 		 */
44837d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
44937d3bfd9SDavid Daney 		interface_port_count[interface] =
45037d3bfd9SDavid Daney 		    __cvmx_helper_spi_enumerate(interface);
45137d3bfd9SDavid Daney 		break;
45237d3bfd9SDavid Daney 		/*
45337d3bfd9SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
45437d3bfd9SDavid Daney 		 * hooked up.
45537d3bfd9SDavid Daney 		 */
45637d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
45737d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
45837d3bfd9SDavid Daney 		interface_port_count[interface] =
45937d3bfd9SDavid Daney 		    __cvmx_helper_sgmii_enumerate(interface);
46037d3bfd9SDavid Daney 		break;
46137d3bfd9SDavid Daney 		/* PCI target Network Packet Interface */
46237d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
46337d3bfd9SDavid Daney 		interface_port_count[interface] =
46437d3bfd9SDavid Daney 		    __cvmx_helper_npi_enumerate(interface);
46537d3bfd9SDavid Daney 		break;
46637d3bfd9SDavid Daney 		/*
46737d3bfd9SDavid Daney 		 * Special loopback only ports. These are not the same
46837d3bfd9SDavid Daney 		 * as other ports in loopback mode.
46937d3bfd9SDavid Daney 		 */
47037d3bfd9SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
47137d3bfd9SDavid Daney 		interface_port_count[interface] =
47237d3bfd9SDavid Daney 		    __cvmx_helper_loop_enumerate(interface);
47337d3bfd9SDavid Daney 		break;
47437d3bfd9SDavid Daney 	}
47537d3bfd9SDavid Daney 
47637d3bfd9SDavid Daney 	interface_port_count[interface] =
47737d3bfd9SDavid Daney 	    __cvmx_helper_board_interface_probe(interface,
47837d3bfd9SDavid Daney 						interface_port_count
47937d3bfd9SDavid Daney 						[interface]);
48037d3bfd9SDavid Daney 
48137d3bfd9SDavid Daney 	/* Make sure all global variables propagate to other cores */
48237d3bfd9SDavid Daney 	CVMX_SYNCWS;
48337d3bfd9SDavid Daney 
48437d3bfd9SDavid Daney 	return 0;
48537d3bfd9SDavid Daney }
48637d3bfd9SDavid Daney 
48737d3bfd9SDavid Daney /**
488af866496SDavid Daney  * This function probes an interface to determine the actual
489af866496SDavid Daney  * number of hardware ports connected to it. It doesn't setup the
490af866496SDavid Daney  * ports or enable them. The main goal here is to set the global
491af866496SDavid Daney  * interface_port_count[interface] correctly. Hardware setup of the
492af866496SDavid Daney  * ports will be performed later.
493af866496SDavid Daney  *
494af866496SDavid Daney  * @interface: Interface to probe
495af866496SDavid Daney  *
496af866496SDavid Daney  * Returns Zero on success, negative on failure
497af866496SDavid Daney  */
cvmx_helper_interface_probe(int interface)498af866496SDavid Daney int cvmx_helper_interface_probe(int interface)
499af866496SDavid Daney {
50037d3bfd9SDavid Daney 	cvmx_helper_interface_enumerate(interface);
501af866496SDavid Daney 	/* At this stage in the game we don't want packets to be moving yet.
502af866496SDavid Daney 	   The following probe calls should perform hardware setup
503af866496SDavid Daney 	   needed to determine port counts. Receive must still be disabled */
504af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
505af866496SDavid Daney 		/* These types don't support ports to IPD/PKO */
506af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
507af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
508af866496SDavid Daney 		break;
509af866496SDavid Daney 		/* XAUI is a single high speed port */
510af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
511af866496SDavid Daney 		__cvmx_helper_xaui_probe(interface);
512af866496SDavid Daney 		break;
513af866496SDavid Daney 		/*
514af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
515af866496SDavid Daney 		 * functions refer to these ports as RGMII.
516af866496SDavid Daney 		 */
517af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
518af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
519af866496SDavid Daney 		__cvmx_helper_rgmii_probe(interface);
520af866496SDavid Daney 		break;
521af866496SDavid Daney 		/*
522af866496SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
523af866496SDavid Daney 		 * the other end.
524af866496SDavid Daney 		 */
525af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
526af866496SDavid Daney 		__cvmx_helper_spi_probe(interface);
527af866496SDavid Daney 		break;
528af866496SDavid Daney 		/*
529af866496SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
530af866496SDavid Daney 		 * hooked up.
531af866496SDavid Daney 		 */
532af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
533af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
534af866496SDavid Daney 		__cvmx_helper_sgmii_probe(interface);
535af866496SDavid Daney 		break;
536af866496SDavid Daney 		/* PCI target Network Packet Interface */
537af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
538af866496SDavid Daney 		__cvmx_helper_npi_probe(interface);
539af866496SDavid Daney 		break;
540af866496SDavid Daney 		/*
541af866496SDavid Daney 		 * Special loopback only ports. These are not the same
542af866496SDavid Daney 		 * as other ports in loopback mode.
543af866496SDavid Daney 		 */
544af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
545af866496SDavid Daney 		__cvmx_helper_loop_probe(interface);
546af866496SDavid Daney 		break;
547af866496SDavid Daney 	}
548af866496SDavid Daney 
549af866496SDavid Daney 	/* Make sure all global variables propagate to other cores */
550af866496SDavid Daney 	CVMX_SYNCWS;
551af866496SDavid Daney 
552af866496SDavid Daney 	return 0;
553af866496SDavid Daney }
554af866496SDavid Daney 
555af866496SDavid Daney /**
556af866496SDavid Daney  * Setup the IPD/PIP for the ports on an interface. Packet
557af866496SDavid Daney  * classification and tagging are set for every port on the
558af866496SDavid Daney  * interface. The number of ports on the interface must already
559af866496SDavid Daney  * have been probed.
560af866496SDavid Daney  *
561af866496SDavid Daney  * @interface: Interface to setup IPD/PIP for
562af866496SDavid Daney  *
563af866496SDavid Daney  * Returns Zero on success, negative on failure
564af866496SDavid Daney  */
__cvmx_helper_interface_setup_ipd(int interface)565af866496SDavid Daney static int __cvmx_helper_interface_setup_ipd(int interface)
566af866496SDavid Daney {
567af866496SDavid Daney 	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
568af866496SDavid Daney 	int num_ports = interface_port_count[interface];
569af866496SDavid Daney 
570af866496SDavid Daney 	while (num_ports--) {
571af866496SDavid Daney 		__cvmx_helper_port_setup_ipd(ipd_port);
572af866496SDavid Daney 		ipd_port++;
573af866496SDavid Daney 	}
574af866496SDavid Daney 	return 0;
575af866496SDavid Daney }
576af866496SDavid Daney 
577af866496SDavid Daney /**
578af866496SDavid Daney  * Setup global setting for IPD/PIP not related to a specific
579af866496SDavid Daney  * interface or port. This must be called before IPD is enabled.
580af866496SDavid Daney  *
581af866496SDavid Daney  * Returns Zero on success, negative on failure.
582af866496SDavid Daney  */
__cvmx_helper_global_setup_ipd(void)583af866496SDavid Daney static int __cvmx_helper_global_setup_ipd(void)
584af866496SDavid Daney {
585af866496SDavid Daney 	/* Setup the global packet input options */
586af866496SDavid Daney 	cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
587af866496SDavid Daney 			CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
588af866496SDavid Daney 			CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
589af866496SDavid Daney 			/* The +8 is to account for the next ptr */
590af866496SDavid Daney 			(CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
591af866496SDavid Daney 			/* The +8 is to account for the next ptr */
592af866496SDavid Daney 			(CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
593af866496SDavid Daney 			CVMX_FPA_WQE_POOL,
594af866496SDavid Daney 			CVMX_IPD_OPC_MODE_STT,
595af866496SDavid Daney 			CVMX_HELPER_ENABLE_BACK_PRESSURE);
596af866496SDavid Daney 	return 0;
597af866496SDavid Daney }
598af866496SDavid Daney 
599af866496SDavid Daney /**
600af866496SDavid Daney  * Setup the PKO for the ports on an interface. The number of
601af866496SDavid Daney  * queues per port and the priority of each PKO output queue
602af866496SDavid Daney  * is set here. PKO must be disabled when this function is called.
603af866496SDavid Daney  *
604af866496SDavid Daney  * @interface: Interface to setup PKO for
605af866496SDavid Daney  *
606af866496SDavid Daney  * Returns Zero on success, negative on failure
607af866496SDavid Daney  */
__cvmx_helper_interface_setup_pko(int interface)608af866496SDavid Daney static int __cvmx_helper_interface_setup_pko(int interface)
609af866496SDavid Daney {
610af866496SDavid Daney 	/*
611af866496SDavid Daney 	 * Each packet output queue has an associated priority. The
612af866496SDavid Daney 	 * higher the priority, the more often it can send a packet. A
613af866496SDavid Daney 	 * priority of 8 means it can send in all 8 rounds of
614af866496SDavid Daney 	 * contention. We're going to make each queue one less than
615af866496SDavid Daney 	 * the last.  The vector of priorities has been extended to
616af866496SDavid Daney 	 * support CN5xxx CPUs, where up to 16 queues can be
617af866496SDavid Daney 	 * associated to a port.  To keep backward compatibility we
618af866496SDavid Daney 	 * don't change the initial 8 priorities and replicate them in
619af866496SDavid Daney 	 * the second half.  With per-core PKO queues (PKO lockless
620af866496SDavid Daney 	 * operation) all queues have the same priority.
621af866496SDavid Daney 	 */
622af866496SDavid Daney 	uint64_t priorities[16] =
623af866496SDavid Daney 	    { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
624af866496SDavid Daney 
625af866496SDavid Daney 	/*
626af866496SDavid Daney 	 * Setup the IPD/PIP and PKO for the ports discovered
627af866496SDavid Daney 	 * above. Here packet classification, tagging and output
628af866496SDavid Daney 	 * priorities are set.
629af866496SDavid Daney 	 */
630af866496SDavid Daney 	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
631af866496SDavid Daney 	int num_ports = interface_port_count[interface];
632af866496SDavid Daney 	while (num_ports--) {
633af866496SDavid Daney 		cvmx_pko_config_port(ipd_port,
634af866496SDavid Daney 				     cvmx_pko_get_base_queue_per_core(ipd_port,
635af866496SDavid Daney 								      0),
636af866496SDavid Daney 				     cvmx_pko_get_num_queues(ipd_port),
637af866496SDavid Daney 				     priorities);
638af866496SDavid Daney 		ipd_port++;
639af866496SDavid Daney 	}
640af866496SDavid Daney 	return 0;
641af866496SDavid Daney }
642af866496SDavid Daney 
643af866496SDavid Daney /**
644af866496SDavid Daney  * Setup global setting for PKO not related to a specific
645af866496SDavid Daney  * interface or port. This must be called before PKO is enabled.
646af866496SDavid Daney  *
647af866496SDavid Daney  * Returns Zero on success, negative on failure.
648af866496SDavid Daney  */
__cvmx_helper_global_setup_pko(void)649af866496SDavid Daney static int __cvmx_helper_global_setup_pko(void)
650af866496SDavid Daney {
651af866496SDavid Daney 	/*
652af866496SDavid Daney 	 * Disable tagwait FAU timeout. This needs to be done before
653af866496SDavid Daney 	 * anyone might start packet output using tags.
654af866496SDavid Daney 	 */
655af866496SDavid Daney 	union cvmx_iob_fau_timeout fau_to;
656af866496SDavid Daney 	fau_to.u64 = 0;
657af866496SDavid Daney 	fau_to.s.tout_val = 0xfff;
658af866496SDavid Daney 	fau_to.s.tout_enb = 0;
659af866496SDavid Daney 	cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
660b92084baSJanne Huttunen 
661b92084baSJanne Huttunen 	if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
662b92084baSJanne Huttunen 		union cvmx_pko_reg_min_pkt min_pkt;
663b92084baSJanne Huttunen 
664b92084baSJanne Huttunen 		min_pkt.u64 = 0;
665b92084baSJanne Huttunen 		min_pkt.s.size1 = 59;
666b92084baSJanne Huttunen 		min_pkt.s.size2 = 59;
667b92084baSJanne Huttunen 		min_pkt.s.size3 = 59;
668b92084baSJanne Huttunen 		min_pkt.s.size4 = 59;
669b92084baSJanne Huttunen 		min_pkt.s.size5 = 59;
670b92084baSJanne Huttunen 		min_pkt.s.size6 = 59;
671b92084baSJanne Huttunen 		min_pkt.s.size7 = 59;
672b92084baSJanne Huttunen 		cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
673b92084baSJanne Huttunen 	}
674b92084baSJanne Huttunen 
675af866496SDavid Daney 	return 0;
676af866496SDavid Daney }
677af866496SDavid Daney 
678af866496SDavid Daney /**
679af866496SDavid Daney  * Setup global backpressure setting.
680af866496SDavid Daney  *
681af866496SDavid Daney  * Returns Zero on success, negative on failure
682af866496SDavid Daney  */
__cvmx_helper_global_setup_backpressure(void)683af866496SDavid Daney static int __cvmx_helper_global_setup_backpressure(void)
684af866496SDavid Daney {
685af866496SDavid Daney #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
686af866496SDavid Daney 	/* Disable backpressure if configured to do so */
687af866496SDavid Daney 	/* Disable backpressure (pause frame) generation */
688af866496SDavid Daney 	int num_interfaces = cvmx_helper_get_number_of_interfaces();
689af866496SDavid Daney 	int interface;
690af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
691af866496SDavid Daney 		switch (cvmx_helper_interface_get_mode(interface)) {
692af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_DISABLED:
693af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_PCIE:
694af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_NPI:
695af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_LOOP:
696af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_XAUI:
697af866496SDavid Daney 			break;
698af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_RGMII:
699af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_GMII:
700af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_SPI:
701af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_SGMII:
702af866496SDavid Daney 		case CVMX_HELPER_INTERFACE_MODE_PICMG:
703af866496SDavid Daney 			cvmx_gmx_set_backpressure_override(interface, 0xf);
704af866496SDavid Daney 			break;
705af866496SDavid Daney 		}
706af866496SDavid Daney 	}
707af866496SDavid Daney #endif
708af866496SDavid Daney 
709af866496SDavid Daney 	return 0;
710af866496SDavid Daney }
711af866496SDavid Daney 
712af866496SDavid Daney /**
713af866496SDavid Daney  * Enable packet input/output from the hardware. This function is
714af866496SDavid Daney  * called after all internal setup is complete and IPD is enabled.
715af866496SDavid Daney  * After this function completes, packets will be accepted from the
716af866496SDavid Daney  * hardware ports. PKO should still be disabled to make sure packets
717af866496SDavid Daney  * aren't sent out partially setup hardware.
718af866496SDavid Daney  *
719af866496SDavid Daney  * @interface: Interface to enable
720af866496SDavid Daney  *
721af866496SDavid Daney  * Returns Zero on success, negative on failure
722af866496SDavid Daney  */
__cvmx_helper_packet_hardware_enable(int interface)723af866496SDavid Daney static int __cvmx_helper_packet_hardware_enable(int interface)
724af866496SDavid Daney {
725af866496SDavid Daney 	int result = 0;
726af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
727af866496SDavid Daney 		/* These types don't support ports to IPD/PKO */
728af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
729af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
730af866496SDavid Daney 		/* Nothing to do */
731af866496SDavid Daney 		break;
732af866496SDavid Daney 		/* XAUI is a single high speed port */
733af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
734af866496SDavid Daney 		result = __cvmx_helper_xaui_enable(interface);
735af866496SDavid Daney 		break;
736af866496SDavid Daney 		/*
737af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
738af866496SDavid Daney 		 * functions refer to these ports as RGMII
739af866496SDavid Daney 		 */
740af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
741af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
742af866496SDavid Daney 		result = __cvmx_helper_rgmii_enable(interface);
743af866496SDavid Daney 		break;
744af866496SDavid Daney 		/*
745af866496SDavid Daney 		 * SPI4 can have 1-16 ports depending on the device at
746af866496SDavid Daney 		 * the other end
747af866496SDavid Daney 		 */
748af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
749af866496SDavid Daney 		result = __cvmx_helper_spi_enable(interface);
750af866496SDavid Daney 		break;
751af866496SDavid Daney 		/*
752af866496SDavid Daney 		 * SGMII can have 1-4 ports depending on how many are
753af866496SDavid Daney 		 * hooked up
754af866496SDavid Daney 		 */
755af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
756af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
757af866496SDavid Daney 		result = __cvmx_helper_sgmii_enable(interface);
758af866496SDavid Daney 		break;
759af866496SDavid Daney 		/* PCI target Network Packet Interface */
760af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
761af866496SDavid Daney 		result = __cvmx_helper_npi_enable(interface);
762af866496SDavid Daney 		break;
763af866496SDavid Daney 		/*
764af866496SDavid Daney 		 * Special loopback only ports. These are not the same
765af866496SDavid Daney 		 * as other ports in loopback mode
766af866496SDavid Daney 		 */
767af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
768af866496SDavid Daney 		result = __cvmx_helper_loop_enable(interface);
769af866496SDavid Daney 		break;
770af866496SDavid Daney 	}
771af866496SDavid Daney 	return result;
772af866496SDavid Daney }
773af866496SDavid Daney 
774af866496SDavid Daney /**
775af866496SDavid Daney  * Function to adjust internal IPD pointer alignments
776af866496SDavid Daney  *
777af866496SDavid Daney  * Returns 0 on success
778af866496SDavid Daney  *	   !0 on failure
779af866496SDavid Daney  */
__cvmx_helper_errata_fix_ipd_ptr_alignment(void)780a3741102SAaro Koskinen static int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
781af866496SDavid Daney {
782af866496SDavid Daney #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
783af866496SDavid Daney      (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
784af866496SDavid Daney #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
785af866496SDavid Daney 	(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
786af866496SDavid Daney #define FIX_IPD_OUTPORT 0
787af866496SDavid Daney 	/* Ports 0-15 are interface 0, 16-31 are interface 1 */
788af866496SDavid Daney #define INTERFACE(port) (port >> 4)
789af866496SDavid Daney #define INDEX(port) (port & 0xf)
790af866496SDavid Daney 	uint64_t *p64;
7919da30353SChris Packham 	union cvmx_pko_command_word0 pko_command;
792af866496SDavid Daney 	union cvmx_buf_ptr g_buffer, pkt_buffer;
793f9546de4SChris Packham 	struct cvmx_wqe *work;
794af866496SDavid Daney 	int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
795af866496SDavid Daney 	union cvmx_gmxx_prtx_cfg gmx_cfg;
796af866496SDavid Daney 	int retry_cnt;
797af866496SDavid Daney 	int retry_loop_cnt;
798af866496SDavid Daney 	int i;
799af866496SDavid Daney 
800af866496SDavid Daney 	/* Save values for restore at end */
801af866496SDavid Daney 	uint64_t prtx_cfg =
802af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
803af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
804af866496SDavid Daney 	uint64_t tx_ptr_en =
805af866496SDavid Daney 	    cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
806af866496SDavid Daney 	uint64_t rx_ptr_en =
807af866496SDavid Daney 	    cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
808af866496SDavid Daney 	uint64_t rxx_jabber =
809af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_RXX_JABBER
810af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
811af866496SDavid Daney 	uint64_t frame_max =
812af866496SDavid Daney 	    cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
813af866496SDavid Daney 			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
814af866496SDavid Daney 
815af866496SDavid Daney 	/* Configure port to gig FDX as required for loopback mode */
816af866496SDavid Daney 	cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
817af866496SDavid Daney 
818af866496SDavid Daney 	/*
819af866496SDavid Daney 	 * Disable reception on all ports so if traffic is present it
820af866496SDavid Daney 	 * will not interfere.
821af866496SDavid Daney 	 */
822af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
823af866496SDavid Daney 
824edf188beSSteven J. Hill 	__delay(100000000ull);
825af866496SDavid Daney 
826af866496SDavid Daney 	for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
827af866496SDavid Daney 		retry_cnt = 100000;
828af866496SDavid Daney 		wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
829af866496SDavid Daney 		pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
830af866496SDavid Daney 		wqe_pcnt &= 0x7f;
831af866496SDavid Daney 
832af866496SDavid Daney 		num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
833af866496SDavid Daney 
834af866496SDavid Daney 		if (num_segs == 0)
835af866496SDavid Daney 			goto fix_ipd_exit;
836af866496SDavid Daney 
837af866496SDavid Daney 		num_segs += 1;
838af866496SDavid Daney 
839af866496SDavid Daney 		size =
840af866496SDavid Daney 		    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
841af866496SDavid Daney 		    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
842af866496SDavid Daney 		    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
843af866496SDavid Daney 
844af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
845af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
846af866496SDavid Daney 		CVMX_SYNC;
847af866496SDavid Daney 
848af866496SDavid Daney 		g_buffer.u64 = 0;
849af866496SDavid Daney 		g_buffer.s.addr =
850af866496SDavid Daney 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
851af866496SDavid Daney 		if (g_buffer.s.addr == 0) {
852af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
853af866496SDavid Daney 				     "buffer allocation failure.\n");
854af866496SDavid Daney 			goto fix_ipd_exit;
855af866496SDavid Daney 		}
856af866496SDavid Daney 
857af866496SDavid Daney 		g_buffer.s.pool = CVMX_FPA_WQE_POOL;
858af866496SDavid Daney 		g_buffer.s.size = num_segs;
859af866496SDavid Daney 
860af866496SDavid Daney 		pkt_buffer.u64 = 0;
861af866496SDavid Daney 		pkt_buffer.s.addr =
862af866496SDavid Daney 		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
863af866496SDavid Daney 		if (pkt_buffer.s.addr == 0) {
864af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
865af866496SDavid Daney 				     "buffer allocation failure.\n");
866af866496SDavid Daney 			goto fix_ipd_exit;
867af866496SDavid Daney 		}
868af866496SDavid Daney 		pkt_buffer.s.i = 1;
869af866496SDavid Daney 		pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
870af866496SDavid Daney 		pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
871af866496SDavid Daney 
872af866496SDavid Daney 		p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
873af866496SDavid Daney 		p64[0] = 0xffffffffffff0000ull;
874af866496SDavid Daney 		p64[1] = 0x08004510ull;
875af866496SDavid Daney 		p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
876af866496SDavid Daney 		p64[3] = 0x3a5fc0a81073c0a8ull;
877af866496SDavid Daney 
878af866496SDavid Daney 		for (i = 0; i < num_segs; i++) {
879af866496SDavid Daney 			if (i > 0)
880af866496SDavid Daney 				pkt_buffer.s.size =
881af866496SDavid Daney 				    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
882af866496SDavid Daney 
883af866496SDavid Daney 			if (i == (num_segs - 1))
884af866496SDavid Daney 				pkt_buffer.s.i = 0;
885af866496SDavid Daney 
886af866496SDavid Daney 			*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
887af866496SDavid Daney 						       8 * i) = pkt_buffer.u64;
888af866496SDavid Daney 		}
889af866496SDavid Daney 
890af866496SDavid Daney 		/* Build the PKO command */
891af866496SDavid Daney 		pko_command.u64 = 0;
892af866496SDavid Daney 		pko_command.s.segs = num_segs;
893af866496SDavid Daney 		pko_command.s.total_bytes = size;
894af866496SDavid Daney 		pko_command.s.dontfree = 0;
895af866496SDavid Daney 		pko_command.s.gather = 1;
896af866496SDavid Daney 
897af866496SDavid Daney 		gmx_cfg.u64 =
898af866496SDavid Daney 		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
899af866496SDavid Daney 				  (INDEX(FIX_IPD_OUTPORT),
900af866496SDavid Daney 				   INTERFACE(FIX_IPD_OUTPORT)));
901af866496SDavid Daney 		gmx_cfg.s.en = 1;
902af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_PRTX_CFG
903af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
904af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
905af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
906af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
907af866496SDavid Daney 		cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
908af866496SDavid Daney 			       1 << INDEX(FIX_IPD_OUTPORT));
909af866496SDavid Daney 
910af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_RXX_JABBER
911af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
912af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
913af866496SDavid Daney 		cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
914af866496SDavid Daney 			       (INDEX(FIX_IPD_OUTPORT),
915af866496SDavid Daney 				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
916af866496SDavid Daney 
917af866496SDavid Daney 		cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
918af866496SDavid Daney 					     cvmx_pko_get_base_queue
919af866496SDavid Daney 					     (FIX_IPD_OUTPORT),
920af866496SDavid Daney 					     CVMX_PKO_LOCK_CMD_QUEUE);
921af866496SDavid Daney 		cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
922af866496SDavid Daney 					    cvmx_pko_get_base_queue
923af866496SDavid Daney 					    (FIX_IPD_OUTPORT), pko_command,
924af866496SDavid Daney 					    g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
925af866496SDavid Daney 
926af866496SDavid Daney 		CVMX_SYNC;
927af866496SDavid Daney 
928af866496SDavid Daney 		do {
929af866496SDavid Daney 			work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
930af866496SDavid Daney 			retry_cnt--;
931af866496SDavid Daney 		} while ((work == NULL) && (retry_cnt > 0));
932af866496SDavid Daney 
933af866496SDavid Daney 		if (!retry_cnt)
934af866496SDavid Daney 			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
935af866496SDavid Daney 				     "get_work() timeout occurred.\n");
936af866496SDavid Daney 
937af866496SDavid Daney 		/* Free packet */
938af866496SDavid Daney 		if (work)
939af866496SDavid Daney 			cvmx_helper_free_packet_data(work);
940af866496SDavid Daney 	}
941af866496SDavid Daney 
942af866496SDavid Daney fix_ipd_exit:
943af866496SDavid Daney 
944af866496SDavid Daney 	/* Return CSR configs to saved values */
945af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_PRTX_CFG
946af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
947af866496SDavid Daney 		       prtx_cfg);
948af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
949af866496SDavid Daney 		       tx_ptr_en);
950af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
951af866496SDavid Daney 		       rx_ptr_en);
952af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_RXX_JABBER
953af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
954af866496SDavid Daney 		       rxx_jabber);
955af866496SDavid Daney 	cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
956af866496SDavid Daney 		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
957af866496SDavid Daney 		       frame_max);
958af866496SDavid Daney 	cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
959af866496SDavid Daney 
960af866496SDavid Daney 	CVMX_SYNC;
961af866496SDavid Daney 	if (num_segs)
962af866496SDavid Daney 		cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
963af866496SDavid Daney 
964af866496SDavid Daney 	return !!num_segs;
965af866496SDavid Daney 
966af866496SDavid Daney }
967af866496SDavid Daney 
968af866496SDavid Daney /**
969af866496SDavid Daney  * Called after all internal packet IO paths are setup. This
970af866496SDavid Daney  * function enables IPD/PIP and begins packet input and output.
971af866496SDavid Daney  *
972af866496SDavid Daney  * Returns Zero on success, negative on failure
973af866496SDavid Daney  */
cvmx_helper_ipd_and_packet_input_enable(void)974af866496SDavid Daney int cvmx_helper_ipd_and_packet_input_enable(void)
975af866496SDavid Daney {
976af866496SDavid Daney 	int num_interfaces;
977af866496SDavid Daney 	int interface;
978af866496SDavid Daney 
979af866496SDavid Daney 	/* Enable IPD */
980af866496SDavid Daney 	cvmx_ipd_enable();
981af866496SDavid Daney 
982af866496SDavid Daney 	/*
983af866496SDavid Daney 	 * Time to enable hardware ports packet input and output. Note
984af866496SDavid Daney 	 * that at this point IPD/PIP must be fully functional and PKO
985af866496SDavid Daney 	 * must be disabled
986af866496SDavid Daney 	 */
987af866496SDavid Daney 	num_interfaces = cvmx_helper_get_number_of_interfaces();
988af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
989af866496SDavid Daney 		if (cvmx_helper_ports_on_interface(interface) > 0)
990af866496SDavid Daney 			__cvmx_helper_packet_hardware_enable(interface);
991af866496SDavid Daney 	}
992af866496SDavid Daney 
993af866496SDavid Daney 	/* Finally enable PKO now that the entire path is up and running */
994af866496SDavid Daney 	cvmx_pko_enable();
995af866496SDavid Daney 
996af866496SDavid Daney 	if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
997af866496SDavid Daney 	     || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
998af866496SDavid Daney 	    && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
999af866496SDavid Daney 		__cvmx_helper_errata_fix_ipd_ptr_alignment();
1000af866496SDavid Daney 	return 0;
1001af866496SDavid Daney }
1002ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
1003af866496SDavid Daney 
1004af866496SDavid Daney /**
1005af866496SDavid Daney  * Initialize the PIP, IPD, and PKO hardware to support
1006af866496SDavid Daney  * simple priority based queues for the ethernet ports. Each
1007af866496SDavid Daney  * port is configured with a number of priority queues based
1008af866496SDavid Daney  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1009af866496SDavid Daney  * priority than the previous.
1010af866496SDavid Daney  *
1011af866496SDavid Daney  * Returns Zero on success, non-zero on failure
1012af866496SDavid Daney  */
cvmx_helper_initialize_packet_io_global(void)1013af866496SDavid Daney int cvmx_helper_initialize_packet_io_global(void)
1014af866496SDavid Daney {
1015af866496SDavid Daney 	int result = 0;
1016af866496SDavid Daney 	int interface;
1017af866496SDavid Daney 	union cvmx_l2c_cfg l2c_cfg;
1018af866496SDavid Daney 	const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1019af866496SDavid Daney 
1020af866496SDavid Daney 	/*
1021af866496SDavid Daney 	 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1022af866496SDavid Daney 	 * be disabled.
1023af866496SDavid Daney 	 */
1024af866496SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1025af866496SDavid Daney 		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1026af866496SDavid Daney 
1027af866496SDavid Daney 	/*
1028af866496SDavid Daney 	 * Tell L2 to give the IOB statically higher priority compared
1029af866496SDavid Daney 	 * to the cores. This avoids conditions where IO blocks might
1030af866496SDavid Daney 	 * be starved under very high L2 loads.
1031af866496SDavid Daney 	 */
1032af866496SDavid Daney 	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1033af866496SDavid Daney 	l2c_cfg.s.lrf_arb_mode = 0;
1034af866496SDavid Daney 	l2c_cfg.s.rfb_arb_mode = 0;
1035af866496SDavid Daney 	cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1036af866496SDavid Daney 
1037af866496SDavid Daney 	cvmx_pko_initialize_global();
1038af866496SDavid Daney 	for (interface = 0; interface < num_interfaces; interface++) {
1039af866496SDavid Daney 		result |= cvmx_helper_interface_probe(interface);
1040af866496SDavid Daney 		if (cvmx_helper_ports_on_interface(interface) > 0)
1041af866496SDavid Daney 			cvmx_dprintf("Interface %d has %d ports (%s)\n",
1042af866496SDavid Daney 				     interface,
1043af866496SDavid Daney 				     cvmx_helper_ports_on_interface(interface),
1044af866496SDavid Daney 				     cvmx_helper_interface_mode_to_string
1045af866496SDavid Daney 				     (cvmx_helper_interface_get_mode
1046af866496SDavid Daney 				      (interface)));
1047af866496SDavid Daney 		result |= __cvmx_helper_interface_setup_ipd(interface);
1048af866496SDavid Daney 		result |= __cvmx_helper_interface_setup_pko(interface);
1049af866496SDavid Daney 	}
1050af866496SDavid Daney 
1051af866496SDavid Daney 	result |= __cvmx_helper_global_setup_ipd();
1052af866496SDavid Daney 	result |= __cvmx_helper_global_setup_pko();
1053af866496SDavid Daney 
1054af866496SDavid Daney 	/* Enable any flow control and backpressure */
1055af866496SDavid Daney 	result |= __cvmx_helper_global_setup_backpressure();
1056af866496SDavid Daney 
1057af866496SDavid Daney #if CVMX_HELPER_ENABLE_IPD
1058af866496SDavid Daney 	result |= cvmx_helper_ipd_and_packet_input_enable();
1059af866496SDavid Daney #endif
1060af866496SDavid Daney 	return result;
1061af866496SDavid Daney }
1062ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1063af866496SDavid Daney 
1064af866496SDavid Daney /**
1065af866496SDavid Daney  * Return the link state of an IPD/PKO port as returned by
1066af866496SDavid Daney  * auto negotiation. The result of this function may not match
1067af866496SDavid Daney  * Octeon's link config if auto negotiation has changed since
1068af866496SDavid Daney  * the last call to cvmx_helper_link_set().
1069af866496SDavid Daney  *
1070af866496SDavid Daney  * @ipd_port: IPD/PKO port to query
1071af866496SDavid Daney  *
1072af866496SDavid Daney  * Returns Link state
1073af866496SDavid Daney  */
cvmx_helper_link_get(int ipd_port)1074f7d2bdcbSChris Packham union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
1075af866496SDavid Daney {
1076f7d2bdcbSChris Packham 	union cvmx_helper_link_info result;
1077af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
1078af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1079af866496SDavid Daney 
1080af866496SDavid Daney 	/* The default result will be a down link unless the code below
1081af866496SDavid Daney 	   changes it */
1082af866496SDavid Daney 	result.u64 = 0;
1083af866496SDavid Daney 
1084af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface))
1085af866496SDavid Daney 		return result;
1086af866496SDavid Daney 
1087af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
1088af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1089af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1090af866496SDavid Daney 		/* Network links are not supported */
1091af866496SDavid Daney 		break;
1092af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1093af866496SDavid Daney 		result = __cvmx_helper_xaui_link_get(ipd_port);
1094af866496SDavid Daney 		break;
1095af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1096af866496SDavid Daney 		if (index == 0)
1097af866496SDavid Daney 			result = __cvmx_helper_rgmii_link_get(ipd_port);
1098af866496SDavid Daney 		else {
1099*4c587a98SLadislav Michl 			WARN_ONCE(1, "Using deprecated link status - please update your DT");
1100af866496SDavid Daney 			result.s.full_duplex = 1;
1101af866496SDavid Daney 			result.s.link_up = 1;
1102af866496SDavid Daney 			result.s.speed = 1000;
1103af866496SDavid Daney 		}
1104af866496SDavid Daney 		break;
1105af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1106af866496SDavid Daney 		result = __cvmx_helper_rgmii_link_get(ipd_port);
1107af866496SDavid Daney 		break;
1108af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1109af866496SDavid Daney 		result = __cvmx_helper_spi_link_get(ipd_port);
1110af866496SDavid Daney 		break;
1111af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1112af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1113af866496SDavid Daney 		result = __cvmx_helper_sgmii_link_get(ipd_port);
1114af866496SDavid Daney 		break;
1115af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1116af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1117af866496SDavid Daney 		/* Network links are not supported */
1118af866496SDavid Daney 		break;
1119af866496SDavid Daney 	}
1120af866496SDavid Daney 	return result;
1121af866496SDavid Daney }
1122ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1123af866496SDavid Daney 
1124af866496SDavid Daney /**
1125af866496SDavid Daney  * Configure an IPD/PKO port for the specified link state. This
1126af866496SDavid Daney  * function does not influence auto negotiation at the PHY level.
1127af866496SDavid Daney  * The passed link state must always match the link state returned
11282b58a76eSAaro Koskinen  * by cvmx_helper_link_get().
1129af866496SDavid Daney  *
1130af866496SDavid Daney  * @ipd_port:  IPD/PKO port to configure
1131af866496SDavid Daney  * @link_info: The new link state
1132af866496SDavid Daney  *
1133af866496SDavid Daney  * Returns Zero on success, negative on failure
1134af866496SDavid Daney  */
cvmx_helper_link_set(int ipd_port,union cvmx_helper_link_info link_info)1135f7d2bdcbSChris Packham int cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)
1136af866496SDavid Daney {
1137af866496SDavid Daney 	int result = -1;
1138af866496SDavid Daney 	int interface = cvmx_helper_get_interface_num(ipd_port);
1139af866496SDavid Daney 	int index = cvmx_helper_get_interface_index_num(ipd_port);
1140af866496SDavid Daney 
1141af866496SDavid Daney 	if (index >= cvmx_helper_ports_on_interface(interface))
1142af866496SDavid Daney 		return -1;
1143af866496SDavid Daney 
1144af866496SDavid Daney 	switch (cvmx_helper_interface_get_mode(interface)) {
1145af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1146af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PCIE:
1147af866496SDavid Daney 		break;
1148af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_XAUI:
1149af866496SDavid Daney 		result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1150af866496SDavid Daney 		break;
1151af866496SDavid Daney 		/*
1152af866496SDavid Daney 		 * RGMII/GMII/MII are all treated about the same. Most
1153af866496SDavid Daney 		 * functions refer to these ports as RGMII.
1154af866496SDavid Daney 		 */
1155af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_RGMII:
1156af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_GMII:
1157af866496SDavid Daney 		result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1158af866496SDavid Daney 		break;
1159af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SPI:
1160af866496SDavid Daney 		result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1161af866496SDavid Daney 		break;
1162af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_SGMII:
1163af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_PICMG:
1164af866496SDavid Daney 		result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1165af866496SDavid Daney 		break;
1166af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_NPI:
1167af866496SDavid Daney 	case CVMX_HELPER_INTERFACE_MODE_LOOP:
1168af866496SDavid Daney 		break;
1169af866496SDavid Daney 	}
1170af866496SDavid Daney 	return result;
1171af866496SDavid Daney }
1172ce4126cbSAaro Koskinen EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1173