]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/octeon-sdk/cvmx-helper.c
Merge dtracetoolkit/dtruss from the vendor.
[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     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  */
120 int 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  */
136 cvmx_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  */
207 static 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  */
261 int 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  */
323 static 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  */
344 static 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  */
369 static 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  */
408 static 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  */
427 static 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  */
472 static 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  */
522 int 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  */
561 int 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  */
632 int 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  */
647 cvmx_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  */
682 cvmx_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  */
745 int 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  */
801 int 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 */