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