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