13236SN/A/***********************license start***************
211525Sdarcy * Copyright (c) 2003-2010  Cavium Inc. (support@cavium.com). All rights
33236SN/A * reserved.
43236SN/A *
53236SN/A *
63236SN/A * Redistribution and use in source and binary forms, with or without
73236SN/A * modification, are permitted provided that the following conditions are
83236SN/A * met:
93236SN/A *
103236SN/A *   * Redistributions of source code must retain the above copyright
113236SN/A *     notice, this list of conditions and the following disclaimer.
123236SN/A *
133236SN/A *   * Redistributions in binary form must reproduce the above
143236SN/A *     copyright notice, this list of conditions and the following
153236SN/A *     disclaimer in the documentation and/or other materials provided
163236SN/A *     with the distribution.
173236SN/A
183236SN/A *   * Neither the name of Cavium Inc. nor the names of
193236SN/A *     its contributors may be used to endorse or promote products
203236SN/A *     derived from this software without specific prior written
213236SN/A *     permission.
223236SN/A
233236SN/A * This Software, including technical data, may be subject to U.S. export  control
243236SN/A * laws, including the U.S. Export Administration Act and its  associated
253236SN/A * regulations, and may be subject to export or import  regulations in other
263236SN/A * countries.
273236SN/A
283236SN/A * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
293236SN/A * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
303236SN/A * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
313236SN/A * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
323236SN/A * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
333236SN/A * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
343236SN/A * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
354208SN/A * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
363236SN/A * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE  RISK ARISING OUT OF USE OR
373236SN/A * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
383236SN/A ***********************license end**************************************/
393236SN/A
403236SN/A
413236SN/A
423236SN/A
433236SN/A
443236SN/A
454208SN/A
463236SN/A/**
474208SN/A * @file
4810188SN/A *
493236SN/A * Helper functions for common, but complicated tasks.
503236SN/A *
513236SN/A * <hr>$Revision: 70030 $<hr>
523236SN/A */
533236SN/A#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
543236SN/A#include <linux/module.h>
553236SN/A#include <asm/octeon/cvmx.h>
563236SN/A#include <asm/octeon/cvmx-config.h>
574208SN/A#include <asm/octeon/cvmx-bootmem.h>
583236SN/A#include <asm/octeon/cvmx-sriox-defs.h>
593236SN/A#include <asm/octeon/cvmx-npi-defs.h>
603236SN/A#include <asm/octeon/cvmx-mio-defs.h>
613236SN/A#include <asm/octeon/cvmx-pexp-defs.h>
623236SN/A#include <asm/octeon/cvmx-pip-defs.h>
633236SN/A#include <asm/octeon/cvmx-asxx-defs.h>
644208SN/A#include <asm/octeon/cvmx-gmxx-defs.h>
654208SN/A#include <asm/octeon/cvmx-smix-defs.h>
664208SN/A#include <asm/octeon/cvmx-dbg-defs.h>
674208SN/A#include <asm/octeon/cvmx-sso-defs.h>
684208SN/A
694208SN/A#include <asm/octeon/cvmx-gmx.h>
704208SN/A#include <asm/octeon/cvmx-fpa.h>
714208SN/A#include <asm/octeon/cvmx-pip.h>
724208SN/A#include <asm/octeon/cvmx-pko.h>
734208SN/A#include <asm/octeon/cvmx-ipd.h>
744208SN/A#include <asm/octeon/cvmx-spi.h>
754208SN/A#include <asm/octeon/cvmx-clock.h>
764208SN/A#include <asm/octeon/cvmx-helper.h>
774208SN/A#include <asm/octeon/cvmx-helper-board.h>
784208SN/A#include <asm/octeon/cvmx-helper-errata.h>
793236SN/A#include <asm/octeon/cvmx-helper-cfg.h>
803236SN/A#else
813236SN/A#if !defined(__FreeBSD__) || !defined(_KERNEL)
823236SN/A#include "executive-config.h"
833236SN/A#endif
843236SN/A#include "cvmx.h"
854582SN/A#include "cvmx-sysinfo.h"
864008SN/A#include "cvmx-bootmem.h"
874008SN/A#include "cvmx-version.h"
8811525Sdarcy#include "cvmx-helper-check-defines.h"
893236SN/A#include "cvmx-gmx.h"
903236SN/A#if !defined(__FreeBSD__) || !defined(_KERNEL)
913236SN/A#include "cvmx-error.h"
923236SN/A#include "cvmx-config.h"
933236SN/A#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 */
116CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int ipd_port,
117    uint64_t *priorities) = NULL;
118#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
119EXPORT_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 */
130CVMX_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 */
140int 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
172EXPORT_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 */
185int 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
193EXPORT_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 */
207cvmx_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
437EXPORT_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 */
452static 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 */
523static 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 */
566int 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 */
617int 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 */
709static 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 */
749static 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 */
777static 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 */
817static 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 */
851static 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 */
891static 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 */
1012static 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 */
1066int 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
1095EXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable);
1096#endif
1097
1098#define __CVMX_SSO_RWQ_SIZE 256
1099
1100int 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
1169int 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 */
1255int 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
1340EXPORT_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 */
1349int 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 */
1361static 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
1379struct 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 */
1394int 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
1411step2:
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
1451step3:
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
1753EXPORT_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 */
1762int 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 */
1780cvmx_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
1812EXPORT_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 */
1825cvmx_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
1882EXPORT_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 */
1898int 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
1947EXPORT_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 */
1964int 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 */
2000