]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/contrib/octeon-sdk/cvmx-helper.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / contrib / octeon-sdk / cvmx-helper.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
3  * reserved.
4  *
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *   * Redistributions of source code must retain the above copyright
11  *     notice, this list of conditions and the following disclaimer.
12  *
13  *   * Redistributions in binary form must reproduce the above
14  *     copyright notice, this list of conditions and the following
15  *     disclaimer in the documentation and/or other materials provided
16  *     with the distribution.
17
18  *   * Neither the name of Cavium Inc. nor the names of
19  *     its contributors may be used to endorse or promote products
20  *     derived from this software without specific prior written
21  *     permission.
22
23  * This Software, including technical data, may be subject to U.S. export  control
24  * laws, including the U.S. Export Administration Act and its  associated
25  * regulations, and may be subject to export or import  regulations in other
26  * countries.
27
28  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29  * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30  * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31  * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32  * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33  * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34  * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35  * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36  * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
37  * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38  ***********************license end**************************************/
39
40
41
42
43
44
45
46 /**
47  * @file
48  *
49  * Helper functions for common, but complicated tasks.
50  *
51  * <hr>$Revision: 70030 $<hr>
52  */
53 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
54 #include <linux/module.h>
55 #include <asm/octeon/cvmx.h>
56 #include <asm/octeon/cvmx-config.h>
57 #include <asm/octeon/cvmx-bootmem.h>
58 #include <asm/octeon/cvmx-sriox-defs.h>
59 #include <asm/octeon/cvmx-npi-defs.h>
60 #include <asm/octeon/cvmx-mio-defs.h>
61 #include <asm/octeon/cvmx-pexp-defs.h>
62 #include <asm/octeon/cvmx-pip-defs.h>
63 #include <asm/octeon/cvmx-asxx-defs.h>
64 #include <asm/octeon/cvmx-gmxx-defs.h>
65 #include <asm/octeon/cvmx-smix-defs.h>
66 #include <asm/octeon/cvmx-dbg-defs.h>
67 #include <asm/octeon/cvmx-sso-defs.h>
68
69 #include <asm/octeon/cvmx-gmx.h>
70 #include <asm/octeon/cvmx-fpa.h>
71 #include <asm/octeon/cvmx-pip.h>
72 #include <asm/octeon/cvmx-pko.h>
73 #include <asm/octeon/cvmx-ipd.h>
74 #include <asm/octeon/cvmx-spi.h>
75 #include <asm/octeon/cvmx-clock.h>
76 #include <asm/octeon/cvmx-helper.h>
77 #include <asm/octeon/cvmx-helper-board.h>
78 #include <asm/octeon/cvmx-helper-errata.h>
79 #include <asm/octeon/cvmx-helper-cfg.h>
80 #else
81 #if !defined(__FreeBSD__) || !defined(_KERNEL)
82 #include "executive-config.h"
83 #endif
84 #include "cvmx.h"
85 #include "cvmx-sysinfo.h"
86 #include "cvmx-bootmem.h"
87 #include "cvmx-version.h"
88 #include "cvmx-helper-check-defines.h"
89 #include "cvmx-gmx.h"
90 #if !defined(__FreeBSD__) || !defined(_KERNEL)
91 #include "cvmx-error.h"
92 #include "cvmx-config.h"
93 #endif
94
95 #include "cvmx-fpa.h"
96 #include "cvmx-pip.h"
97 #include "cvmx-pko.h"
98 #include "cvmx-ipd.h"
99 #include "cvmx-spi.h"
100 #include "cvmx-helper.h"
101 #include "cvmx-helper-board.h"
102 #include "cvmx-helper-errata.h"
103 #include "cvmx-helper-cfg.h"
104 #endif
105
106
107 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
108
109 /**
110  * cvmx_override_pko_queue_priority(int pko_port, uint64_t
111  * priorities[16]) is a function pointer. It is meant to allow
112  * customization of the PKO queue priorities based on the port
113  * number. Users should set this pointer to a function before
114  * calling any cvmx-helper operations.
115  */
116 CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int ipd_port,
117     uint64_t *priorities) = NULL;
118 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
119 EXPORT_SYMBOL(cvmx_override_pko_queue_priority);
120 #endif
121
122 /**
123  * cvmx_override_ipd_port_setup(int ipd_port) is a function
124  * pointer. It is meant to allow customization of the IPD 
125  * port/port kind setup before packet input/output comes online. 
126  * It is called after cvmx-helper does the default IPD configuration,
127  * but before IPD is enabled. Users should set this pointer to a
128  * function before calling any cvmx-helper operations.
129  */
130 CVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL;
131
132 /**
133  * Return the number of interfaces the chip has. Each interface
134  * may have multiple ports. Most chips support two interfaces,
135  * but the CNX0XX and CNX1XX are exceptions. These only support
136  * one interface.
137  *
138  * @return Number of interfaces on chip
139  */
140 int cvmx_helper_get_number_of_interfaces(void)
141 {
142     switch (cvmx_sysinfo_get()->board_type) {
143 #if defined(OCTEON_VENDOR_LANNER)
144         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
145             return 2;
146         case CVMX_BOARD_TYPE_CUST_LANNER_MR730:
147             return 1;
148 #endif
149 #if defined(OCTEON_VENDOR_RADISYS)
150         case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE:
151             return 2;
152 #endif
153         default:
154             break;
155     }
156
157     if (OCTEON_IS_MODEL(OCTEON_CN68XX))
158         return 9;
159     else if (OCTEON_IS_MODEL(OCTEON_CN66XX))
160         if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
161             return 7;
162         else
163             return 8;
164     else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
165         return 6;
166     else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN61XX))
167         return 4;
168     else
169         return 3;
170 }
171 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
172 EXPORT_SYMBOL(cvmx_helper_get_number_of_interfaces);
173 #endif
174
175
176 /**
177  * Return the number of ports on an interface. Depending on the
178  * chip and configuration, this can be 1-16. A value of 0
179  * specifies that the interface doesn't exist or isn't usable.
180  *
181  * @param interface Interface to get the port count for
182  *
183  * @return Number of ports on interface. Can be Zero.
184  */
185 int cvmx_helper_ports_on_interface(int interface)
186 {
187     if (octeon_has_feature(OCTEON_FEATURE_PKND))
188         return cvmx_helper_interface_enumerate(interface);
189     else
190         return __cvmx_helper_get_num_ipd_ports(interface);
191 }
192 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
193 EXPORT_SYMBOL(cvmx_helper_ports_on_interface);
194 #endif
195
196
197 /**
198  * Get the operating mode of an interface. Depending on the Octeon
199  * chip and configuration, this function returns an enumeration
200  * of the type of packet I/O supported by an interface.
201  *
202  * @param interface Interface to probe
203  *
204  * @return Mode of the interface. Unknown or unsupported interfaces return
205  *         DISABLED.
206  */
207 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
208 {
209     cvmx_gmxx_inf_mode_t mode;
210
211     if (OCTEON_IS_MODEL(OCTEON_CN68XX))
212     {
213         cvmx_mio_qlmx_cfg_t qlm_cfg;
214         switch(interface)
215         {
216             case 0:
217                 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
218                 /* QLM is disabled when QLM SPD is 15. */
219                 if (qlm_cfg.s.qlm_spd == 15)
220                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
221
222                 if (qlm_cfg.s.qlm_cfg == 7)
223                     return CVMX_HELPER_INTERFACE_MODE_RXAUI;
224                 else if (qlm_cfg.s.qlm_cfg == 2)
225                     return CVMX_HELPER_INTERFACE_MODE_SGMII;
226                 else if (qlm_cfg.s.qlm_cfg == 3)
227                     return CVMX_HELPER_INTERFACE_MODE_XAUI;
228                 else
229                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
230                 break;
231             case 1:
232                 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
233                 /* QLM is disabled when QLM SPD is 15. */
234                 if (qlm_cfg.s.qlm_spd == 15)
235                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
236
237                 if (qlm_cfg.s.qlm_cfg == 7)
238                     return CVMX_HELPER_INTERFACE_MODE_RXAUI;
239                 else
240                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
241                 break;
242             case 2:
243             case 3:
244             case 4:
245                 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
246                 /* QLM is disabled when QLM SPD is 15. */
247                 if (qlm_cfg.s.qlm_spd == 15)
248                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
249
250                 if (qlm_cfg.s.qlm_cfg == 2)
251                     return CVMX_HELPER_INTERFACE_MODE_SGMII;
252                 else if (qlm_cfg.s.qlm_cfg == 3)
253                     return CVMX_HELPER_INTERFACE_MODE_XAUI;
254                 else
255                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
256                 break; 
257             case 5:
258             case 6:
259                 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface - 4));
260                 /* QLM is disabled when QLM SPD is 15. */
261                 if (qlm_cfg.s.qlm_spd == 15)
262                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
263
264                 if (qlm_cfg.s.qlm_cfg == 1)
265                 {
266                     return CVMX_HELPER_INTERFACE_MODE_ILK;
267                 }
268                 else
269                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
270                 break; 
271             case 7:
272                 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
273                 /* QLM is disabled when QLM SPD is 15. */
274                 if (qlm_cfg.s.qlm_spd == 15)
275                     return CVMX_HELPER_INTERFACE_MODE_DISABLED;
276                 else if (qlm_cfg.s.qlm_cfg != 0)
277                 {
278                     qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
279                     if (qlm_cfg.s.qlm_cfg != 0)
280                         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
281                 }
282                 return CVMX_HELPER_INTERFACE_MODE_NPI;
283                 break; 
284             case 8:
285                 return CVMX_HELPER_INTERFACE_MODE_LOOP;
286                 break; 
287             default:
288                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
289                 break; 
290         }
291     }
292                     
293     if (interface == 2)
294         return CVMX_HELPER_INTERFACE_MODE_NPI;
295
296     if (interface == 3)
297     {
298         if (OCTEON_IS_MODEL(OCTEON_CN56XX)
299             || OCTEON_IS_MODEL(OCTEON_CN52XX)
300             || OCTEON_IS_MODEL(OCTEON_CN6XXX)
301             || OCTEON_IS_MODEL(OCTEON_CNF7XXX))
302             return CVMX_HELPER_INTERFACE_MODE_LOOP;
303         else
304             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
305     }
306
307     /* Only present in CN63XX & CN66XX Octeon model */
308     if ((OCTEON_IS_MODEL(OCTEON_CN63XX) && (interface == 4 || interface == 5)) 
309         || (OCTEON_IS_MODEL(OCTEON_CN66XX) && interface >= 4 && interface <= 7))
310     {
311         cvmx_sriox_status_reg_t sriox_status_reg;
312
313         /* cn66xx pass1.0 has only 2 SRIO interfaces. */
314         if ((interface == 5 || interface == 7) && OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
315             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
316
317         sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(interface-4));
318         if (sriox_status_reg.s.srio)
319             return CVMX_HELPER_INTERFACE_MODE_SRIO;
320         else
321             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
322     }
323
324     /* Interface 5 always disabled in CN66XX */
325     if (OCTEON_IS_MODEL(OCTEON_CN66XX))
326     {
327         cvmx_mio_qlmx_cfg_t mio_qlm_cfg;
328
329         /* QLM2 is SGMII0 and QLM1 is SGMII1 */
330         if (interface == 0)
331             mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
332         else if (interface == 1)
333             mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
334         else
335             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
336
337         if (mio_qlm_cfg.s.qlm_spd == 15)
338             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
339
340         if (mio_qlm_cfg.s.qlm_cfg == 9)
341             return CVMX_HELPER_INTERFACE_MODE_SGMII;
342         else if (mio_qlm_cfg.s.qlm_cfg == 11)
343             return CVMX_HELPER_INTERFACE_MODE_XAUI;
344         else
345             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
346     }
347     else if (OCTEON_IS_MODEL(OCTEON_CN61XX))
348     {
349         cvmx_mio_qlmx_cfg_t qlm_cfg;
350
351         if (interface == 0)
352         {
353             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
354             if (qlm_cfg.s.qlm_cfg == 2)
355                 return CVMX_HELPER_INTERFACE_MODE_SGMII;
356             else if (qlm_cfg.s.qlm_cfg == 3)
357                 return CVMX_HELPER_INTERFACE_MODE_XAUI;
358             else
359                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
360         }
361         else if (interface == 1)
362         {
363             /* If QLM 1 is PEV0/PEM1 mode, them QLM0 cannot be SGMII/XAUI */
364             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
365             if (qlm_cfg.s.qlm_cfg == 1)
366                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
367
368             qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
369             if (qlm_cfg.s.qlm_cfg == 2)
370                 return CVMX_HELPER_INTERFACE_MODE_SGMII;
371             else if (qlm_cfg.s.qlm_cfg == 3)
372                 return CVMX_HELPER_INTERFACE_MODE_XAUI;
373             else
374                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
375         }
376     }
377
378     if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1)
379     {
380         /* Lie about interface type of CN3005 board.  This board has a switch on port 1 like
381         ** the other evaluation boards, but it is connected over RGMII instead of GMII.  Report
382         ** GMII mode so that the speed is forced to 1 Gbit full duplex.  Other than some initial configuration
383         ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes.
384         */
385         return CVMX_HELPER_INTERFACE_MODE_GMII;
386     }
387
388     /* Interface 1 is always disabled on CN31XX and CN30XX */
389     if ((interface == 1) 
390         && (OCTEON_IS_MODEL(OCTEON_CN31XX)
391             || OCTEON_IS_MODEL(OCTEON_CN30XX)
392             || OCTEON_IS_MODEL(OCTEON_CN50XX)
393             || OCTEON_IS_MODEL(OCTEON_CN52XX)
394             || OCTEON_IS_MODEL(OCTEON_CN63XX)
395             || OCTEON_IS_MODEL(OCTEON_CNF71XX)))
396         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
397
398     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
399
400     if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
401     {
402         switch(mode.cn56xx.mode)
403         {
404             case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED;
405             case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI;
406             case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII;
407             case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG;
408             default:return CVMX_HELPER_INTERFACE_MODE_DISABLED;
409         }
410     }
411     else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
412     {
413         switch(mode.cn63xx.mode)
414         {
415             case 0: return CVMX_HELPER_INTERFACE_MODE_SGMII;
416             case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI;
417             default: return CVMX_HELPER_INTERFACE_MODE_DISABLED;
418         }
419     }
420     else
421     {
422         if (!mode.s.en)
423             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
424
425         if (mode.s.type)
426         {
427             if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
428                 return CVMX_HELPER_INTERFACE_MODE_SPI;
429             else
430                 return CVMX_HELPER_INTERFACE_MODE_GMII;
431         }
432         else
433             return CVMX_HELPER_INTERFACE_MODE_RGMII;
434     }
435 }
436 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
437 EXPORT_SYMBOL(cvmx_helper_interface_get_mode);
438 #endif
439
440 /**
441  * @INTERNAL
442  * Configure the IPD/PIP tagging and QoS options for a specific
443  * port. This function determines the POW work queue entry
444  * contents for a port. The setup performed here is controlled by
445  * the defines in executive-config.h.
446  *
447  * @param ipd_port Port/Port kind to configure. This follows the IPD numbering, 
448  *                 not the per interface numbering
449  *
450  * @return Zero on success, negative on failure
451  */
452 static int __cvmx_helper_port_setup_ipd(int ipd_port)
453 {
454     cvmx_pip_prt_cfgx_t port_config;
455     cvmx_pip_prt_tagx_t tag_config;
456
457     if (octeon_has_feature(OCTEON_FEATURE_PKND))
458     {
459         int interface, index, pknd;
460         cvmx_pip_prt_cfgbx_t prt_cfgbx;
461
462         interface = cvmx_helper_get_interface_num(ipd_port);
463         index = cvmx_helper_get_interface_index_num(ipd_port);
464         pknd = cvmx_helper_get_pknd(interface, index);
465
466         port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd));
467         tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(pknd));
468
469         port_config.s.qos = pknd & 0x7;
470
471         /* Default BPID to use for packets on this port-kind */
472         prt_cfgbx.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGBX(pknd));
473         prt_cfgbx.s.bpid = pknd;
474         cvmx_write_csr(CVMX_PIP_PRT_CFGBX(pknd), prt_cfgbx.u64);
475     }
476     else
477     {
478         port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
479         tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
480
481         /* Have each port go to a different POW queue */
482         port_config.s.qos = ipd_port & 0x7;
483     }
484
485     /* Process the headers and place the IP header in the work queue */
486     port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
487
488     tag_config.s.ip6_src_flag  = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
489     tag_config.s.ip6_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
490     tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
491     tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
492     tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
493     tag_config.s.ip4_src_flag  = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
494     tag_config.s.ip4_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
495     tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
496     tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
497     tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
498     tag_config.s.inc_prt_flag  = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
499     tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
500     tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
501     tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
502     tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
503     tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
504     /* Put all packets in group 0. Other groups can be used by the app */
505     tag_config.s.grp = 0;
506
507     cvmx_pip_config_port(ipd_port, port_config, tag_config);
508
509     /* Give the user a chance to override our setting for each port */
510     if (cvmx_override_ipd_port_setup)
511         cvmx_override_ipd_port_setup(ipd_port);
512
513     return 0;
514 }
515
516 /**
517  * Enable or disable FCS stripping for all the ports on an interface.
518  *
519  * @param interface
520  * @param nports number of ports
521  * @param has_fcs 0 for disable and !0 for enable
522  */
523 static int cvmx_helper_fcs_op(int interface, int nports, int has_fcs)
524 {
525     uint64_t port_bit;
526     int index;
527     int pknd;
528     cvmx_pip_sub_pkind_fcsx_t pkind_fcsx;
529     cvmx_pip_prt_cfgx_t port_cfg;
530     
531     if (!octeon_has_feature(OCTEON_FEATURE_PKND))
532         return 0;
533
534     port_bit = 0;
535     for (index = 0; index < nports; index++)
536         port_bit |= ((uint64_t)1 << cvmx_helper_get_pknd(interface, index));
537     
538     pkind_fcsx.u64 = cvmx_read_csr(CVMX_PIP_SUB_PKIND_FCSX(0));
539     if (has_fcs)
540         pkind_fcsx.s.port_bit |= port_bit;
541     else
542         pkind_fcsx.s.port_bit &= ~port_bit;
543     cvmx_write_csr(CVMX_PIP_SUB_PKIND_FCSX(0), pkind_fcsx.u64);
544
545     for (pknd = 0; pknd < 64; pknd++)
546     {
547         if ((1ull << pknd) & port_bit)
548         {
549             port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd));
550             port_cfg.s.crc_en = (has_fcs) ? 1 : 0;
551             cvmx_write_csr(CVMX_PIP_PRT_CFGX(pknd), port_cfg.u64);
552         }
553     }
554
555     return 0;
556 }
557
558 /**
559  * Determine the actual number of hardware ports connected to an
560  * interface. It doesn't setup the ports or enable them.
561  *
562  * @param interface Interface to enumerate
563  *
564  * @return The number of ports on the interface, negative on failure
565  */
566 int cvmx_helper_interface_enumerate(int interface)
567 {
568         switch (cvmx_helper_interface_get_mode(interface)) {
569                 /* XAUI is a single high speed port */
570         case CVMX_HELPER_INTERFACE_MODE_XAUI:
571         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
572                 return __cvmx_helper_xaui_enumerate(interface);
573                 /* RGMII/GMII/MII are all treated about the same. Most functions
574                    refer to these ports as RGMII */
575         case CVMX_HELPER_INTERFACE_MODE_RGMII:
576         case CVMX_HELPER_INTERFACE_MODE_GMII:
577                 return  __cvmx_helper_rgmii_enumerate(interface);
578                 /* SPI4 can have 1-16 ports depending on the device at the other end */
579         case CVMX_HELPER_INTERFACE_MODE_SPI:
580                 return __cvmx_helper_spi_enumerate(interface);
581                 /* SGMII can have 1-4 ports depending on how many are hooked up */
582         case CVMX_HELPER_INTERFACE_MODE_SGMII:
583         case CVMX_HELPER_INTERFACE_MODE_PICMG:
584                 return __cvmx_helper_sgmii_enumerate(interface);
585                 /* PCI target Network Packet Interface */
586         case CVMX_HELPER_INTERFACE_MODE_NPI:
587                 return __cvmx_helper_npi_enumerate(interface);
588                 /* Special loopback only ports. These are not the same
589                  * as other ports in loopback mode */
590         case CVMX_HELPER_INTERFACE_MODE_LOOP:
591                 return __cvmx_helper_loop_enumerate(interface);
592                 /* SRIO has 2^N ports, where N is number of interfaces */
593         case CVMX_HELPER_INTERFACE_MODE_SRIO:
594                 return __cvmx_helper_srio_enumerate(interface);
595
596         case CVMX_HELPER_INTERFACE_MODE_ILK:
597                 return __cvmx_helper_ilk_enumerate(interface);
598                 /* These types don't support ports to IPD/PKO */
599         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
600         case CVMX_HELPER_INTERFACE_MODE_PCIE:
601         default:
602                 return 0;
603     }
604 }
605
606 /**
607  * This function probes an interface to determine the actual number of
608  * hardware ports connected to it. It does some setup the ports but
609  * doesn't enable them. The main goal here is to set the global
610  * interface_port_count[interface] correctly. Final hardware setup of
611  * the ports will be performed later.
612  *
613  * @param interface Interface to probe
614  *
615  * @return Zero on success, negative on failure
616  */
617 int cvmx_helper_interface_probe(int interface)
618 {
619     /* At this stage in the game we don't want packets to be moving yet.
620         The following probe calls should perform hardware setup
621         needed to determine port counts. Receive must still be disabled */
622     int nports;
623     int has_fcs;
624     enum cvmx_pko_padding padding = CVMX_PKO_PADDING_NONE;
625
626     nports = -1;
627     has_fcs = 0;
628     switch (cvmx_helper_interface_get_mode(interface))
629     {
630         /* These types don't support ports to IPD/PKO */
631         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
632         case CVMX_HELPER_INTERFACE_MODE_PCIE:
633             nports = 0;
634             break;
635         /* XAUI is a single high speed port */
636         case CVMX_HELPER_INTERFACE_MODE_XAUI:
637         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
638             nports = __cvmx_helper_xaui_probe(interface);
639             has_fcs = 1;
640             padding = CVMX_PKO_PADDING_60;
641             break;
642         /* RGMII/GMII/MII are all treated about the same. Most functions
643             refer to these ports as RGMII */
644         case CVMX_HELPER_INTERFACE_MODE_RGMII:
645         case CVMX_HELPER_INTERFACE_MODE_GMII:
646             nports = __cvmx_helper_rgmii_probe(interface);
647             padding = CVMX_PKO_PADDING_60;
648             break;
649         /* SPI4 can have 1-16 ports depending on the device at the other end */
650         case CVMX_HELPER_INTERFACE_MODE_SPI:
651             nports = __cvmx_helper_spi_probe(interface);
652             padding = CVMX_PKO_PADDING_60;
653             break;
654         /* SGMII can have 1-4 ports depending on how many are hooked up */
655         case CVMX_HELPER_INTERFACE_MODE_SGMII:
656             padding = CVMX_PKO_PADDING_60;
657         case CVMX_HELPER_INTERFACE_MODE_PICMG:
658             nports = __cvmx_helper_sgmii_probe(interface);
659             has_fcs = 1;
660             break;
661         /* PCI target Network Packet Interface */
662         case CVMX_HELPER_INTERFACE_MODE_NPI:
663             nports = __cvmx_helper_npi_probe(interface);
664             break;
665         /* Special loopback only ports. These are not the same as other ports
666             in loopback mode */
667         case CVMX_HELPER_INTERFACE_MODE_LOOP:
668             nports = __cvmx_helper_loop_probe(interface);
669             break;
670         /* SRIO has 2^N ports, where N is number of interfaces */
671         case CVMX_HELPER_INTERFACE_MODE_SRIO:
672             nports = __cvmx_helper_srio_probe(interface);
673             break;
674         case CVMX_HELPER_INTERFACE_MODE_ILK:
675             nports = __cvmx_helper_ilk_probe(interface);
676             has_fcs = 1;
677             padding = CVMX_PKO_PADDING_60;
678             break;
679     }
680
681     if (nports == -1)
682         return -1;
683
684     if (!octeon_has_feature(OCTEON_FEATURE_PKND))
685         has_fcs = 0;
686
687     nports = __cvmx_helper_board_interface_probe(interface, nports);
688     __cvmx_helper_init_interface(interface, nports, has_fcs, padding);
689     cvmx_helper_fcs_op(interface, nports, has_fcs);
690
691     /* Make sure all global variables propagate to other cores */
692     CVMX_SYNCWS;
693
694     return 0;
695 }
696
697
698 /**
699  * @INTERNAL
700  * Setup the IPD/PIP for the ports on an interface. Packet
701  * classification and tagging are set for every port on the
702  * interface. The number of ports on the interface must already
703  * have been probed.
704  *
705  * @param interface Interface to setup IPD/PIP for
706  *
707  * @return Zero on success, negative on failure
708  */
709 static int __cvmx_helper_interface_setup_ipd(int interface)
710 {
711
712     cvmx_helper_interface_mode_t mode;
713     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
714     int num_ports = cvmx_helper_ports_on_interface(interface);
715     int delta;
716
717     if (num_ports == CVMX_HELPER_CFG_INVALID_VALUE)
718         return 0;
719
720     mode = cvmx_helper_interface_get_mode(interface);
721
722     if (mode == CVMX_HELPER_INTERFACE_MODE_LOOP)
723         __cvmx_helper_loop_enable(interface);
724
725     delta = 1;
726     if (octeon_has_feature(OCTEON_FEATURE_PKND))
727     {
728         if (mode == CVMX_HELPER_INTERFACE_MODE_SGMII)
729             delta = 16;
730     }
731
732     while (num_ports--)
733     {
734         __cvmx_helper_port_setup_ipd(ipd_port);
735         ipd_port += delta;
736     }
737
738     return 0;
739 }
740
741
742 /**
743  * @INTERNAL
744  * Setup global setting for IPD/PIP not related to a specific
745  * interface or port. This must be called before IPD is enabled.
746  *
747  * @return Zero on success, negative on failure.
748  */
749 static int __cvmx_helper_global_setup_ipd(void)
750 {
751 #ifndef CVMX_HELPER_IPD_DRAM_MODE
752 #define CVMX_HELPER_IPD_DRAM_MODE   CVMX_IPD_OPC_MODE_STT
753 #endif
754     /* Setup the global packet input options */
755     cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8,
756                     CVMX_HELPER_FIRST_MBUFF_SKIP/8,
757                     CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8,
758                     (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
759                     (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
760                     CVMX_FPA_WQE_POOL,
761                     CVMX_HELPER_IPD_DRAM_MODE,
762                     1);
763     return 0;
764 }
765
766
767 /**
768  * @INTERNAL
769  * Setup the PKO for the ports on an interface. The number of
770  * queues per port and the priority of each PKO output queue
771  * is set here. PKO must be disabled when this function is called.
772  *
773  * @param interface Interface to setup PKO for
774  *
775  * @return Zero on success, negative on failure
776  */
777 static int __cvmx_helper_interface_setup_pko(int interface)
778 {
779     /* Each packet output queue has an associated priority. The higher the
780         priority, the more often it can send a packet. A priority of 8 means
781         it can send in all 8 rounds of contention. We're going to make each
782         queue one less than the last.
783         The vector of priorities has been extended to support CN5xxx CPUs,
784         where up to 16 queues can be associated to a port.
785         To keep backward compatibility we don't change the initial 8
786         priorities and replicate them in the second half.
787         With per-core PKO queues (PKO lockless operation) all queues have
788         the same priority. */
789     /* uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; */
790     uint64_t priorities[16] = {[0 ... 15] = 8};
791
792     /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet
793         classification, tagging and output priorities are set */
794     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
795     int num_ports = cvmx_helper_ports_on_interface(interface);
796     while (num_ports--)
797     {
798         /* Give the user a chance to override the per queue priorities */
799         if (cvmx_override_pko_queue_priority)
800             cvmx_override_pko_queue_priority(ipd_port, priorities);
801
802         cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0),
803                              cvmx_pko_get_num_queues(ipd_port), priorities);
804         ipd_port++;
805     }
806     return 0;
807 }
808
809
810 /**
811  * @INTERNAL
812  * Setup global setting for PKO not related to a specific
813  * interface or port. This must be called before PKO is enabled.
814  *
815  * @return Zero on success, negative on failure.
816  */
817 static int __cvmx_helper_global_setup_pko(void)
818 {
819     /* Disable tagwait FAU timeout. This needs to be done before anyone might
820         start packet output using tags */
821     cvmx_iob_fau_timeout_t fau_to;
822     fau_to.u64 = 0;
823     fau_to.s.tout_val = 0xfff;
824     fau_to.s.tout_enb = 0;
825     cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
826
827     if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
828             cvmx_pko_reg_min_pkt_t min_pkt;
829
830             min_pkt.u64 = 0;
831             min_pkt.s.size1 = 59;
832             min_pkt.s.size2 = 59;
833             min_pkt.s.size3 = 59;
834             min_pkt.s.size4 = 59;
835             min_pkt.s.size5 = 59;
836             min_pkt.s.size6 = 59;
837             min_pkt.s.size7 = 59;
838             cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
839     }
840
841     return 0;
842 }
843
844
845 /**
846  * @INTERNAL
847  * Setup global backpressure setting.
848  *
849  * @return Zero on success, negative on failure
850  */
851 static int __cvmx_helper_global_setup_backpressure(void)
852 {
853 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
854     /* Disable backpressure if configured to do so */
855     /* Disable backpressure (pause frame) generation */
856     int num_interfaces = cvmx_helper_get_number_of_interfaces();
857     int interface;
858     for (interface=0; interface<num_interfaces; interface++)
859     {
860         switch (cvmx_helper_interface_get_mode(interface))
861         {
862             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
863             case CVMX_HELPER_INTERFACE_MODE_PCIE:
864             case CVMX_HELPER_INTERFACE_MODE_SRIO:
865             case CVMX_HELPER_INTERFACE_MODE_ILK:
866             case CVMX_HELPER_INTERFACE_MODE_NPI:
867             case CVMX_HELPER_INTERFACE_MODE_LOOP:
868             case CVMX_HELPER_INTERFACE_MODE_XAUI:
869             case CVMX_HELPER_INTERFACE_MODE_RXAUI:
870                 break;
871             case CVMX_HELPER_INTERFACE_MODE_RGMII:
872             case CVMX_HELPER_INTERFACE_MODE_GMII:
873             case CVMX_HELPER_INTERFACE_MODE_SPI:
874             case CVMX_HELPER_INTERFACE_MODE_SGMII:
875             case CVMX_HELPER_INTERFACE_MODE_PICMG:
876                 cvmx_gmx_set_backpressure_override(interface, 0xf);
877                 break;
878         }
879     }
880     //cvmx_dprintf("Disabling backpressure\n");
881 #endif
882
883     return 0;
884 }
885
886 /**
887  * @INTERNAL
888  * Verify the per port IPD backpressure is aligned properly.
889  * @return Zero if working, non zero if misaligned
890  */
891 static int __cvmx_helper_backpressure_is_misaligned(void)
892 {
893     uint64_t ipd_int_enb;
894     cvmx_ipd_ctl_status_t ipd_reg;
895     uint64_t bp_status0;
896     uint64_t bp_status1;
897     const int port0 = 0;
898     const int port1 = 16;
899     cvmx_helper_interface_mode_t mode0 = cvmx_helper_interface_get_mode(0);
900     cvmx_helper_interface_mode_t mode1 = cvmx_helper_interface_get_mode(1);
901
902     /* Disable error interrupts while we check backpressure */
903     ipd_int_enb = cvmx_read_csr(CVMX_IPD_INT_ENB);
904     cvmx_write_csr(CVMX_IPD_INT_ENB, 0);
905
906     /* Enable per port backpressure */
907     ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
908     ipd_reg.s.pbp_en = 1;
909     cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64);
910
911     if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
912     {
913         /* Enable backpressure for port with a zero threshold */
914         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 1<<17);
915         /* Add 1000 to the page count to simulate packets coming in */
916         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | 1000);
917     }
918
919     if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
920     {
921         /* Enable backpressure for port with a zero threshold */
922         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 1<<17);
923         /* Add 1000 to the page count to simulate packets coming in */
924         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | 1000);
925     }
926
927     /* Wait 500 cycles for the BP to update */
928     cvmx_wait(500);
929
930     /* Read the BP state from the debug select register */
931     switch (mode0)
932     {
933         case CVMX_HELPER_INTERFACE_MODE_SPI:
934             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9004);
935             bp_status0 = cvmx_read_csr(CVMX_DBG_DATA);
936             bp_status0 = 0xffff & ~bp_status0;
937             break;
938         case CVMX_HELPER_INTERFACE_MODE_RGMII:
939         case CVMX_HELPER_INTERFACE_MODE_GMII:
940             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x0e00);
941             bp_status0 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA);
942             break;
943         case CVMX_HELPER_INTERFACE_MODE_XAUI:
944         case CVMX_HELPER_INTERFACE_MODE_SGMII:
945         case CVMX_HELPER_INTERFACE_MODE_PICMG:
946             cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x0e00);
947             bp_status0 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
948             break;
949         default:
950             bp_status0 = 1<<port0;
951             break;
952     }
953
954     /* Read the BP state from the debug select register */
955     switch (mode1)
956     {
957         case CVMX_HELPER_INTERFACE_MODE_SPI:
958             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9804);
959             bp_status1 = cvmx_read_csr(CVMX_DBG_DATA);
960             bp_status1 = 0xffff & ~bp_status1;
961             break;
962         case CVMX_HELPER_INTERFACE_MODE_RGMII:
963         case CVMX_HELPER_INTERFACE_MODE_GMII:
964             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x1600);
965             bp_status1 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA);
966             break;
967         case CVMX_HELPER_INTERFACE_MODE_XAUI:
968         case CVMX_HELPER_INTERFACE_MODE_SGMII:
969         case CVMX_HELPER_INTERFACE_MODE_PICMG:
970             cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x1600);
971             bp_status1 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
972             break;
973         default:
974             bp_status1 = 1<<(port1-16);
975             break;
976     }
977
978     if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
979     {
980         /* Shutdown BP */
981         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | (0x1ffffff & -1000));
982         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 0);
983     }
984
985     if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
986     {
987         /* Shutdown BP */
988         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | (0x1ffffff & -1000));
989         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 0);
990     }
991
992     /* Clear any error interrupts that might have been set */
993     cvmx_write_csr(CVMX_IPD_INT_SUM, 0x1f);
994     cvmx_write_csr(CVMX_IPD_INT_ENB, ipd_int_enb);
995
996     return ((bp_status0 != 1ull<<port0) || (bp_status1 != 1ull<<(port1-16)));
997 }
998
999
1000 /**
1001  * @INTERNAL
1002  * Enable packet input/output from the hardware. This function is
1003  * called after all internal setup is complete and IPD is enabled.
1004  * After this function completes, packets will be accepted from the
1005  * hardware ports. PKO should still be disabled to make sure packets
1006  * aren't sent out partially setup hardware.
1007  *
1008  * @param interface Interface to enable
1009  *
1010  * @return Zero on success, negative on failure
1011  */
1012 static int __cvmx_helper_packet_hardware_enable(int interface)
1013 {
1014     int result = 0;
1015     switch (cvmx_helper_interface_get_mode(interface))
1016     {
1017         /* These types don't support ports to IPD/PKO */
1018         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1019         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1020         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1021             /* Nothing to do */
1022             break;
1023         /* XAUI is a single high speed port */
1024         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1025         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1026             result = __cvmx_helper_xaui_enable(interface);
1027             break;
1028         /* RGMII/GMII/MII are all treated about the same. Most functions
1029             refer to these ports as RGMII */
1030         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1031         case CVMX_HELPER_INTERFACE_MODE_GMII:
1032             result = __cvmx_helper_rgmii_enable(interface);
1033             break;
1034         /* SPI4 can have 1-16 ports depending on the device at the other end */
1035         case CVMX_HELPER_INTERFACE_MODE_SPI:
1036             result = __cvmx_helper_spi_enable(interface);
1037             break;
1038         /* SGMII can have 1-4 ports depending on how many are hooked up */
1039         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1040         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1041             result = __cvmx_helper_sgmii_enable(interface);
1042             break;
1043         /* PCI target Network Packet Interface */
1044         case CVMX_HELPER_INTERFACE_MODE_NPI:
1045             result = __cvmx_helper_npi_enable(interface);
1046             break;
1047         /* SRIO has 2^N ports, where N is number of interfaces */
1048         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1049             result = __cvmx_helper_srio_enable(interface);
1050             break;
1051         case CVMX_HELPER_INTERFACE_MODE_ILK:
1052             result = __cvmx_helper_ilk_enable(interface);
1053             break;
1054     }
1055     result |= __cvmx_helper_board_hardware_enable(interface);
1056     return result;
1057 }
1058
1059
1060 /**
1061  * Called after all internal packet IO paths are setup. This
1062  * function enables IPD/PIP and begins packet input and output.
1063  *
1064  * @return Zero on success, negative on failure
1065  */
1066 int cvmx_helper_ipd_and_packet_input_enable(void)
1067 {
1068     int num_interfaces;
1069     int interface;
1070
1071     /* Enable IPD */
1072     cvmx_ipd_enable();
1073
1074     /* Time to enable hardware ports packet input and output. Note that at this
1075         point IPD/PIP must be fully functional and PKO must be disabled */
1076     num_interfaces = cvmx_helper_get_number_of_interfaces();
1077     for (interface=0; interface<num_interfaces; interface++)
1078     {
1079         if (cvmx_helper_ports_on_interface(interface) > 0)
1080         {
1081             //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface);
1082             __cvmx_helper_packet_hardware_enable(interface);
1083         }
1084     }
1085
1086     /* Finally enable PKO now that the entire path is up and running */
1087     cvmx_pko_enable();
1088
1089     if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) &&
1090         (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
1091         __cvmx_helper_errata_fix_ipd_ptr_alignment();
1092     return 0;
1093 }
1094 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1095 EXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable);
1096 #endif
1097
1098 #define __CVMX_SSO_RWQ_SIZE 256
1099
1100 int cvmx_helper_initialize_sso(int wqe_entries)
1101 {
1102     int cvm_oct_sso_number_rwq_bufs;
1103     char *mem;
1104     int i;
1105     cvmx_sso_cfg_t sso_cfg;
1106     cvmx_fpa_fpfx_marks_t fpa_marks;
1107
1108     if (!OCTEON_IS_MODEL(OCTEON_CN68XX))
1109         return 0;
1110
1111     /*
1112      * CN68XX-P1 may reset with the wrong values, put in
1113      * the correct values.
1114      */
1115     fpa_marks.u64 = 0;
1116     fpa_marks.s.fpf_wr = 0xa4;
1117     fpa_marks.s.fpf_rd = 0x40;
1118     cvmx_write_csr(CVMX_FPA_FPF8_MARKS, fpa_marks.u64);
1119
1120     cvm_oct_sso_number_rwq_bufs = ((wqe_entries - 1) / 26) + 1 + 48 + 8;
1121
1122     mem = cvmx_bootmem_alloc(__CVMX_SSO_RWQ_SIZE * cvm_oct_sso_number_rwq_bufs, CVMX_CACHE_LINE_SIZE);
1123     if (mem == NULL) {
1124         cvmx_dprintf("Out of memory initializing sso pool\n");
1125         return -1;
1126     }
1127     /* Make sure RWI/RWO is disabled. */
1128     sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG);
1129     sso_cfg.s.rwen = 0;
1130     cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64);
1131
1132     for (i = cvm_oct_sso_number_rwq_bufs - 8; i > 0; i--) {
1133         cvmx_sso_rwq_psh_fptr_t fptr;
1134
1135         for (;;) {
1136             fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR);
1137             if (!fptr.s.full)
1138                 break;
1139             cvmx_wait(1000);
1140         }
1141         fptr.s.fptr = cvmx_ptr_to_phys(mem) >> 7;
1142         cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64);
1143         mem = mem + __CVMX_SSO_RWQ_SIZE;
1144     }
1145
1146     for (i = 0; i < 8; i++) {
1147         cvmx_sso_rwq_head_ptrx_t head_ptr;
1148         cvmx_sso_rwq_tail_ptrx_t tail_ptr;
1149
1150         head_ptr.u64 = 0;
1151         tail_ptr.u64 = 0;
1152         head_ptr.s.ptr = cvmx_ptr_to_phys(mem) >> 7;
1153         tail_ptr.s.ptr = head_ptr.s.ptr;
1154         cvmx_write_csr(CVMX_SSO_RWQ_HEAD_PTRX(i), head_ptr.u64);
1155         cvmx_write_csr(CVMX_SSO_RWQ_TAIL_PTRX(i), tail_ptr.u64);
1156         mem = mem + __CVMX_SSO_RWQ_SIZE;
1157     }
1158
1159     sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG);
1160     sso_cfg.s.rwen = 1;
1161     sso_cfg.s.dwb = cvmx_helper_cfg_opt_get(CVMX_HELPER_CFG_OPT_USE_DWB);
1162     sso_cfg.s.rwq_byp_dis = 0;
1163     sso_cfg.s.rwio_byp_dis = 0;
1164     cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64);
1165
1166     return 0;
1167 }
1168
1169 int cvmx_helper_uninitialize_sso(void)
1170 {
1171     cvmx_fpa_quex_available_t queue_available;
1172     cvmx_sso_cfg_t sso_cfg;
1173     cvmx_sso_rwq_pop_fptr_t pop_fptr;
1174     cvmx_sso_rwq_psh_fptr_t fptr;
1175     cvmx_sso_fpage_cnt_t fpage_cnt;
1176     int num_to_transfer, i;
1177     char *mem;
1178
1179     if (!OCTEON_IS_MODEL(OCTEON_CN68XX))
1180         return 0;
1181
1182     sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG);
1183     sso_cfg.s.rwen = 0;
1184     sso_cfg.s.rwq_byp_dis = 1;
1185     cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64);
1186     cvmx_read_csr(CVMX_SSO_CFG);
1187     queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8));
1188
1189     /* Make CVMX_FPA_QUEX_AVAILABLE(8) % 16 == 0*/
1190     for (num_to_transfer = (16 - queue_available.s.que_siz) % 16;
1191          num_to_transfer > 0; num_to_transfer--) {
1192         do {
1193             pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR);
1194         } while (!pop_fptr.s.val);
1195         for (;;) {
1196             fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR);
1197             if (!fptr.s.full)
1198                 break;
1199             cvmx_wait(1000);
1200         }
1201         fptr.s.fptr = pop_fptr.s.fptr;
1202         cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64);
1203     }
1204     cvmx_read_csr(CVMX_SSO_CFG);
1205
1206     do {
1207         queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8));
1208     } while (queue_available.s.que_siz % 16);
1209
1210     sso_cfg.s.rwen = 1;
1211     sso_cfg.s.rwq_byp_dis = 0;
1212     cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64);
1213
1214     for (i = 0; i < 8; i++) {
1215         cvmx_sso_rwq_head_ptrx_t head_ptr;
1216         cvmx_sso_rwq_tail_ptrx_t tail_ptr;
1217
1218         head_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_HEAD_PTRX(i));
1219         tail_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_TAIL_PTRX(i));
1220         if (head_ptr.s.ptr != tail_ptr.s.ptr) {
1221             cvmx_dprintf("head_ptr.s.ptr != tail_ptr.s.ptr, idx: %d\n", i);
1222         }
1223
1224         mem = cvmx_phys_to_ptr(((uint64_t)head_ptr.s.ptr) << 7);
1225         /* Leak the memory */
1226     }
1227
1228     do {
1229         do {
1230             pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR);
1231             if (pop_fptr.s.val) {
1232                 mem = cvmx_phys_to_ptr(((uint64_t)pop_fptr.s.fptr) << 7);
1233                 /* Leak the memory */
1234             }
1235         } while (pop_fptr.s.val);
1236         fpage_cnt.u64 = cvmx_read_csr(CVMX_SSO_FPAGE_CNT);
1237     } while (fpage_cnt.s.fpage_cnt);
1238
1239     sso_cfg.s.rwen = 0;
1240     sso_cfg.s.rwq_byp_dis = 0;
1241     cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64);
1242
1243     return 0;
1244 }
1245
1246 /**
1247  * Initialize the PIP, IPD, and PKO hardware to support
1248  * simple priority based queues for the ethernet ports. Each
1249  * port is configured with a number of priority queues based
1250  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1251  * priority than the previous.
1252  *
1253  * @return Zero on success, non-zero on failure
1254  */
1255 int cvmx_helper_initialize_packet_io_global(void)
1256 {
1257     int result = 0;
1258     int interface;
1259     cvmx_l2c_cfg_t l2c_cfg;
1260     cvmx_smix_en_t smix_en;
1261     const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1262
1263     /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */
1264     if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1265         __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1266
1267     /* Tell L2 to give the IOB statically higher priority compared to the
1268         cores. This avoids conditions where IO blocks might be starved under
1269         very high L2 loads */
1270     if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX))
1271     {
1272         cvmx_l2c_ctl_t l2c_ctl;
1273         l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL);
1274         l2c_ctl.s.rsp_arb_mode = 1;
1275         l2c_ctl.s.xmc_arb_mode = 0;
1276         cvmx_write_csr(CVMX_L2C_CTL, l2c_ctl.u64);
1277     }
1278     else
1279     {
1280         l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1281         l2c_cfg.s.lrf_arb_mode = 0;
1282         l2c_cfg.s.rfb_arb_mode = 0;
1283         cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1284     }
1285
1286     if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
1287     {
1288         int smi_inf = 1;
1289         int i;
1290
1291         /* Newer chips have more than one SMI/MDIO interface */
1292         if (OCTEON_IS_MODEL(OCTEON_CN68XX))
1293             smi_inf = 4;
1294         else if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) 
1295                  && !OCTEON_IS_MODEL(OCTEON_CN58XX) 
1296                  && !OCTEON_IS_MODEL(OCTEON_CN50XX))
1297             smi_inf = 2;
1298
1299         for (i = 0; i < smi_inf; i++)
1300         {
1301             /* Make sure SMI/MDIO is enabled so we can query PHYs */
1302             smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(i));
1303             if (!smix_en.s.en)
1304             {
1305                 smix_en.s.en = 1;
1306                 cvmx_write_csr(CVMX_SMIX_EN(i), smix_en.u64);
1307             }
1308         }
1309     }
1310
1311     __cvmx_helper_cfg_init();
1312
1313     for (interface=0; interface<num_interfaces; interface++)
1314         result |= cvmx_helper_interface_probe(interface);
1315
1316     cvmx_pko_initialize_global();
1317     for (interface=0; interface<num_interfaces; interface++)
1318     {
1319         if (cvmx_helper_ports_on_interface(interface) > 0)
1320             cvmx_dprintf("Interface %d has %d ports (%s)\n",
1321                      interface, cvmx_helper_ports_on_interface(interface),
1322                      cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface)));
1323         result |= __cvmx_helper_interface_setup_ipd(interface);
1324         if (!OCTEON_IS_MODEL(OCTEON_CN68XX))
1325             result |= __cvmx_helper_interface_setup_pko(interface);
1326     }
1327
1328     result |= __cvmx_helper_global_setup_ipd();
1329     result |= __cvmx_helper_global_setup_pko();
1330
1331     /* Enable any flow control and backpressure */
1332     result |= __cvmx_helper_global_setup_backpressure();
1333
1334 #if CVMX_HELPER_ENABLE_IPD
1335     result |= cvmx_helper_ipd_and_packet_input_enable();
1336 #endif
1337     return result;
1338 }
1339 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1340 EXPORT_SYMBOL(cvmx_helper_initialize_packet_io_global);
1341 #endif
1342
1343
1344 /**
1345  * Does core local initialization for packet io
1346  *
1347  * @return Zero on success, non-zero on failure
1348  */
1349 int cvmx_helper_initialize_packet_io_local(void)
1350 {
1351     return cvmx_pko_initialize_local();
1352 }
1353
1354 /**
1355  * wait for the pko queue to drain
1356  *
1357  * @param queue a valid pko queue
1358  * @return count is the length of the queue after calling this
1359  * function
1360  */
1361 static int cvmx_helper_wait_pko_queue_drain(int queue)
1362 {
1363     const int timeout = 5; /* Wait up to 5 seconds for timeouts */
1364     int count;
1365     uint64_t start_cycle, stop_cycle;
1366
1367     count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue));
1368     start_cycle = cvmx_get_cycle();
1369     stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout;
1370     while (count && (cvmx_get_cycle() < stop_cycle))
1371     {
1372         cvmx_wait(10000);
1373         count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue));
1374     }
1375
1376     return count;
1377 }
1378
1379 struct cvmx_buffer_list {
1380     struct cvmx_buffer_list *next;
1381 };
1382
1383 /**
1384  * Undo the initialization performed in
1385  * cvmx_helper_initialize_packet_io_global(). After calling this routine and the
1386  * local version on each core, packet IO for Octeon will be disabled and placed
1387  * in the initial reset state. It will then be safe to call the initialize
1388  * later on. Note that this routine does not empty the FPA pools. It frees all
1389  * buffers used by the packet IO hardware to the FPA so a function emptying the
1390  * FPA after shutdown should find all packet buffers in the FPA.
1391  *
1392  * @return Zero on success, negative on failure.
1393  */
1394 int cvmx_helper_shutdown_packet_io_global(void)
1395 {
1396     const int timeout = 5; /* Wait up to 5 seconds for timeouts */
1397     int result = 0;
1398     int num_interfaces;
1399     int interface;
1400     int num_ports;
1401     int index;
1402     struct cvmx_buffer_list *pool0_buffers;
1403     struct cvmx_buffer_list *pool0_buffers_tail;
1404     cvmx_wqe_t *work;
1405
1406     /* Step 1: Disable all backpressure */
1407     for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++)
1408         if (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_DISABLED)
1409             cvmx_gmx_set_backpressure_override(interface, 0xf);
1410
1411 step2:
1412     /* Step 2: Wait for the PKO queues to drain */
1413     if (octeon_has_feature(OCTEON_FEATURE_PKND))
1414     {
1415         int queue, max_queue;
1416
1417         max_queue = __cvmx_helper_cfg_pko_max_queue();
1418         for (queue = 0; queue < max_queue; queue++)
1419         {
1420             if (cvmx_helper_wait_pko_queue_drain(queue))
1421             {
1422                 result = -1;
1423                 goto step3;
1424             }
1425         }
1426     }
1427     else
1428     {
1429         num_interfaces = cvmx_helper_get_number_of_interfaces();
1430         for (interface=0; interface<num_interfaces; interface++)
1431         {
1432             num_ports = cvmx_helper_ports_on_interface(interface);
1433             for (index=0; index<num_ports; index++)
1434             {
1435                 int pko_port = cvmx_helper_get_ipd_port(interface, index);
1436                 int queue = cvmx_pko_get_base_queue(pko_port);
1437                 int max_queue = queue + cvmx_pko_get_num_queues(pko_port);
1438                 while (queue < max_queue)
1439                 {
1440                     if (cvmx_helper_wait_pko_queue_drain(queue))
1441                     {
1442                         result = -1;
1443                         goto step3;
1444                     }
1445                     queue++;
1446                 }
1447             }
1448         }
1449     }
1450
1451 step3:
1452     /* Step 3: Disable TX and RX on all ports */
1453     for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++)
1454     {
1455         switch (cvmx_helper_interface_get_mode(interface))
1456         {
1457             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1458             case CVMX_HELPER_INTERFACE_MODE_PCIE:
1459                 /* Not a packet interface */
1460                 break;
1461             case CVMX_HELPER_INTERFACE_MODE_NPI:
1462             case CVMX_HELPER_INTERFACE_MODE_SRIO:
1463             case CVMX_HELPER_INTERFACE_MODE_ILK:
1464                 /* We don't handle the NPI/NPEI/SRIO packet engines. The caller
1465                     must know these are idle */
1466                 break;
1467             case CVMX_HELPER_INTERFACE_MODE_LOOP:
1468                 /* Nothing needed. Once PKO is idle, the loopback devices
1469                     must be idle */
1470                 break;
1471             case CVMX_HELPER_INTERFACE_MODE_SPI:
1472                 /* SPI cannot be disabled from Octeon. It is the responsibility
1473                     of the caller to make sure SPI is idle before doing
1474                     shutdown */
1475                 /* Fall through and do the same processing as RGMII/GMII */
1476             case CVMX_HELPER_INTERFACE_MODE_GMII:
1477             case CVMX_HELPER_INTERFACE_MODE_RGMII:
1478                 /* Disable outermost RX at the ASX block */
1479                 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), 0);
1480                 num_ports = cvmx_helper_ports_on_interface(interface);
1481                 if (num_ports > 4)
1482                     num_ports = 4;
1483                 for (index=0; index<num_ports; index++)
1484                 {
1485                     cvmx_gmxx_prtx_cfg_t gmx_cfg;
1486                     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
1487                     gmx_cfg.s.en = 0;
1488                     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
1489                     /* Poll the GMX state machine waiting for it to become idle */
1490                     cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880);
1491                     if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, timeout*1000000))
1492                     {
1493                         cvmx_dprintf("GMX RX path timeout waiting for idle\n");
1494                         result = -1;
1495                     }
1496                     if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, timeout*1000000))
1497                     {
1498                         cvmx_dprintf("GMX TX path timeout waiting for idle\n");
1499                         result = -1;
1500                     }
1501                 }
1502                 /* Disable outermost TX at the ASX block */
1503                 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), 0);
1504                 /* Disable interrupts for interface */
1505                 cvmx_write_csr(CVMX_ASXX_INT_EN(interface), 0);
1506                 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0);
1507                 break;
1508             case CVMX_HELPER_INTERFACE_MODE_XAUI:
1509             case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1510             case CVMX_HELPER_INTERFACE_MODE_SGMII:
1511             case CVMX_HELPER_INTERFACE_MODE_PICMG:
1512                 num_ports = cvmx_helper_ports_on_interface(interface);
1513                 if (num_ports > 4)
1514                     num_ports = 4;
1515                 for (index=0; index<num_ports; index++)
1516                 {
1517                     cvmx_gmxx_prtx_cfg_t gmx_cfg;
1518                     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
1519                     gmx_cfg.s.en = 0;
1520                     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
1521                     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, timeout*1000000))
1522                     {
1523                         cvmx_dprintf("GMX RX path timeout waiting for idle\n");
1524                         result = -1;
1525                     }
1526                     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, timeout*1000000))
1527                     {
1528                         cvmx_dprintf("GMX TX path timeout waiting for idle\n");
1529                         result = -1;
1530                     }
1531                 }
1532                 break;
1533         }
1534     }
1535
1536     /* Step 4: Retrieve all packets from the POW and free them */
1537     while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT)))
1538     {
1539         cvmx_helper_free_packet_data(work);
1540         cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 0);
1541     }
1542
1543     /* Step 4b: Special workaround for pass 2 errata */
1544     if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
1545     {
1546         cvmx_ipd_ptr_count_t ipd_cnt;
1547         int to_add;
1548         ipd_cnt.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
1549         to_add = (ipd_cnt.s.wqev_cnt + ipd_cnt.s.wqe_pcnt) & 0x7;
1550         if (to_add)
1551         {
1552             int port = -1;
1553             cvmx_dprintf("Aligning CN38XX pass 2 IPD counters\n");
1554             if (cvmx_helper_interface_get_mode(0) == CVMX_HELPER_INTERFACE_MODE_RGMII)
1555                 port = 0;
1556             else if (cvmx_helper_interface_get_mode(1) == CVMX_HELPER_INTERFACE_MODE_RGMII)
1557                 port = 16;
1558
1559             if (port != -1)
1560             {
1561                 char *buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
1562                 if (buffer)
1563                 {
1564                     int queue = cvmx_pko_get_base_queue(port);
1565                     cvmx_pko_command_word0_t pko_command;
1566                     cvmx_buf_ptr_t packet;
1567                     uint64_t start_cycle;
1568                     uint64_t stop_cycle;
1569
1570                     /* Populate a minimal packet */
1571                     memset(buffer, 0xff, 6);
1572                     memset(buffer+6, 0, 54);
1573                     pko_command.u64 = 0;
1574                     pko_command.s.dontfree = 1;
1575                     pko_command.s.total_bytes = 60;
1576                     pko_command.s.segs = 1;
1577                     packet.u64 = 0;
1578                     packet.s.addr = cvmx_ptr_to_phys(buffer);
1579                     packet.s.size = CVMX_FPA_PACKET_POOL_SIZE;
1580                     __cvmx_helper_rgmii_configure_loopback(port, 1, 0);
1581                     while (to_add--)
1582                     {
1583                         cvmx_pko_send_packet_prepare(port, queue, CVMX_PKO_LOCK_CMD_QUEUE);
1584                         if (cvmx_pko_send_packet_finish(port, queue, pko_command, packet, CVMX_PKO_LOCK_CMD_QUEUE))
1585                         {
1586                             cvmx_dprintf("ERROR: Unable to align IPD counters (PKO failed)\n");
1587                             break;
1588                         }
1589                     }
1590                     cvmx_fpa_free(buffer, CVMX_FPA_PACKET_POOL, 0);
1591
1592                     /* Wait for the packets to loop back */
1593                     start_cycle = cvmx_get_cycle();
1594                     stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout;
1595                     while (cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)) &&
1596                            (cvmx_get_cycle() < stop_cycle))
1597                     {
1598                         cvmx_wait(1000);
1599                     }
1600                     cvmx_wait(1000);
1601                     __cvmx_helper_rgmii_configure_loopback(port, 0, 0);
1602                     if (to_add == -1)
1603                         goto step2;
1604                 }
1605                 else
1606                     cvmx_dprintf("ERROR: Unable to align IPD counters (Packet pool empty)\n");
1607             }
1608             else
1609                 cvmx_dprintf("ERROR: Unable to align IPD counters\n");
1610         }
1611     }
1612
1613     /* Step 5 */
1614     cvmx_ipd_disable();
1615
1616     /* Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP
1617         have not been reset yet */
1618     __cvmx_ipd_free_ptr();
1619
1620     /* Step 7: Free the PKO command buffers and put PKO in reset */
1621     cvmx_pko_shutdown();
1622
1623     /* Step 8: Disable MAC address filtering */
1624     for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++)
1625     {
1626         switch (cvmx_helper_interface_get_mode(interface))
1627         {
1628             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1629             case CVMX_HELPER_INTERFACE_MODE_PCIE:
1630             case CVMX_HELPER_INTERFACE_MODE_SRIO:
1631             case CVMX_HELPER_INTERFACE_MODE_ILK:
1632             case CVMX_HELPER_INTERFACE_MODE_NPI:
1633             case CVMX_HELPER_INTERFACE_MODE_LOOP:
1634                 break;
1635             case CVMX_HELPER_INTERFACE_MODE_XAUI:
1636             case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1637             case CVMX_HELPER_INTERFACE_MODE_GMII:
1638             case CVMX_HELPER_INTERFACE_MODE_RGMII:
1639             case CVMX_HELPER_INTERFACE_MODE_SPI:
1640             case CVMX_HELPER_INTERFACE_MODE_SGMII:
1641             case CVMX_HELPER_INTERFACE_MODE_PICMG:
1642                 num_ports = cvmx_helper_ports_on_interface(interface);
1643                 if (num_ports > 4)
1644                     num_ports = 4;
1645                 for (index=0; index<num_ports; index++)
1646                 {
1647                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1);
1648                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0);
1649                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0);
1650                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0);
1651                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0);
1652                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0);
1653                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0);
1654                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0);
1655                 }
1656                 break;
1657         }
1658     }
1659
1660     /* Step 9: Drain all FPA buffers out of pool 0 before we reset
1661      * IPD/PIP.  This is needed to keep IPD_QUE0_FREE_PAGE_CNT in
1662      * sync. We temporarily keep the buffers in the pool0_buffers
1663      * list.
1664      */
1665     pool0_buffers = NULL;
1666     pool0_buffers_tail = NULL;
1667     while (1)
1668     {
1669         struct cvmx_buffer_list *buffer = cvmx_fpa_alloc(0);
1670         if (buffer) {
1671             buffer->next = NULL;
1672
1673             if (pool0_buffers == NULL)
1674                 pool0_buffers = buffer;
1675             else
1676                 pool0_buffers_tail->next = buffer;
1677
1678             pool0_buffers_tail = buffer;
1679         }
1680         else
1681             break;
1682     }
1683
1684     /* Step 10: Reset IPD and PIP */
1685     {
1686         cvmx_ipd_ctl_status_t ipd_ctl_status;
1687         ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
1688         ipd_ctl_status.s.reset = 1;
1689         cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
1690
1691         if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
1692             (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)))
1693         {
1694             /* only try 1000 times.  Normally if this works it will happen in
1695             ** the first 50 loops. */
1696             int max_loops = 1000;
1697             int loop = 0;
1698             /* Per port backpressure counters can get misaligned after an
1699                IPD reset. This code realigns them by performing repeated
1700                resets. See IPD-13473 */
1701             cvmx_wait(100);
1702             if (__cvmx_helper_backpressure_is_misaligned())
1703             {
1704                 cvmx_dprintf("Starting to align per port backpressure counters.\n");
1705                 while (__cvmx_helper_backpressure_is_misaligned() && (loop++ < max_loops))
1706                 {
1707                     cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
1708                     cvmx_wait(123);
1709                 }
1710                 if (loop < max_loops)
1711                     cvmx_dprintf("Completed aligning per port backpressure counters (%d loops).\n", loop);
1712                 else
1713                 {
1714                     cvmx_dprintf("ERROR: unable to align per port backpressure counters.\n");
1715                     /* For now, don't hang.... */
1716                 }
1717             }
1718         }
1719
1720         /* PIP_SFT_RST not present in CN38XXp{1,2} */
1721         if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
1722         {
1723             cvmx_pip_sft_rst_t pip_sft_rst;
1724             pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST);
1725             pip_sft_rst.s.rst = 1;
1726             cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64);
1727         }
1728
1729         /* Make sure IPD has finished reset. */
1730         if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
1731         {
1732             if (CVMX_WAIT_FOR_FIELD64(CVMX_IPD_CTL_STATUS, cvmx_ipd_ctl_status_t, rst_done, ==, 0, 1000))
1733             {
1734                 cvmx_dprintf("IPD reset timeout waiting for idle\n");
1735                 result = -1;
1736             }
1737         }
1738     }
1739
1740     /* Step 11: Restore the FPA buffers into pool 0 */
1741     while (pool0_buffers) {
1742         struct cvmx_buffer_list *n = pool0_buffers->next;
1743         cvmx_fpa_free(pool0_buffers, 0, 0);
1744         pool0_buffers = n;
1745     }
1746
1747     /* Step 12: Release interface structures */
1748     __cvmx_helper_shutdown_interfaces();
1749
1750     return result;
1751 }
1752 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1753 EXPORT_SYMBOL(cvmx_helper_shutdown_packet_io_global);
1754 #endif
1755
1756
1757 /**
1758  * Does core local shutdown of packet io
1759  *
1760  * @return Zero on success, non-zero on failure
1761  */
1762 int cvmx_helper_shutdown_packet_io_local(void)
1763 {
1764     /* Currently there is nothing to do per core. This may change in
1765         the future */
1766     return 0;
1767 }
1768
1769
1770
1771 /**
1772  * Auto configure an IPD/PKO port link state and speed. This
1773  * function basically does the equivalent of:
1774  * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
1775  *
1776  * @param ipd_port IPD/PKO port to auto configure
1777  *
1778  * @return Link state after configure
1779  */
1780 cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
1781 {
1782     cvmx_helper_link_info_t link_info;
1783     int interface = cvmx_helper_get_interface_num(ipd_port);
1784     int index = cvmx_helper_get_interface_index_num(ipd_port);
1785
1786     if (index >= cvmx_helper_ports_on_interface(interface))
1787     {
1788         link_info.u64 = 0;
1789         return link_info;
1790     }
1791
1792     link_info = cvmx_helper_link_get(ipd_port);
1793     if (link_info.u64 == (__cvmx_helper_get_link_info(interface, index)).u64)
1794         return link_info;
1795
1796 #if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)
1797     if (!link_info.s.link_up)
1798         cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port);
1799 #endif
1800
1801     /* If we fail to set the link speed, port_link_info will not change */
1802     cvmx_helper_link_set(ipd_port, link_info);
1803
1804 #if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)
1805     if (link_info.s.link_up)
1806         cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port);
1807 #endif
1808
1809     return link_info;
1810 }
1811 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1812 EXPORT_SYMBOL(cvmx_helper_link_autoconf);
1813 #endif
1814
1815 /**
1816  * Return the link state of an IPD/PKO port as returned by
1817  * auto negotiation. The result of this function may not match
1818  * Octeon's link config if auto negotiation has changed since
1819  * the last call to cvmx_helper_link_set().
1820  *
1821  * @param ipd_port IPD/PKO port to query
1822  *
1823  * @return Link state
1824  */
1825 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1826 {
1827     cvmx_helper_link_info_t result;
1828     int interface = cvmx_helper_get_interface_num(ipd_port);
1829     int index = cvmx_helper_get_interface_index_num(ipd_port);
1830
1831     /* The default result will be a down link unless the code below
1832         changes it */
1833     result.u64 = 0;
1834
1835     if (index >= cvmx_helper_ports_on_interface(interface))
1836         return result;
1837
1838     switch (cvmx_helper_interface_get_mode(interface))
1839     {
1840         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1841         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1842             /* Network links are not supported */
1843             break;
1844         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1845         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1846             result = __cvmx_helper_xaui_link_get(ipd_port);
1847             break;
1848         case CVMX_HELPER_INTERFACE_MODE_GMII:
1849             if (index == 0)
1850                 result = __cvmx_helper_rgmii_link_get(ipd_port);
1851             else
1852             {
1853                 result.s.full_duplex = 1;
1854                 result.s.link_up = 1;
1855                 result.s.speed = 1000;
1856             }
1857             break;
1858         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1859             result = __cvmx_helper_rgmii_link_get(ipd_port);
1860             break;
1861         case CVMX_HELPER_INTERFACE_MODE_SPI:
1862             result = __cvmx_helper_spi_link_get(ipd_port);
1863             break;
1864         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1865         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1866             result = __cvmx_helper_sgmii_link_get(ipd_port);
1867             break;
1868         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1869             result = __cvmx_helper_srio_link_get(ipd_port);
1870             break;
1871         case CVMX_HELPER_INTERFACE_MODE_ILK:
1872             result = __cvmx_helper_ilk_link_get(ipd_port);
1873             break;
1874         case CVMX_HELPER_INTERFACE_MODE_NPI:
1875         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1876             /* Network links are not supported */
1877             break;
1878     }
1879     return result;
1880 }
1881 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1882 EXPORT_SYMBOL(cvmx_helper_link_get);
1883 #endif
1884
1885
1886 /**
1887  * Configure an IPD/PKO port for the specified link state. This
1888  * function does not influence auto negotiation at the PHY level.
1889  * The passed link state must always match the link state returned
1890  * by cvmx_helper_link_get(). It is normally best to use
1891  * cvmx_helper_link_autoconf() instead.
1892  *
1893  * @param ipd_port  IPD/PKO port to configure
1894  * @param link_info The new link state
1895  *
1896  * @return Zero on success, negative on failure
1897  */
1898 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1899 {
1900     int result = -1;
1901     int interface = cvmx_helper_get_interface_num(ipd_port);
1902     int index = cvmx_helper_get_interface_index_num(ipd_port);
1903
1904     if (index >= cvmx_helper_ports_on_interface(interface))
1905         return -1;
1906
1907     switch (cvmx_helper_interface_get_mode(interface))
1908     {
1909         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1910         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1911             break;
1912         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1913         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1914             result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1915             break;
1916         /* RGMII/GMII/MII are all treated about the same. Most functions
1917             refer to these ports as RGMII */
1918         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1919         case CVMX_HELPER_INTERFACE_MODE_GMII:
1920             result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1921             break;
1922         case CVMX_HELPER_INTERFACE_MODE_SPI:
1923             result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1924             break;
1925         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1926         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1927             result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1928             break;
1929         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1930             result = __cvmx_helper_srio_link_set(ipd_port, link_info);
1931             break;
1932         case CVMX_HELPER_INTERFACE_MODE_ILK:
1933             result = __cvmx_helper_ilk_link_set(ipd_port, link_info);
1934             break;
1935         case CVMX_HELPER_INTERFACE_MODE_NPI:
1936         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1937             break;
1938     }
1939     /* Set the port_link_info here so that the link status is updated
1940        no matter how cvmx_helper_link_set is called. We don't change
1941        the value if link_set failed */
1942     if (result == 0)
1943         __cvmx_helper_set_link_info(interface, index, link_info);
1944     return result;
1945 }
1946 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1947 EXPORT_SYMBOL(cvmx_helper_link_set);
1948 #endif
1949
1950
1951 /**
1952  * Configure a port for internal and/or external loopback. Internal loopback
1953  * causes packets sent by the port to be received by Octeon. External loopback
1954  * causes packets received from the wire to sent out again.
1955  *
1956  * @param ipd_port IPD/PKO port to loopback.
1957  * @param enable_internal
1958  *                 Non zero if you want internal loopback
1959  * @param enable_external
1960  *                 Non zero if you want external loopback
1961  *
1962  * @return Zero on success, negative on failure.
1963  */
1964 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external)
1965 {
1966     int result = -1;
1967     int interface = cvmx_helper_get_interface_num(ipd_port);
1968     int index = cvmx_helper_get_interface_index_num(ipd_port);
1969
1970     if (index >= cvmx_helper_ports_on_interface(interface))
1971         return -1;
1972
1973     switch (cvmx_helper_interface_get_mode(interface))
1974     {
1975         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1976         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1977         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1978         case CVMX_HELPER_INTERFACE_MODE_ILK:
1979         case CVMX_HELPER_INTERFACE_MODE_SPI:
1980         case CVMX_HELPER_INTERFACE_MODE_NPI:
1981         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1982             break;
1983         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1984         case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1985             result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external);
1986             break;
1987         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1988         case CVMX_HELPER_INTERFACE_MODE_GMII:
1989             result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external);
1990             break;
1991         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1992         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1993             result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external);
1994             break;
1995     }
1996     return result;
1997 }
1998
1999 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */