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