cvmx-helper.c revision 210311
1/***********************license start***************
2 *  Copyright (c) 2003-2008 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 *  TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
24 *  AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS
25 *  OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
26 *  RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
27 *  REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
28 *  DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
29 *  OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
30 *  PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET
31 *  POSSESSION OR CORRESPONDENCE TO DESCRIPTION.  THE ENTIRE RISK ARISING OUT
32 *  OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
33 *
34 *
35 *  For any questions regarding licensing please contact marketing@caviumnetworks.com
36 *
37 ***********************license end**************************************/
38
39
40
41
42
43
44/**
45 * @file
46 *
47 * Helper functions for common, but complicated tasks.
48 *
49 * <hr>$Revision: 42150 $<hr>
50 */
51#include "cvmx.h"
52#include "cvmx-bootmem.h"
53#include "cvmx-fpa.h"
54#include "cvmx-pip.h"
55#include "cvmx-pko.h"
56#include "cvmx-ipd.h"
57#include "cvmx-asx.h"
58#include "cvmx-gmx.h"
59#include "cvmx-spi.h"
60#include "cvmx-sysinfo.h"
61#include "cvmx-helper.h"
62#include "cvmx-version.h"
63#include "cvmx-helper-check-defines.h"
64#include "cvmx-helper-board.h"
65#include "cvmx-helper-errata.h"
66
67#ifdef CVMX_ENABLE_PKO_FUNCTIONS
68
69/**
70 * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
71 * priorities[16]) is a function pointer. It is meant to allow
72 * customization of the PKO queue priorities based on the port
73 * number. Users should set this pointer to a function before
74 * calling any cvmx-helper operations.
75 */
76CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int pko_port, uint64_t priorities[16]) = NULL;
77
78/**
79 * cvmx_override_ipd_port_setup(int ipd_port) is a function
80 * pointer. It is meant to allow customization of the IPD port
81 * setup before packet input/output comes online. It is called
82 * after cvmx-helper does the default IPD configuration, but
83 * before IPD is enabled. Users should set this pointer to a
84 * function before calling any cvmx-helper operations.
85 */
86CVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL;
87
88/* Port count per interface */
89static CVMX_SHARED int interface_port_count[4] = {0,0,0,0};
90/* Port last configured link info index by IPD/PKO port */
91static CVMX_SHARED cvmx_helper_link_info_t port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
92
93
94/**
95 * Return the number of interfaces the chip has. Each interface
96 * may have multiple ports. Most chips support two interfaces,
97 * but the CNX0XX and CNX1XX are exceptions. These only support
98 * one interface.
99 *
100 * @return Number of interfaces on chip
101 */
102int cvmx_helper_get_number_of_interfaces(void)
103{
104    if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
105        return 4;
106    else
107        return 3;
108}
109
110
111/**
112 * Return the number of ports on an interface. Depending on the
113 * chip and configuration, this can be 1-16. A value of 0
114 * specifies that the interface doesn't exist or isn't usable.
115 *
116 * @param interface Interface to get the port count for
117 *
118 * @return Number of ports on interface. Can be Zero.
119 */
120int cvmx_helper_ports_on_interface(int interface)
121{
122    return interface_port_count[interface];
123}
124
125
126/**
127 * Get the operating mode of an interface. Depending on the Octeon
128 * chip and configuration, this function returns an enumeration
129 * of the type of packet I/O supported by an interface.
130 *
131 * @param interface Interface to probe
132 *
133 * @return Mode of the interface. Unknown or unsupported interfaces return
134 *         DISABLED.
135 */
136cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
137{
138    cvmx_gmxx_inf_mode_t mode;
139    if (interface == 2)
140        return CVMX_HELPER_INTERFACE_MODE_NPI;
141
142    if (interface == 3)
143    {
144        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
145            return CVMX_HELPER_INTERFACE_MODE_LOOP;
146        else
147            return CVMX_HELPER_INTERFACE_MODE_DISABLED;
148    }
149
150    if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1)
151    {
152        /* Lie about interface type of CN3005 board.  This board has a switch on port 1 like
153        ** the other evaluation boards, but it is connected over RGMII instead of GMII.  Report
154        ** GMII mode so that the speed is forced to 1 Gbit full duplex.  Other than some initial configuration
155        ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes.
156        */
157        return CVMX_HELPER_INTERFACE_MODE_GMII;
158    }
159
160    /* Interface 1 is always disabled on CN31XX and CN30XX */
161    if ((interface == 1) && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)))
162        return CVMX_HELPER_INTERFACE_MODE_DISABLED;
163
164    mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
165
166    if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
167    {
168        switch(mode.cn56xx.mode)
169        {
170            case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED;
171            case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI;
172            case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII;
173            case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG;
174            default:return CVMX_HELPER_INTERFACE_MODE_DISABLED;
175        }
176    }
177    else
178    {
179        if (!mode.s.en)
180            return CVMX_HELPER_INTERFACE_MODE_DISABLED;
181
182        if (mode.s.type)
183        {
184            if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
185                return CVMX_HELPER_INTERFACE_MODE_SPI;
186            else
187                return CVMX_HELPER_INTERFACE_MODE_GMII;
188        }
189        else
190            return CVMX_HELPER_INTERFACE_MODE_RGMII;
191    }
192}
193
194
195/**
196 * @INTERNAL
197 * Configure the IPD/PIP tagging and QoS options for a specific
198 * port. This function determines the POW work queue entry
199 * contents for a port. The setup performed here is controlled by
200 * the defines in executive-config.h.
201 *
202 * @param ipd_port Port to configure. This follows the IPD numbering, not the
203 *                 per interface numbering
204 *
205 * @return Zero on success, negative on failure
206 */
207static int __cvmx_helper_port_setup_ipd(int ipd_port)
208{
209    cvmx_pip_port_cfg_t port_config;
210    cvmx_pip_port_tag_cfg_t tag_config;
211
212    port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
213    tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
214
215    /* Have each port go to a different POW queue */
216    port_config.s.qos = ipd_port & 0x7;
217
218    /* Process the headers and place the IP header in the work queue */
219    port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
220
221    tag_config.s.ip6_src_flag  = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
222    tag_config.s.ip6_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
223    tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
224    tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
225    tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
226    tag_config.s.ip4_src_flag  = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
227    tag_config.s.ip4_dst_flag  = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
228    tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
229    tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
230    tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
231    tag_config.s.inc_prt_flag  = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
232    tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
233    tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
234    tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
235    tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
236    tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
237    /* Put all packets in group 0. Other groups can be used by the app */
238    tag_config.s.grp = 0;
239
240    cvmx_pip_config_port(ipd_port, port_config, tag_config);
241
242    /* Give the user a chance to override our setting for each port */
243    if (cvmx_override_ipd_port_setup)
244        cvmx_override_ipd_port_setup(ipd_port);
245
246    return 0;
247}
248
249
250/**
251 * This function probes an interface to determine the actual
252 * number of hardware ports connected to it. It doesn't setup the
253 * ports or enable them. The main goal here is to set the global
254 * interface_port_count[interface] correctly. Hardware setup of the
255 * ports will be performed later.
256 *
257 * @param interface Interface to probe
258 *
259 * @return Zero on success, negative on failure
260 */
261int cvmx_helper_interface_probe(int interface)
262{
263    /* At this stage in the game we don't want packets to be moving yet.
264        The following probe calls should perform hardware setup
265        needed to determine port counts. Receive must still be disabled */
266    switch (cvmx_helper_interface_get_mode(interface))
267    {
268        /* These types don't support ports to IPD/PKO */
269        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
270        case CVMX_HELPER_INTERFACE_MODE_PCIE:
271            interface_port_count[interface] = 0;
272            break;
273        /* XAUI is a single high speed port */
274        case CVMX_HELPER_INTERFACE_MODE_XAUI:
275            interface_port_count[interface] = __cvmx_helper_xaui_probe(interface);
276            break;
277        /* RGMII/GMII/MII are all treated about the same. Most functions
278            refer to these ports as RGMII */
279        case CVMX_HELPER_INTERFACE_MODE_RGMII:
280        case CVMX_HELPER_INTERFACE_MODE_GMII:
281            interface_port_count[interface] = __cvmx_helper_rgmii_probe(interface);
282            break;
283        /* SPI4 can have 1-16 ports depending on the device at the other end */
284        case CVMX_HELPER_INTERFACE_MODE_SPI:
285            interface_port_count[interface] = __cvmx_helper_spi_probe(interface);
286            break;
287        /* SGMII can have 1-4 ports depending on how many are hooked up */
288        case CVMX_HELPER_INTERFACE_MODE_SGMII:
289        case CVMX_HELPER_INTERFACE_MODE_PICMG:
290            interface_port_count[interface] = __cvmx_helper_sgmii_probe(interface);
291            break;
292        /* PCI target Network Packet Interface */
293        case CVMX_HELPER_INTERFACE_MODE_NPI:
294            interface_port_count[interface] = __cvmx_helper_npi_probe(interface);
295            break;
296        /* Special loopback only ports. These are not the same as other ports
297            in loopback mode */
298        case CVMX_HELPER_INTERFACE_MODE_LOOP:
299            interface_port_count[interface] = __cvmx_helper_loop_probe(interface);
300            break;
301    }
302
303    interface_port_count[interface] = __cvmx_helper_board_interface_probe(interface, interface_port_count[interface]);
304
305    /* Make sure all global variables propagate to other cores */
306    CVMX_SYNCWS;
307
308    return 0;
309}
310
311
312/**
313 * @INTERNAL
314 * Setup the IPD/PIP for the ports on an interface. Packet
315 * classification and tagging are set for every port on the
316 * interface. The number of ports on the interface must already
317 * have been probed.
318 *
319 * @param interface Interface to setup IPD/PIP for
320 *
321 * @return Zero on success, negative on failure
322 */
323static int __cvmx_helper_interface_setup_ipd(int interface)
324{
325    int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
326    int num_ports = interface_port_count[interface];
327
328    while (num_ports--)
329    {
330        __cvmx_helper_port_setup_ipd(ipd_port);
331        ipd_port++;
332    }
333    return 0;
334}
335
336
337/**
338 * @INTERNAL
339 * Setup global setting for IPD/PIP not related to a specific
340 * interface or port. This must be called before IPD is enabled.
341 *
342 * @return Zero on success, negative on failure.
343 */
344static int __cvmx_helper_global_setup_ipd(void)
345{
346    /* Setup the global packet input options */
347    cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8,
348                    CVMX_HELPER_FIRST_MBUFF_SKIP/8,
349                    CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8,
350                    (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
351                    (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */
352                    CVMX_FPA_WQE_POOL,
353                    CVMX_IPD_OPC_MODE_STT,
354                    CVMX_HELPER_ENABLE_BACK_PRESSURE);
355    return 0;
356}
357
358
359/**
360 * @INTERNAL
361 * Setup the PKO for the ports on an interface. The number of
362 * queues per port and the priority of each PKO output queue
363 * is set here. PKO must be disabled when this function is called.
364 *
365 * @param interface Interface to setup PKO for
366 *
367 * @return Zero on success, negative on failure
368 */
369static int __cvmx_helper_interface_setup_pko(int interface)
370{
371    /* Each packet output queue has an associated priority. The higher the
372        priority, the more often it can send a packet. A priority of 8 means
373        it can send in all 8 rounds of contention. We're going to make each
374        queue one less than the last.
375        The vector of priorities has been extended to support CN5xxx CPUs,
376        where up to 16 queues can be associated to a port.
377        To keep backward compatibility we don't change the initial 8
378        priorities and replicate them in the second half.
379        With per-core PKO queues (PKO lockless operation) all queues have
380        the same priority. */
381    uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1};
382
383    /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet
384        classification, tagging and output priorities are set */
385    int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
386    int num_ports = interface_port_count[interface];
387    while (num_ports--)
388    {
389        /* Give the user a chance to override the per queue priorities */
390        if (cvmx_override_pko_queue_priority)
391            cvmx_override_pko_queue_priority(ipd_port, priorities);
392
393        cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0),
394                             cvmx_pko_get_num_queues(ipd_port), priorities);
395        ipd_port++;
396    }
397    return 0;
398}
399
400
401/**
402 * @INTERNAL
403 * Setup global setting for PKO not related to a specific
404 * interface or port. This must be called before PKO is enabled.
405 *
406 * @return Zero on success, negative on failure.
407 */
408static int __cvmx_helper_global_setup_pko(void)
409{
410    /* Disable tagwait FAU timeout. This needs to be done before anyone might
411        start packet output using tags */
412    cvmx_iob_fau_timeout_t fau_to;
413    fau_to.u64 = 0;
414    fau_to.s.tout_val = 0xfff;
415    fau_to.s.tout_enb = 0;
416    cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
417    return 0;
418}
419
420
421/**
422 * @INTERNAL
423 * Setup global backpressure setting.
424 *
425 * @return Zero on success, negative on failure
426 */
427static int __cvmx_helper_global_setup_backpressure(void)
428{
429#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
430    /* Disable backpressure if configured to do so */
431    /* Disable backpressure (pause frame) generation */
432    int num_interfaces = cvmx_helper_get_number_of_interfaces();
433    int interface;
434    for (interface=0; interface<num_interfaces; interface++)
435    {
436        switch (cvmx_helper_interface_get_mode(interface))
437        {
438            case CVMX_HELPER_INTERFACE_MODE_DISABLED:
439            case CVMX_HELPER_INTERFACE_MODE_PCIE:
440            case CVMX_HELPER_INTERFACE_MODE_NPI:
441            case CVMX_HELPER_INTERFACE_MODE_LOOP:
442            case CVMX_HELPER_INTERFACE_MODE_XAUI:
443                break;
444            case CVMX_HELPER_INTERFACE_MODE_RGMII:
445            case CVMX_HELPER_INTERFACE_MODE_GMII:
446            case CVMX_HELPER_INTERFACE_MODE_SPI:
447            case CVMX_HELPER_INTERFACE_MODE_SGMII:
448            case CVMX_HELPER_INTERFACE_MODE_PICMG:
449                cvmx_gmx_set_backpressure_override(interface, 0xf);
450                break;
451        }
452    }
453    //cvmx_dprintf("Disabling backpressure\n");
454#endif
455
456    return 0;
457}
458
459
460/**
461 * @INTERNAL
462 * Enable packet input/output from the hardware. This function is
463 * called after all internal setup is complete and IPD is enabled.
464 * After this function completes, packets will be accepted from the
465 * hardware ports. PKO should still be disabled to make sure packets
466 * aren't sent out partially setup hardware.
467 *
468 * @param interface Interface to enable
469 *
470 * @return Zero on success, negative on failure
471 */
472static int __cvmx_helper_packet_hardware_enable(int interface)
473{
474    int result = 0;
475    switch (cvmx_helper_interface_get_mode(interface))
476    {
477        /* These types don't support ports to IPD/PKO */
478        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
479        case CVMX_HELPER_INTERFACE_MODE_PCIE:
480            /* Nothing to do */
481            break;
482        /* XAUI is a single high speed port */
483        case CVMX_HELPER_INTERFACE_MODE_XAUI:
484            result = __cvmx_helper_xaui_enable(interface);
485            break;
486        /* RGMII/GMII/MII are all treated about the same. Most functions
487            refer to these ports as RGMII */
488        case CVMX_HELPER_INTERFACE_MODE_RGMII:
489        case CVMX_HELPER_INTERFACE_MODE_GMII:
490            result = __cvmx_helper_rgmii_enable(interface);
491            break;
492        /* SPI4 can have 1-16 ports depending on the device at the other end */
493        case CVMX_HELPER_INTERFACE_MODE_SPI:
494            result = __cvmx_helper_spi_enable(interface);
495            break;
496        /* SGMII can have 1-4 ports depending on how many are hooked up */
497        case CVMX_HELPER_INTERFACE_MODE_SGMII:
498        case CVMX_HELPER_INTERFACE_MODE_PICMG:
499            result = __cvmx_helper_sgmii_enable(interface);
500            break;
501        /* PCI target Network Packet Interface */
502        case CVMX_HELPER_INTERFACE_MODE_NPI:
503            result = __cvmx_helper_npi_enable(interface);
504            break;
505        /* Special loopback only ports. These are not the same as other ports
506            in loopback mode */
507        case CVMX_HELPER_INTERFACE_MODE_LOOP:
508            result = __cvmx_helper_loop_enable(interface);
509            break;
510    }
511    result |= __cvmx_helper_board_hardware_enable(interface);
512    return result;
513}
514
515
516/**
517 * Called after all internal packet IO paths are setup. This
518 * function enables IPD/PIP and begins packet input and output.
519 *
520 * @return Zero on success, negative on failure
521 */
522int cvmx_helper_ipd_and_packet_input_enable(void)
523{
524    int num_interfaces;
525    int interface;
526
527    /* Enable IPD */
528    cvmx_ipd_enable();
529
530    /* Time to enable hardware ports packet input and output. Note that at this
531        point IPD/PIP must be fully functional and PKO must be disabled */
532    num_interfaces = cvmx_helper_get_number_of_interfaces();
533    for (interface=0; interface<num_interfaces; interface++)
534    {
535        if (cvmx_helper_ports_on_interface(interface) > 0)
536        {
537            //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface);
538            __cvmx_helper_packet_hardware_enable(interface);
539        }
540    }
541
542    /* Finally enable PKO now that the entire path is up and running */
543    cvmx_pko_enable();
544
545    if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) &&
546        (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
547        __cvmx_helper_errata_fix_ipd_ptr_alignment();
548    return 0;
549}
550
551
552/**
553 * Initialize the PIP, IPD, and PKO hardware to support
554 * simple priority based queues for the ethernet ports. Each
555 * port is configured with a number of priority queues based
556 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
557 * priority than the previous.
558 *
559 * @return Zero on success, non-zero on failure
560 */
561int cvmx_helper_initialize_packet_io_global(void)
562{
563    int result = 0;
564    int interface;
565    cvmx_l2c_cfg_t l2c_cfg;
566    cvmx_smix_en_t smix_en;
567    const int num_interfaces = cvmx_helper_get_number_of_interfaces();
568
569    /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */
570    if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
571        __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
572
573    /* Tell L2 to give the IOB statically higher priority compared to the
574        cores. This avoids conditions where IO blocks might be starved under
575        very high L2 loads */
576    l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
577    l2c_cfg.s.lrf_arb_mode = 0;
578    l2c_cfg.s.rfb_arb_mode = 0;
579    cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
580
581    /* Make sure SMI/MDIO is enabled so we can query PHYs */
582    smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
583    if (!smix_en.s.en)
584    {
585        smix_en.s.en = 1;
586        cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
587    }
588
589    /* Newer chips actually have two SMI/MDIO interfaces */
590    if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
591        !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
592        !OCTEON_IS_MODEL(OCTEON_CN50XX))
593    {
594        smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
595        if (!smix_en.s.en)
596        {
597            smix_en.s.en = 1;
598            cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
599        }
600    }
601
602    cvmx_pko_initialize_global();
603    for (interface=0; interface<num_interfaces; interface++)
604    {
605        result |= cvmx_helper_interface_probe(interface);
606        if (cvmx_helper_ports_on_interface(interface) > 0)
607            cvmx_dprintf("Interface %d has %d ports (%s)\n",
608                     interface, cvmx_helper_ports_on_interface(interface),
609                     cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface)));
610        result |= __cvmx_helper_interface_setup_ipd(interface);
611        result |= __cvmx_helper_interface_setup_pko(interface);
612    }
613
614    result |= __cvmx_helper_global_setup_ipd();
615    result |= __cvmx_helper_global_setup_pko();
616
617    /* Enable any flow control and backpressure */
618    result |= __cvmx_helper_global_setup_backpressure();
619
620#if CVMX_HELPER_ENABLE_IPD
621    result |= cvmx_helper_ipd_and_packet_input_enable();
622#endif
623    return result;
624}
625
626
627/**
628 * Does core local initialization for packet io
629 *
630 * @return Zero on success, non-zero on failure
631 */
632int cvmx_helper_initialize_packet_io_local(void)
633{
634    return cvmx_pko_initialize_local();
635}
636
637
638/**
639 * Auto configure an IPD/PKO port link state and speed. This
640 * function basically does the equivalent of:
641 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
642 *
643 * @param ipd_port IPD/PKO port to auto configure
644 *
645 * @return Link state after configure
646 */
647cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
648{
649    cvmx_helper_link_info_t link_info;
650    int interface = cvmx_helper_get_interface_num(ipd_port);
651    int index = cvmx_helper_get_interface_index_num(ipd_port);
652
653    if (index >= cvmx_helper_ports_on_interface(interface))
654    {
655        link_info.u64 = 0;
656        return link_info;
657    }
658
659    link_info = cvmx_helper_link_get(ipd_port);
660    if (link_info.u64 ==  port_link_info[ipd_port].u64)
661        return link_info;
662
663    /* If we fail to set the link speed, port_link_info will not change */
664    cvmx_helper_link_set(ipd_port, link_info);
665
666    /* port_link_info should be the current value, which will be different
667        than expect if cvmx_helper_link_set() failed */
668    return port_link_info[ipd_port];
669}
670
671
672/**
673 * Return the link state of an IPD/PKO port as returned by
674 * auto negotiation. The result of this function may not match
675 * Octeon's link config if auto negotiation has changed since
676 * the last call to cvmx_helper_link_set().
677 *
678 * @param ipd_port IPD/PKO port to query
679 *
680 * @return Link state
681 */
682cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
683{
684    cvmx_helper_link_info_t result;
685    int interface = cvmx_helper_get_interface_num(ipd_port);
686    int index = cvmx_helper_get_interface_index_num(ipd_port);
687
688    /* The default result will be a down link unless the code below
689        changes it */
690    result.u64 = 0;
691
692    if (index >= cvmx_helper_ports_on_interface(interface))
693        return result;
694
695    switch (cvmx_helper_interface_get_mode(interface))
696    {
697        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
698        case CVMX_HELPER_INTERFACE_MODE_PCIE:
699            /* Network links are not supported */
700            break;
701        case CVMX_HELPER_INTERFACE_MODE_XAUI:
702            result = __cvmx_helper_xaui_link_get(ipd_port);
703            break;
704        case CVMX_HELPER_INTERFACE_MODE_GMII:
705            if (index == 0)
706                result = __cvmx_helper_rgmii_link_get(ipd_port);
707            else
708            {
709                result.s.full_duplex = 1;
710                result.s.link_up = 1;
711                result.s.speed = 1000;
712            }
713            break;
714        case CVMX_HELPER_INTERFACE_MODE_RGMII:
715            result = __cvmx_helper_rgmii_link_get(ipd_port);
716            break;
717        case CVMX_HELPER_INTERFACE_MODE_SPI:
718            result = __cvmx_helper_spi_link_get(ipd_port);
719            break;
720        case CVMX_HELPER_INTERFACE_MODE_SGMII:
721        case CVMX_HELPER_INTERFACE_MODE_PICMG:
722            result = __cvmx_helper_sgmii_link_get(ipd_port);
723            break;
724        case CVMX_HELPER_INTERFACE_MODE_NPI:
725        case CVMX_HELPER_INTERFACE_MODE_LOOP:
726            /* Network links are not supported */
727            break;
728    }
729    return result;
730}
731
732
733/**
734 * Configure an IPD/PKO port for the specified link state. This
735 * function does not influence auto negotiation at the PHY level.
736 * The passed link state must always match the link state returned
737 * by cvmx_helper_link_get(). It is normally best to use
738 * cvmx_helper_link_autoconf() instead.
739 *
740 * @param ipd_port  IPD/PKO port to configure
741 * @param link_info The new link state
742 *
743 * @return Zero on success, negative on failure
744 */
745int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
746{
747    int result = -1;
748    int interface = cvmx_helper_get_interface_num(ipd_port);
749    int index = cvmx_helper_get_interface_index_num(ipd_port);
750
751    if (index >= cvmx_helper_ports_on_interface(interface))
752        return -1;
753
754    switch (cvmx_helper_interface_get_mode(interface))
755    {
756        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
757        case CVMX_HELPER_INTERFACE_MODE_PCIE:
758            break;
759        case CVMX_HELPER_INTERFACE_MODE_XAUI:
760            result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
761            break;
762        /* RGMII/GMII/MII are all treated about the same. Most functions
763            refer to these ports as RGMII */
764        case CVMX_HELPER_INTERFACE_MODE_RGMII:
765        case CVMX_HELPER_INTERFACE_MODE_GMII:
766            result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
767            break;
768        case CVMX_HELPER_INTERFACE_MODE_SPI:
769            result = __cvmx_helper_spi_link_set(ipd_port, link_info);
770            break;
771        case CVMX_HELPER_INTERFACE_MODE_SGMII:
772        case CVMX_HELPER_INTERFACE_MODE_PICMG:
773            result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
774            break;
775        case CVMX_HELPER_INTERFACE_MODE_NPI:
776        case CVMX_HELPER_INTERFACE_MODE_LOOP:
777            break;
778    }
779    /* Set the port_link_info here so that the link status is updated
780       no matter how cvmx_helper_link_set is called. We don't change
781       the value if link_set failed */
782    if (result == 0)
783        port_link_info[ipd_port].u64 = link_info.u64;
784    return result;
785}
786
787
788/**
789 * Configure a port for internal and/or external loopback. Internal loopback
790 * causes packets sent by the port to be received by Octeon. External loopback
791 * causes packets received from the wire to sent out again.
792 *
793 * @param ipd_port IPD/PKO port to loopback.
794 * @param enable_internal
795 *                 Non zero if you want internal loopback
796 * @param enable_external
797 *                 Non zero if you want external loopback
798 *
799 * @return Zero on success, negative on failure.
800 */
801int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external)
802{
803    int result = -1;
804    int interface = cvmx_helper_get_interface_num(ipd_port);
805    int index = cvmx_helper_get_interface_index_num(ipd_port);
806
807    if (index >= cvmx_helper_ports_on_interface(interface))
808        return -1;
809
810    switch (cvmx_helper_interface_get_mode(interface))
811    {
812        case CVMX_HELPER_INTERFACE_MODE_DISABLED:
813        case CVMX_HELPER_INTERFACE_MODE_PCIE:
814        case CVMX_HELPER_INTERFACE_MODE_SPI:
815        case CVMX_HELPER_INTERFACE_MODE_NPI:
816        case CVMX_HELPER_INTERFACE_MODE_LOOP:
817            break;
818        case CVMX_HELPER_INTERFACE_MODE_XAUI:
819            result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external);
820            break;
821        case CVMX_HELPER_INTERFACE_MODE_RGMII:
822        case CVMX_HELPER_INTERFACE_MODE_GMII:
823            result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external);
824            break;
825        case CVMX_HELPER_INTERFACE_MODE_SGMII:
826        case CVMX_HELPER_INTERFACE_MODE_PICMG:
827            result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external);
828            break;
829    }
830    return result;
831}
832
833#endif /* CVMX_ENABLE_PKO_FUNCTIONS */
834