]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/contrib/octeon-sdk/cvmx-helper.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / contrib / octeon-sdk / cvmx-helper.c
1 /***********************license start***************
2  * Copyright (c) 2003-2010  Cavium Networks (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 Networks 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  NETWORKS 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: 52004 $<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-pexp-defs.h>
61 #include <asm/octeon/cvmx-pip-defs.h>
62 #include <asm/octeon/cvmx-asxx-defs.h>
63 #include <asm/octeon/cvmx-gmxx-defs.h>
64 #include <asm/octeon/cvmx-smix-defs.h>
65 #include <asm/octeon/cvmx-dbg-defs.h>
66
67 #include <asm/octeon/cvmx-gmx.h>
68 #include <asm/octeon/cvmx-fpa.h>
69 #include <asm/octeon/cvmx-pip.h>
70 #include <asm/octeon/cvmx-pko.h>
71 #include <asm/octeon/cvmx-ipd.h>
72 #include <asm/octeon/cvmx-spi.h>
73 #include <asm/octeon/cvmx-clock.h>
74 #include <asm/octeon/cvmx-helper.h>
75 #include <asm/octeon/cvmx-helper-board.h>
76 #include <asm/octeon/cvmx-helper-errata.h>
77 #else
78 #if !defined(__FreeBSD__) || !defined(_KERNEL)
79 #include "executive-config.h"
80 #endif
81 #include "cvmx.h"
82 #include "cvmx-sysinfo.h"
83 #include "cvmx-bootmem.h"
84 #include "cvmx-version.h"
85 #include "cvmx-helper-check-defines.h"
86 #include "cvmx-gmx.h"
87 #include "cvmx-error.h"
88 #if !defined(__FreeBSD__) || !defined(_KERNEL)
89 #include "cvmx-config.h"
90 #endif
91
92 #include "cvmx-fpa.h"
93 #include "cvmx-pip.h"
94 #include "cvmx-pko.h"
95 #include "cvmx-ipd.h"
96 #include "cvmx-spi.h"
97 #include "cvmx-helper.h"
98 #include "cvmx-helper-board.h"
99 #include "cvmx-helper-errata.h"
100 #endif
101
102
103
104 #ifdef CVMX_ENABLE_PKO_FUNCTIONS
105
106 /**
107  * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
108  * priorities[16]) is a function pointer. It is meant to allow
109  * customization of the PKO queue priorities based on the port
110  * number. Users should set this pointer to a function before
111  * calling any cvmx-helper operations.
112  */
113 CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int pko_port, uint64_t priorities[16]) = NULL;
114 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
115 EXPORT_SYMBOL(cvmx_override_pko_queue_priority);
116 #endif
117
118 /**
119  * cvmx_override_ipd_port_setup(int ipd_port) is a function
120  * pointer. It is meant to allow customization of the IPD port
121  * setup before packet input/output comes online. It is called
122  * after cvmx-helper does the default IPD configuration, but
123  * before IPD is enabled. Users should set this pointer to a
124  * function before calling any cvmx-helper operations.
125  */
126 CVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL;
127
128 /* Port count per interface */
129 static CVMX_SHARED int interface_port_count[6] = {0,};
130 /* Port last configured link info index by IPD/PKO port */
131 static CVMX_SHARED cvmx_helper_link_info_t port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
132
133
134 /**
135  * Return the number of interfaces the chip has. Each interface
136  * may have multiple ports. Most chips support two interfaces,
137  * but the CNX0XX and CNX1XX are exceptions. These only support
138  * one interface.
139  *
140  * @return Number of interfaces on chip
141  */
142 int cvmx_helper_get_number_of_interfaces(void)
143 {
144     switch (cvmx_sysinfo_get()->board_type) {
145 #if defined(OCTEON_VENDOR_LANNER)
146         case CVMX_BOARD_TYPE_CUST_LANNER_MR955:
147             return 2;
148         case CVMX_BOARD_TYPE_CUST_LANNER_MR730:
149             return 1;
150 #endif
151         default:
152             break;
153     }
154
155     if (OCTEON_IS_MODEL(OCTEON_CN63XX))
156         return 6;
157     else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
158         return 4;
159     else
160         return 3;
161 }
162 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
163 EXPORT_SYMBOL(cvmx_helper_get_number_of_interfaces);
164 #endif
165
166
167 /**
168  * Return the number of ports on an interface. Depending on the
169  * chip and configuration, this can be 1-16. A value of 0
170  * specifies that the interface doesn't exist or isn't usable.
171  *
172  * @param interface Interface to get the port count for
173  *
174  * @return Number of ports on interface. Can be Zero.
175  */
176 int cvmx_helper_ports_on_interface(int interface)
177 {
178     return interface_port_count[interface];
179 }
180 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
181 EXPORT_SYMBOL(cvmx_helper_ports_on_interface);
182 #endif
183
184
185 /**
186  * Get the operating mode of an interface. Depending on the Octeon
187  * chip and configuration, this function returns an enumeration
188  * of the type of packet I/O supported by an interface.
189  *
190  * @param interface Interface to probe
191  *
192  * @return Mode of the interface. Unknown or unsupported interfaces return
193  *         DISABLED.
194  */
195 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
196 {
197     cvmx_gmxx_inf_mode_t mode;
198     if (interface == 2)
199         return CVMX_HELPER_INTERFACE_MODE_NPI;
200
201     if (interface == 3)
202     {
203         if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN6XXX))
204             return CVMX_HELPER_INTERFACE_MODE_LOOP;
205         else
206             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
207     }
208
209     if (OCTEON_IS_MODEL(OCTEON_CN6XXX) && (interface == 4 || interface == 5))
210     {
211         cvmx_sriox_status_reg_t sriox_status_reg;
212         sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(interface-4));
213         if (sriox_status_reg.s.srio)
214             return CVMX_HELPER_INTERFACE_MODE_SRIO;
215         else
216             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
217     }
218
219     if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1)
220     {
221         /* Lie about interface type of CN3005 board.  This board has a switch on port 1 like
222         ** the other evaluation boards, but it is connected over RGMII instead of GMII.  Report
223         ** GMII mode so that the speed is forced to 1 Gbit full duplex.  Other than some initial configuration
224         ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes.
225         */
226         return CVMX_HELPER_INTERFACE_MODE_GMII;
227     }
228
229     /* Interface 1 is always disabled on CN31XX and CN30XX */
230     if ((interface == 1) && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX)))
231         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
232
233     mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
234
235     if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
236     {
237         switch(mode.cn56xx.mode)
238         {
239             case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED;
240             case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI;
241             case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII;
242             case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG;
243             default:return CVMX_HELPER_INTERFACE_MODE_DISABLED;
244         }
245     }
246     else if (OCTEON_IS_MODEL(OCTEON_CN63XX))
247     {
248         switch(mode.cn63xx.mode)
249         {
250             case 0: return CVMX_HELPER_INTERFACE_MODE_SGMII;
251             case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI;
252             default: return CVMX_HELPER_INTERFACE_MODE_DISABLED;
253         }
254     }
255     else
256     {
257         if (!mode.s.en)
258             return CVMX_HELPER_INTERFACE_MODE_DISABLED;
259
260         if (mode.s.type)
261         {
262             if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
263                 return CVMX_HELPER_INTERFACE_MODE_SPI;
264             else
265                 return CVMX_HELPER_INTERFACE_MODE_GMII;
266         }
267         else
268             return CVMX_HELPER_INTERFACE_MODE_RGMII;
269     }
270 }
271 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
272 EXPORT_SYMBOL(cvmx_helper_interface_get_mode);
273 #endif
274
275 /**
276  * @INTERNAL
277  * Configure the IPD/PIP tagging and QoS options for a specific
278  * port. This function determines the POW work queue entry
279  * contents for a port. The setup performed here is controlled by
280  * the defines in executive-config.h.
281  *
282  * @param ipd_port Port to configure. This follows the IPD numbering, not the
283  *                 per interface numbering
284  *
285  * @return Zero on success, negative on failure
286  */
287 static int __cvmx_helper_port_setup_ipd(int ipd_port)
288 {
289     cvmx_pip_prt_cfgx_t port_config;
290     cvmx_pip_prt_tagx_t tag_config;
291
292     port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
293     tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
294
295     /* Have each port go to a different POW queue */
296     port_config.s.qos = ipd_port & 0x7;
297
298     /* Process the headers and place the IP header in the work queue */
299     port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
300
301     tag_config.s.ip6_src_flag  = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
302     tag_config.s.ip6_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
303     tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
304     tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
305     tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
306     tag_config.s.ip4_src_flag  = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
307     tag_config.s.ip4_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
308     tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
309     tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
310     tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
311     tag_config.s.inc_prt_flag  = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
312     tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
313     tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
314     tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
315     tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
316     tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
317     /* Put all packets in group 0. Other groups can be used by the app */
318     tag_config.s.grp = 0;
319
320     cvmx_pip_config_port(ipd_port, port_config, tag_config);
321
322     /* Give the user a chance to override our setting for each port */
323     if (cvmx_override_ipd_port_setup)
324         cvmx_override_ipd_port_setup(ipd_port);
325
326     return 0;
327 }
328
329
330 /**
331  * This function probes an interface to determine the actual
332  * number of hardware ports connected to it. It doesn't setup the
333  * ports or enable them. The main goal here is to set the global
334  * interface_port_count[interface] correctly. Hardware setup of the
335  * ports will be performed later.
336  *
337  * @param interface Interface to probe
338  *
339  * @return Zero on success, negative on failure
340  */
341 int cvmx_helper_interface_probe(int interface)
342 {
343     /* At this stage in the game we don't want packets to be moving yet.
344         The following probe calls should perform hardware setup
345         needed to determine port counts. Receive must still be disabled */
346     switch (cvmx_helper_interface_get_mode(interface))
347     {
348         /* These types don't support ports to IPD/PKO */
349         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
350         case CVMX_HELPER_INTERFACE_MODE_PCIE:
351             interface_port_count[interface] = 0;
352             break;
353         /* XAUI is a single high speed port */
354         case CVMX_HELPER_INTERFACE_MODE_XAUI:
355             interface_port_count[interface] = __cvmx_helper_xaui_probe(interface);
356             break;
357         /* RGMII/GMII/MII are all treated about the same. Most functions
358             refer to these ports as RGMII */
359         case CVMX_HELPER_INTERFACE_MODE_RGMII:
360         case CVMX_HELPER_INTERFACE_MODE_GMII:
361             interface_port_count[interface] = __cvmx_helper_rgmii_probe(interface);
362             break;
363         /* SPI4 can have 1-16 ports depending on the device at the other end */
364         case CVMX_HELPER_INTERFACE_MODE_SPI:
365             interface_port_count[interface] = __cvmx_helper_spi_probe(interface);
366             break;
367         /* SGMII can have 1-4 ports depending on how many are hooked up */
368         case CVMX_HELPER_INTERFACE_MODE_SGMII:
369         case CVMX_HELPER_INTERFACE_MODE_PICMG:
370             interface_port_count[interface] = __cvmx_helper_sgmii_probe(interface);
371             break;
372         /* PCI target Network Packet Interface */
373         case CVMX_HELPER_INTERFACE_MODE_NPI:
374             interface_port_count[interface] = __cvmx_helper_npi_probe(interface);
375             break;
376         /* Special loopback only ports. These are not the same as other ports
377             in loopback mode */
378         case CVMX_HELPER_INTERFACE_MODE_LOOP:
379             interface_port_count[interface] = __cvmx_helper_loop_probe(interface);
380             break;
381         /* SRIO has 2^N ports, where N is number of interfaces */
382         case CVMX_HELPER_INTERFACE_MODE_SRIO:
383             interface_port_count[interface] = __cvmx_helper_srio_probe(interface);
384             break;
385     }
386
387     interface_port_count[interface] = __cvmx_helper_board_interface_probe(interface, interface_port_count[interface]);
388
389     /* Make sure all global variables propagate to other cores */
390     CVMX_SYNCWS;
391
392     return 0;
393 }
394
395
396 /**
397  * @INTERNAL
398  * Setup the IPD/PIP for the ports on an interface. Packet
399  * classification and tagging are set for every port on the
400  * interface. The number of ports on the interface must already
401  * have been probed.
402  *
403  * @param interface Interface to setup IPD/PIP for
404  *
405  * @return Zero on success, negative on failure
406  */
407 static int __cvmx_helper_interface_setup_ipd(int interface)
408 {
409     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
410     int num_ports = interface_port_count[interface];
411
412     while (num_ports--)
413     {
414         __cvmx_helper_port_setup_ipd(ipd_port);
415         ipd_port++;
416     }
417     return 0;
418 }
419
420
421 /**
422  * @INTERNAL
423  * Setup global setting for IPD/PIP not related to a specific
424  * interface or port. This must be called before IPD is enabled.
425  *
426  * @return Zero on success, negative on failure.
427  */
428 static int __cvmx_helper_global_setup_ipd(void)
429 {
430 #ifndef CVMX_HELPER_IPD_DRAM_MODE
431 #define CVMX_HELPER_IPD_DRAM_MODE   CVMX_IPD_OPC_MODE_STT
432 #endif
433     /* Setup the global packet input options */
434     cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8,
435                     CVMX_HELPER_FIRST_MBUFF_SKIP/8,
436                     CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8,
437                     (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
438                     (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
439                     CVMX_FPA_WQE_POOL,
440                     CVMX_HELPER_IPD_DRAM_MODE,
441                     1);
442     return 0;
443 }
444
445
446 /**
447  * @INTERNAL
448  * Setup the PKO for the ports on an interface. The number of
449  * queues per port and the priority of each PKO output queue
450  * is set here. PKO must be disabled when this function is called.
451  *
452  * @param interface Interface to setup PKO for
453  *
454  * @return Zero on success, negative on failure
455  */
456 static int __cvmx_helper_interface_setup_pko(int interface)
457 {
458     /* Each packet output queue has an associated priority. The higher the
459         priority, the more often it can send a packet. A priority of 8 means
460         it can send in all 8 rounds of contention. We're going to make each
461         queue one less than the last.
462         The vector of priorities has been extended to support CN5xxx CPUs,
463         where up to 16 queues can be associated to a port.
464         To keep backward compatibility we don't change the initial 8
465         priorities and replicate them in the second half.
466         With per-core PKO queues (PKO lockless operation) all queues have
467         the same priority. */
468     uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1};
469
470     /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet
471         classification, tagging and output priorities are set */
472     int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
473     int num_ports = interface_port_count[interface];
474     while (num_ports--)
475     {
476         /* Give the user a chance to override the per queue priorities */
477         if (cvmx_override_pko_queue_priority)
478             cvmx_override_pko_queue_priority(ipd_port, priorities);
479
480         cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0),
481                              cvmx_pko_get_num_queues(ipd_port), priorities);
482         ipd_port++;
483     }
484     return 0;
485 }
486
487
488 /**
489  * @INTERNAL
490  * Setup global setting for PKO not related to a specific
491  * interface or port. This must be called before PKO is enabled.
492  *
493  * @return Zero on success, negative on failure.
494  */
495 static int __cvmx_helper_global_setup_pko(void)
496 {
497     /* Disable tagwait FAU timeout. This needs to be done before anyone might
498         start packet output using tags */
499     cvmx_iob_fau_timeout_t fau_to;
500     fau_to.u64 = 0;
501     fau_to.s.tout_val = 0xfff;
502     fau_to.s.tout_enb = 0;
503     cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
504     return 0;
505 }
506
507
508 /**
509  * @INTERNAL
510  * Setup global backpressure setting.
511  *
512  * @return Zero on success, negative on failure
513  */
514 static int __cvmx_helper_global_setup_backpressure(void)
515 {
516 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
517     /* Disable backpressure if configured to do so */
518     /* Disable backpressure (pause frame) generation */
519     int num_interfaces = cvmx_helper_get_number_of_interfaces();
520     int interface;
521     for (interface=0; interface<num_interfaces; interface++)
522     {
523         switch (cvmx_helper_interface_get_mode(interface))
524         {
525             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
526             case CVMX_HELPER_INTERFACE_MODE_PCIE:
527             case CVMX_HELPER_INTERFACE_MODE_SRIO:
528             case CVMX_HELPER_INTERFACE_MODE_NPI:
529             case CVMX_HELPER_INTERFACE_MODE_LOOP:
530             case CVMX_HELPER_INTERFACE_MODE_XAUI:
531                 break;
532             case CVMX_HELPER_INTERFACE_MODE_RGMII:
533             case CVMX_HELPER_INTERFACE_MODE_GMII:
534             case CVMX_HELPER_INTERFACE_MODE_SPI:
535             case CVMX_HELPER_INTERFACE_MODE_SGMII:
536             case CVMX_HELPER_INTERFACE_MODE_PICMG:
537                 cvmx_gmx_set_backpressure_override(interface, 0xf);
538                 break;
539         }
540     }
541     //cvmx_dprintf("Disabling backpressure\n");
542 #endif
543
544     return 0;
545 }
546
547 /**
548  * @INTERNAL
549  * Verify the per port IPD backpressure is aligned properly.
550  * @return Zero if working, non zero if misaligned
551  */
552 static int __cvmx_helper_backpressure_is_misaligned(void)
553 {
554     uint64_t ipd_int_enb;
555     cvmx_ipd_ctl_status_t ipd_reg;
556     uint64_t bp_status0;
557     uint64_t bp_status1;
558     const int port0 = 0;
559     const int port1 = 16;
560     cvmx_helper_interface_mode_t mode0 = cvmx_helper_interface_get_mode(0);
561     cvmx_helper_interface_mode_t mode1 = cvmx_helper_interface_get_mode(1);
562
563     /* Disable error interrupts while we check backpressure */
564     ipd_int_enb = cvmx_read_csr(CVMX_IPD_INT_ENB);
565     cvmx_write_csr(CVMX_IPD_INT_ENB, 0);
566
567     /* Enable per port backpressure */
568     ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
569     ipd_reg.s.pbp_en = 1;
570     cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64);
571
572     if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
573     {
574         /* Enable backpressure for port with a zero threshold */
575         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 1<<17);
576         /* Add 1000 to the page count to simulate packets coming in */
577         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | 1000);
578     }
579
580     if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
581     {
582         /* Enable backpressure for port with a zero threshold */
583         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 1<<17);
584         /* Add 1000 to the page count to simulate packets coming in */
585         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | 1000);
586     }
587
588     /* Wait 500 cycles for the BP to update */
589     cvmx_wait(500);
590
591     /* Read the BP state from the debug select register */
592     switch (mode0)
593     {
594         case CVMX_HELPER_INTERFACE_MODE_SPI:
595             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9004);
596             bp_status0 = cvmx_read_csr(CVMX_DBG_DATA);
597             bp_status0 = 0xffff & ~bp_status0;
598             break;
599         case CVMX_HELPER_INTERFACE_MODE_RGMII:
600         case CVMX_HELPER_INTERFACE_MODE_GMII:
601             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x0e00);
602             bp_status0 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA);
603             break;
604         case CVMX_HELPER_INTERFACE_MODE_XAUI:
605         case CVMX_HELPER_INTERFACE_MODE_SGMII:
606         case CVMX_HELPER_INTERFACE_MODE_PICMG:
607             cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x0e00);
608             bp_status0 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
609             break;
610         default:
611             bp_status0 = 1<<port0;
612             break;
613     }
614
615     /* Read the BP state from the debug select register */
616     switch (mode1)
617     {
618         case CVMX_HELPER_INTERFACE_MODE_SPI:
619             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9804);
620             bp_status1 = cvmx_read_csr(CVMX_DBG_DATA);
621             bp_status1 = 0xffff & ~bp_status1;
622             break;
623         case CVMX_HELPER_INTERFACE_MODE_RGMII:
624         case CVMX_HELPER_INTERFACE_MODE_GMII:
625             cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x1600);
626             bp_status1 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA);
627             break;
628         case CVMX_HELPER_INTERFACE_MODE_XAUI:
629         case CVMX_HELPER_INTERFACE_MODE_SGMII:
630         case CVMX_HELPER_INTERFACE_MODE_PICMG:
631             cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x1600);
632             bp_status1 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA);
633             break;
634         default:
635             bp_status1 = 1<<(port1-16);
636             break;
637     }
638
639     if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
640     {
641         /* Shutdown BP */
642         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | (0x1ffffff & -1000));
643         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 0);
644     }
645
646     if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED)
647     {
648         /* Shutdown BP */
649         cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | (0x1ffffff & -1000));
650         cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 0);
651     }
652
653     /* Clear any error interrupts that might have been set */
654     cvmx_write_csr(CVMX_IPD_INT_SUM, 0x1f);
655     cvmx_write_csr(CVMX_IPD_INT_ENB, ipd_int_enb);
656
657     return ((bp_status0 != 1ull<<port0) || (bp_status1 != 1ull<<(port1-16)));
658 }
659
660
661 /**
662  * @INTERNAL
663  * Enable packet input/output from the hardware. This function is
664  * called after all internal setup is complete and IPD is enabled.
665  * After this function completes, packets will be accepted from the
666  * hardware ports. PKO should still be disabled to make sure packets
667  * aren't sent out partially setup hardware.
668  *
669  * @param interface Interface to enable
670  *
671  * @return Zero on success, negative on failure
672  */
673 static int __cvmx_helper_packet_hardware_enable(int interface)
674 {
675     int result = 0;
676     switch (cvmx_helper_interface_get_mode(interface))
677     {
678         /* These types don't support ports to IPD/PKO */
679         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
680         case CVMX_HELPER_INTERFACE_MODE_PCIE:
681             /* Nothing to do */
682             break;
683         /* XAUI is a single high speed port */
684         case CVMX_HELPER_INTERFACE_MODE_XAUI:
685             result = __cvmx_helper_xaui_enable(interface);
686             break;
687         /* RGMII/GMII/MII are all treated about the same. Most functions
688             refer to these ports as RGMII */
689         case CVMX_HELPER_INTERFACE_MODE_RGMII:
690         case CVMX_HELPER_INTERFACE_MODE_GMII:
691             result = __cvmx_helper_rgmii_enable(interface);
692             break;
693         /* SPI4 can have 1-16 ports depending on the device at the other end */
694         case CVMX_HELPER_INTERFACE_MODE_SPI:
695             result = __cvmx_helper_spi_enable(interface);
696             break;
697         /* SGMII can have 1-4 ports depending on how many are hooked up */
698         case CVMX_HELPER_INTERFACE_MODE_SGMII:
699         case CVMX_HELPER_INTERFACE_MODE_PICMG:
700             result = __cvmx_helper_sgmii_enable(interface);
701             break;
702         /* PCI target Network Packet Interface */
703         case CVMX_HELPER_INTERFACE_MODE_NPI:
704             result = __cvmx_helper_npi_enable(interface);
705             break;
706         /* Special loopback only ports. These are not the same as other ports
707             in loopback mode */
708         case CVMX_HELPER_INTERFACE_MODE_LOOP:
709             result = __cvmx_helper_loop_enable(interface);
710             break;
711         /* SRIO has 2^N ports, where N is number of interfaces */
712         case CVMX_HELPER_INTERFACE_MODE_SRIO:
713             result = __cvmx_helper_srio_enable(interface);
714             break;
715     }
716     result |= __cvmx_helper_board_hardware_enable(interface);
717     return result;
718 }
719
720
721 /**
722  * Called after all internal packet IO paths are setup. This
723  * function enables IPD/PIP and begins packet input and output.
724  *
725  * @return Zero on success, negative on failure
726  */
727 int cvmx_helper_ipd_and_packet_input_enable(void)
728 {
729     int num_interfaces;
730     int interface;
731
732     /* Enable IPD */
733     cvmx_ipd_enable();
734
735     /* Time to enable hardware ports packet input and output. Note that at this
736         point IPD/PIP must be fully functional and PKO must be disabled */
737     num_interfaces = cvmx_helper_get_number_of_interfaces();
738     for (interface=0; interface<num_interfaces; interface++)
739     {
740         if (cvmx_helper_ports_on_interface(interface) > 0)
741         {
742             //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface);
743             __cvmx_helper_packet_hardware_enable(interface);
744         }
745     }
746
747     /* Finally enable PKO now that the entire path is up and running */
748     cvmx_pko_enable();
749
750     if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) &&
751         (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
752         __cvmx_helper_errata_fix_ipd_ptr_alignment();
753     return 0;
754 }
755 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
756 EXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable);
757 #endif
758
759 /**
760  * Initialize the PIP, IPD, and PKO hardware to support
761  * simple priority based queues for the ethernet ports. Each
762  * port is configured with a number of priority queues based
763  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
764  * priority than the previous.
765  *
766  * @return Zero on success, non-zero on failure
767  */
768 int cvmx_helper_initialize_packet_io_global(void)
769 {
770     int result = 0;
771     int interface;
772     cvmx_l2c_cfg_t l2c_cfg;
773     cvmx_smix_en_t smix_en;
774     const int num_interfaces = cvmx_helper_get_number_of_interfaces();
775
776     /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */
777     if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
778         __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
779
780     /* Tell L2 to give the IOB statically higher priority compared to the
781         cores. This avoids conditions where IO blocks might be starved under
782         very high L2 loads */
783     if (OCTEON_IS_MODEL(OCTEON_CN6XXX))
784     {
785         cvmx_l2c_ctl_t l2c_ctl;
786         l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL);
787         l2c_ctl.s.rsp_arb_mode = 1;
788         l2c_ctl.s.xmc_arb_mode = 0;
789         cvmx_write_csr(CVMX_L2C_CTL, l2c_ctl.u64);
790     }
791     else
792     {
793         l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
794         l2c_cfg.s.lrf_arb_mode = 0;
795         l2c_cfg.s.rfb_arb_mode = 0;
796         cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
797     }
798
799     if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)
800     {
801         /* Make sure SMI/MDIO is enabled so we can query PHYs */
802         smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
803         if (!smix_en.s.en)
804         {
805             smix_en.s.en = 1;
806             cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
807         }
808
809         /* Newer chips actually have two SMI/MDIO interfaces */
810         if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
811             !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
812             !OCTEON_IS_MODEL(OCTEON_CN50XX))
813         {
814             smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
815             if (!smix_en.s.en)
816             {
817                 smix_en.s.en = 1;
818                 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
819             }
820         }
821     }
822
823     for (interface=0; interface<num_interfaces; interface++)
824         result |= cvmx_helper_interface_probe(interface);
825
826     cvmx_pko_initialize_global();
827     for (interface=0; interface<num_interfaces; interface++)
828     {
829         if (cvmx_helper_ports_on_interface(interface) > 0)
830             cvmx_dprintf("Interface %d has %d ports (%s)\n",
831                      interface, cvmx_helper_ports_on_interface(interface),
832                      cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface)));
833         result |= __cvmx_helper_interface_setup_ipd(interface);
834         result |= __cvmx_helper_interface_setup_pko(interface);
835     }
836
837     result |= __cvmx_helper_global_setup_ipd();
838     result |= __cvmx_helper_global_setup_pko();
839
840     /* Enable any flow control and backpressure */
841     result |= __cvmx_helper_global_setup_backpressure();
842
843 #if CVMX_HELPER_ENABLE_IPD
844     result |= cvmx_helper_ipd_and_packet_input_enable();
845 #endif
846     return result;
847 }
848 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
849 EXPORT_SYMBOL(cvmx_helper_initialize_packet_io_global);
850 #endif
851
852
853 /**
854  * Does core local initialization for packet io
855  *
856  * @return Zero on success, non-zero on failure
857  */
858 int cvmx_helper_initialize_packet_io_local(void)
859 {
860     return cvmx_pko_initialize_local();
861 }
862
863
864 /**
865  * Undo the initialization performed in
866  * cvmx_helper_initialize_packet_io_global(). After calling this routine and the
867  * local version on each core, packet IO for Octeon will be disabled and placed
868  * in the initial reset state. It will then be safe to call the initialize
869  * later on. Note that this routine does not empty the FPA pools. It frees all
870  * buffers used by the packet IO hardware to the FPA so a function emptying the
871  * FPA after shutdown should find all packet buffers in the FPA.
872  *
873  * @return Zero on success, negative on failure.
874  */
875 int cvmx_helper_shutdown_packet_io_global(void)
876 {
877     const int timeout = 5; /* Wait up to 5 seconds for timeouts */
878     int result = 0;
879     int num_interfaces;
880     int interface;
881     int num_ports;
882     int index;
883     int pool0_count;
884     cvmx_wqe_t *work;
885
886     /* Step 1: Disable all backpressure */
887     for (interface=0; interface<2; interface++)
888         if (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_DISABLED)
889             cvmx_gmx_set_backpressure_override(interface, 0xf);
890
891 step2:
892     /* Step 2: Wait for the PKO queues to drain */
893     num_interfaces = cvmx_helper_get_number_of_interfaces();
894     for (interface=0; interface<num_interfaces; interface++)
895     {
896         num_ports = cvmx_helper_ports_on_interface(interface);
897         for (index=0; index<num_ports; index++)
898         {
899             int pko_port = cvmx_helper_get_ipd_port(interface, index);
900             int queue = cvmx_pko_get_base_queue(pko_port);
901             int max_queue = queue + cvmx_pko_get_num_queues(pko_port);
902             while (queue < max_queue)
903             {
904                 int count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue));
905                 uint64_t start_cycle = cvmx_get_cycle();
906                 uint64_t stop_cycle = start_cycle +
907                     cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout;
908                 while (count && (cvmx_get_cycle() < stop_cycle))
909                 {
910                     cvmx_wait(10000);
911                     count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue));
912                 }
913                 if (count)
914                 {
915                     cvmx_dprintf("PKO port %d, queue %d, timeout waiting for idle\n",
916                         pko_port, queue);
917                     result = -1;
918                 }
919                 queue++;
920             }
921         }
922     }
923
924     /* Step 3: Disable TX and RX on all ports */
925     for (interface=0; interface<2; interface++)
926     {
927         switch (cvmx_helper_interface_get_mode(interface))
928         {
929             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
930             case CVMX_HELPER_INTERFACE_MODE_PCIE:
931                 /* Not a packet interface */
932                 break;
933             case CVMX_HELPER_INTERFACE_MODE_NPI:
934             case CVMX_HELPER_INTERFACE_MODE_SRIO:
935                 /* We don't handle the NPI/NPEI/SRIO packet engines. The caller
936                     must know these are idle */
937                 break;
938             case CVMX_HELPER_INTERFACE_MODE_LOOP:
939                 /* Nothing needed. Once PKO is idle, the loopback devices
940                     must be idle */
941                 break;
942             case CVMX_HELPER_INTERFACE_MODE_SPI:
943                 /* SPI cannot be disabled from Octeon. It is the responsibility
944                     of the caller to make sure SPI is idle before doing
945                     shutdown */
946                 /* Fall through and do the same processing as RGMII/GMII */
947             case CVMX_HELPER_INTERFACE_MODE_GMII:
948             case CVMX_HELPER_INTERFACE_MODE_RGMII:
949                 /* Disable outermost RX at the ASX block */
950                 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), 0);
951                 num_ports = cvmx_helper_ports_on_interface(interface);
952                 if (num_ports > 4)
953                     num_ports = 4;
954                 for (index=0; index<num_ports; index++)
955                 {
956                     cvmx_gmxx_prtx_cfg_t gmx_cfg;
957                     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
958                     gmx_cfg.s.en = 0;
959                     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
960                     /* Poll the GMX state machine waiting for it to become idle */
961                     cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880);
962                     if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, timeout*1000000))
963                     {
964                         cvmx_dprintf("GMX RX path timeout waiting for idle\n");
965                         result = -1;
966                     }
967                     if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, timeout*1000000))
968                     {
969                         cvmx_dprintf("GMX TX path timeout waiting for idle\n");
970                         result = -1;
971                     }
972                 }
973                 /* Disable outermost TX at the ASX block */
974                 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), 0);
975                 /* Disable interrupts for interface */
976                 cvmx_write_csr(CVMX_ASXX_INT_EN(interface), 0);
977                 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0);
978                 break;
979             case CVMX_HELPER_INTERFACE_MODE_XAUI:
980             case CVMX_HELPER_INTERFACE_MODE_SGMII:
981             case CVMX_HELPER_INTERFACE_MODE_PICMG:
982                 num_ports = cvmx_helper_ports_on_interface(interface);
983                 if (num_ports > 4)
984                     num_ports = 4;
985                 for (index=0; index<num_ports; index++)
986                 {
987                     cvmx_gmxx_prtx_cfg_t gmx_cfg;
988                     gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface));
989                     gmx_cfg.s.en = 0;
990                     cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64);
991                     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, timeout*1000000))
992                     {
993                         cvmx_dprintf("GMX RX path timeout waiting for idle\n");
994                         result = -1;
995                     }
996                     if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, timeout*1000000))
997                     {
998                         cvmx_dprintf("GMX TX path timeout waiting for idle\n");
999                         result = -1;
1000                     }
1001                 }
1002                 break;
1003         }
1004     }
1005
1006     /* Step 4: Retrieve all packets from the POW and free them */
1007     while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT)))
1008     {
1009         cvmx_helper_free_packet_data(work);
1010         cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 0);
1011     }
1012
1013     /* Step 4b: Special workaround for pass 2 errata */
1014     if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
1015     {
1016         cvmx_ipd_ptr_count_t ipd_cnt;
1017         int to_add;
1018         ipd_cnt.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
1019         to_add = (ipd_cnt.s.wqev_cnt + ipd_cnt.s.wqe_pcnt) & 0x7;
1020         if (to_add)
1021         {
1022             int port = -1;
1023             cvmx_dprintf("Aligning CN38XX pass 2 IPD counters\n");
1024             if (cvmx_helper_interface_get_mode(0) == CVMX_HELPER_INTERFACE_MODE_RGMII)
1025                 port = 0;
1026             else if (cvmx_helper_interface_get_mode(1) == CVMX_HELPER_INTERFACE_MODE_RGMII)
1027                 port = 16;
1028
1029             if (port != -1)
1030             {
1031                 char *buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
1032                 if (buffer)
1033                 {
1034                     int queue = cvmx_pko_get_base_queue(port);
1035                     cvmx_pko_command_word0_t pko_command;
1036                     cvmx_buf_ptr_t packet;
1037                     uint64_t start_cycle;
1038                     uint64_t stop_cycle;
1039
1040                     /* Populate a minimal packet */
1041                     memset(buffer, 0xff, 6);
1042                     memset(buffer+6, 0, 54);
1043                     pko_command.u64 = 0;
1044                     pko_command.s.dontfree = 1;
1045                     pko_command.s.total_bytes = 60;
1046                     pko_command.s.segs = 1;
1047                     packet.u64 = 0;
1048                     packet.s.addr = cvmx_ptr_to_phys(buffer);
1049                     packet.s.size = CVMX_FPA_PACKET_POOL_SIZE;
1050                     __cvmx_helper_rgmii_configure_loopback(port, 1, 0);
1051                     while (to_add--)
1052                     {
1053                         cvmx_pko_send_packet_prepare(port, queue, CVMX_PKO_LOCK_CMD_QUEUE);
1054                         if (cvmx_pko_send_packet_finish(port, queue, pko_command, packet, CVMX_PKO_LOCK_CMD_QUEUE))
1055                         {
1056                             cvmx_dprintf("ERROR: Unable to align IPD counters (PKO failed)\n");
1057                             break;
1058                         }
1059                     }
1060                     cvmx_fpa_free(buffer, CVMX_FPA_PACKET_POOL, 0);
1061
1062                     /* Wait for the packets to loop back */
1063                     start_cycle = cvmx_get_cycle();
1064                     stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout;
1065                     while (cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)) &&
1066                            (cvmx_get_cycle() < stop_cycle))
1067                     {
1068                         cvmx_wait(1000);
1069                     }
1070                     cvmx_wait(1000);
1071                     __cvmx_helper_rgmii_configure_loopback(port, 0, 0);
1072                     if (to_add == -1)
1073                         goto step2;
1074                 }
1075                 else
1076                     cvmx_dprintf("ERROR: Unable to align IPD counters (Packet pool empty)\n");
1077             }
1078             else
1079                 cvmx_dprintf("ERROR: Unable to align IPD counters\n");
1080         }
1081     }
1082
1083     /* Step 5: Disable IPD and PKO. PIP is taken care of in the next step */
1084     cvmx_ipd_disable();
1085     cvmx_pko_disable();
1086
1087     /* Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP
1088         have not been reset yet */
1089     __cvmx_ipd_free_ptr();
1090
1091     /* Step 7: Free the PKO command buffers and put PKO in reset */
1092     cvmx_pko_shutdown();
1093
1094     /* Step 8: Disable MAC address filtering */
1095     for (interface=0; interface<2; interface++)
1096     {
1097         switch (cvmx_helper_interface_get_mode(interface))
1098         {
1099             case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1100             case CVMX_HELPER_INTERFACE_MODE_PCIE:
1101             case CVMX_HELPER_INTERFACE_MODE_SRIO:
1102             case CVMX_HELPER_INTERFACE_MODE_NPI:
1103             case CVMX_HELPER_INTERFACE_MODE_LOOP:
1104                 break;
1105             case CVMX_HELPER_INTERFACE_MODE_XAUI:
1106             case CVMX_HELPER_INTERFACE_MODE_GMII:
1107             case CVMX_HELPER_INTERFACE_MODE_RGMII:
1108             case CVMX_HELPER_INTERFACE_MODE_SPI:
1109             case CVMX_HELPER_INTERFACE_MODE_SGMII:
1110             case CVMX_HELPER_INTERFACE_MODE_PICMG:
1111                 num_ports = cvmx_helper_ports_on_interface(interface);
1112                 if (num_ports > 4)
1113                     num_ports = 4;
1114                 for (index=0; index<num_ports; index++)
1115                 {
1116                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1);
1117                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0);
1118                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0);
1119                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0);
1120                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0);
1121                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0);
1122                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0);
1123                     cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0);
1124                 }
1125                 break;
1126         }
1127     }
1128
1129     /* Step 9: Drain all FPA buffers out of pool 0 before we reset IPD/PIP.
1130         This is needed to keep IPD_QUE0_FREE_PAGE_CNT in sync. We use pool 1
1131         for temporary storage */
1132     pool0_count = 0;
1133     while (1)
1134     {
1135         void *buffer = cvmx_fpa_alloc(0);
1136         if (buffer)
1137         {
1138             cvmx_fpa_free(buffer, 1, 0);
1139             pool0_count++;
1140         }
1141         else
1142             break;
1143     }
1144
1145
1146     /* Step 10: Reset IPD and PIP */
1147     {
1148         cvmx_ipd_ctl_status_t ipd_ctl_status;
1149         ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
1150         ipd_ctl_status.s.reset = 1;
1151         cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
1152
1153         if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) &&
1154             (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX)))
1155         {
1156             /* only try 1000 times.  Normally if this works it will happen in
1157             ** the first 50 loops. */
1158             int max_loops = 1000;
1159             int loop = 0;
1160             /* Per port backpressure counters can get misaligned after an
1161                IPD reset. This code realigns them by performing repeated
1162                resets. See IPD-13473 */
1163             cvmx_wait(100);
1164             if (__cvmx_helper_backpressure_is_misaligned())
1165             {
1166                 cvmx_dprintf("Starting to align per port backpressure counters.\n");
1167                 while (__cvmx_helper_backpressure_is_misaligned() && (loop++ < max_loops))
1168                 {
1169                     cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64);
1170                     cvmx_wait(123);
1171                 }
1172                 if (loop < max_loops)
1173                     cvmx_dprintf("Completed aligning per port backpressure counters (%d loops).\n", loop);
1174                 else
1175                 {
1176                     cvmx_dprintf("ERROR: unable to align per port backpressure counters.\n");
1177                     /* For now, don't hang.... */
1178                 }
1179             }
1180         }
1181
1182         /* PIP_SFT_RST not present in CN38XXp{1,2} */
1183         if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2))
1184         {
1185             cvmx_pip_sft_rst_t pip_sft_rst;
1186             pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST);
1187             pip_sft_rst.s.rst = 1;
1188             cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64);
1189         }
1190     }
1191
1192     /* Step 11: Restore the FPA buffers into pool 0 */
1193     while (pool0_count--)
1194         cvmx_fpa_free(cvmx_fpa_alloc(1), 0, 0);
1195
1196     return result;
1197 }
1198 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1199 EXPORT_SYMBOL(cvmx_helper_shutdown_packet_io_global);
1200 #endif
1201
1202
1203 /**
1204  * Does core local shutdown of packet io
1205  *
1206  * @return Zero on success, non-zero on failure
1207  */
1208 int cvmx_helper_shutdown_packet_io_local(void)
1209 {
1210     /* Currently there is nothing to do per core. This may change in
1211         the future */
1212     return 0;
1213 }
1214
1215
1216
1217 /**
1218  * Auto configure an IPD/PKO port link state and speed. This
1219  * function basically does the equivalent of:
1220  * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
1221  *
1222  * @param ipd_port IPD/PKO port to auto configure
1223  *
1224  * @return Link state after configure
1225  */
1226 cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
1227 {
1228     cvmx_helper_link_info_t link_info;
1229     int interface = cvmx_helper_get_interface_num(ipd_port);
1230     int index = cvmx_helper_get_interface_index_num(ipd_port);
1231
1232     if (index >= cvmx_helper_ports_on_interface(interface))
1233     {
1234         link_info.u64 = 0;
1235         return link_info;
1236     }
1237
1238     link_info = cvmx_helper_link_get(ipd_port);
1239     if (link_info.u64 ==  port_link_info[ipd_port].u64)
1240         return link_info;
1241
1242 #if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)
1243     if (!link_info.s.link_up)
1244         cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port);
1245 #endif
1246
1247     /* If we fail to set the link speed, port_link_info will not change */
1248     cvmx_helper_link_set(ipd_port, link_info);
1249
1250 #if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)
1251     if (link_info.s.link_up)
1252         cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port);
1253 #endif
1254
1255     /* port_link_info should be the current value, which will be different
1256         than expect if cvmx_helper_link_set() failed */
1257     return port_link_info[ipd_port];
1258 }
1259 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1260 EXPORT_SYMBOL(cvmx_helper_link_autoconf);
1261 #endif
1262
1263 /**
1264  * Return the link state of an IPD/PKO port as returned by
1265  * auto negotiation. The result of this function may not match
1266  * Octeon's link config if auto negotiation has changed since
1267  * the last call to cvmx_helper_link_set().
1268  *
1269  * @param ipd_port IPD/PKO port to query
1270  *
1271  * @return Link state
1272  */
1273 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1274 {
1275     cvmx_helper_link_info_t result;
1276     int interface = cvmx_helper_get_interface_num(ipd_port);
1277     int index = cvmx_helper_get_interface_index_num(ipd_port);
1278
1279     /* The default result will be a down link unless the code below
1280         changes it */
1281     result.u64 = 0;
1282
1283     if (index >= cvmx_helper_ports_on_interface(interface))
1284         return result;
1285
1286     switch (cvmx_helper_interface_get_mode(interface))
1287     {
1288         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1289         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1290             /* Network links are not supported */
1291             break;
1292         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1293             result = __cvmx_helper_xaui_link_get(ipd_port);
1294             break;
1295         case CVMX_HELPER_INTERFACE_MODE_GMII:
1296             if (index == 0)
1297                 result = __cvmx_helper_rgmii_link_get(ipd_port);
1298             else
1299             {
1300                 result.s.full_duplex = 1;
1301                 result.s.link_up = 1;
1302                 result.s.speed = 1000;
1303             }
1304             break;
1305         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1306             result = __cvmx_helper_rgmii_link_get(ipd_port);
1307             break;
1308         case CVMX_HELPER_INTERFACE_MODE_SPI:
1309             result = __cvmx_helper_spi_link_get(ipd_port);
1310             break;
1311         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1312         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1313             result = __cvmx_helper_sgmii_link_get(ipd_port);
1314             break;
1315         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1316             result = __cvmx_helper_srio_link_get(ipd_port);
1317             break;
1318         case CVMX_HELPER_INTERFACE_MODE_NPI:
1319         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1320             /* Network links are not supported */
1321             break;
1322     }
1323     return result;
1324 }
1325 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1326 EXPORT_SYMBOL(cvmx_helper_link_get);
1327 #endif
1328
1329
1330 /**
1331  * Configure an IPD/PKO port for the specified link state. This
1332  * function does not influence auto negotiation at the PHY level.
1333  * The passed link state must always match the link state returned
1334  * by cvmx_helper_link_get(). It is normally best to use
1335  * cvmx_helper_link_autoconf() instead.
1336  *
1337  * @param ipd_port  IPD/PKO port to configure
1338  * @param link_info The new link state
1339  *
1340  * @return Zero on success, negative on failure
1341  */
1342 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1343 {
1344     int result = -1;
1345     int interface = cvmx_helper_get_interface_num(ipd_port);
1346     int index = cvmx_helper_get_interface_index_num(ipd_port);
1347
1348     if (index >= cvmx_helper_ports_on_interface(interface))
1349         return -1;
1350
1351     switch (cvmx_helper_interface_get_mode(interface))
1352     {
1353         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1354         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1355             break;
1356         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1357             result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1358             break;
1359         /* RGMII/GMII/MII are all treated about the same. Most functions
1360             refer to these ports as RGMII */
1361         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1362         case CVMX_HELPER_INTERFACE_MODE_GMII:
1363             result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1364             break;
1365         case CVMX_HELPER_INTERFACE_MODE_SPI:
1366             result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1367             break;
1368         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1369         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1370             result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1371             break;
1372         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1373             result = __cvmx_helper_srio_link_set(ipd_port, link_info);
1374             break;
1375         case CVMX_HELPER_INTERFACE_MODE_NPI:
1376         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1377             break;
1378     }
1379     /* Set the port_link_info here so that the link status is updated
1380        no matter how cvmx_helper_link_set is called. We don't change
1381        the value if link_set failed */
1382     if (result == 0)
1383         port_link_info[ipd_port].u64 = link_info.u64;
1384     return result;
1385 }
1386 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1387 EXPORT_SYMBOL(cvmx_helper_link_set);
1388 #endif
1389
1390
1391 /**
1392  * Configure a port for internal and/or external loopback. Internal loopback
1393  * causes packets sent by the port to be received by Octeon. External loopback
1394  * causes packets received from the wire to sent out again.
1395  *
1396  * @param ipd_port IPD/PKO port to loopback.
1397  * @param enable_internal
1398  *                 Non zero if you want internal loopback
1399  * @param enable_external
1400  *                 Non zero if you want external loopback
1401  *
1402  * @return Zero on success, negative on failure.
1403  */
1404 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external)
1405 {
1406     int result = -1;
1407     int interface = cvmx_helper_get_interface_num(ipd_port);
1408     int index = cvmx_helper_get_interface_index_num(ipd_port);
1409
1410     if (index >= cvmx_helper_ports_on_interface(interface))
1411         return -1;
1412
1413     switch (cvmx_helper_interface_get_mode(interface))
1414     {
1415         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1416         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1417         case CVMX_HELPER_INTERFACE_MODE_SRIO:
1418         case CVMX_HELPER_INTERFACE_MODE_SPI:
1419         case CVMX_HELPER_INTERFACE_MODE_NPI:
1420         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1421             break;
1422         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1423             result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external);
1424             break;
1425         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1426         case CVMX_HELPER_INTERFACE_MODE_GMII:
1427             result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external);
1428             break;
1429         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1430         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1431             result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external);
1432             break;
1433     }
1434     return result;
1435 }
1436
1437 #endif /* CVMX_ENABLE_PKO_FUNCTIONS */