Merge branch 'x86/cleanups' into irq/sparseirq
[pandora-kernel.git] / drivers / staging / octeon / cvmx-helper.c
1 /***********************license start***************
2  * Author: Cavium Networks
3  *
4  * Contact: support@caviumnetworks.com
5  * This file is part of the OCTEON SDK
6  *
7  * Copyright (c) 2003-2008 Cavium Networks
8  *
9  * This file is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License, Version 2, as
11  * published by the Free Software Foundation.
12  *
13  * This file is distributed in the hope that it will be useful, but
14  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
15  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
16  * NONINFRINGEMENT.  See the GNU General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this file; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22  * or visit http://www.gnu.org/licenses/.
23  *
24  * This file may also be available under a different license from Cavium.
25  * Contact Cavium Networks for more information
26  ***********************license end**************************************/
27
28 /*
29  *
30  * Helper functions for common, but complicated tasks.
31  *
32  */
33 #include <asm/octeon/octeon.h>
34
35 #include "cvmx-config.h"
36
37 #include "cvmx-fpa.h"
38 #include "cvmx-pip.h"
39 #include "cvmx-pko.h"
40 #include "cvmx-ipd.h"
41 #include "cvmx-spi.h"
42 #include "cvmx-helper.h"
43 #include "cvmx-helper-board.h"
44
45 #include "cvmx-pip-defs.h"
46 #include "cvmx-smix-defs.h"
47 #include "cvmx-asxx-defs.h"
48
49 /**
50  * cvmx_override_pko_queue_priority(int ipd_port, uint64_t
51  * priorities[16]) is a function pointer. It is meant to allow
52  * customization of the PKO queue priorities based on the port
53  * number. Users should set this pointer to a function before
54  * calling any cvmx-helper operations.
55  */
56 void (*cvmx_override_pko_queue_priority) (int pko_port,
57                                           uint64_t priorities[16]);
58
59 /**
60  * cvmx_override_ipd_port_setup(int ipd_port) is a function
61  * pointer. It is meant to allow customization of the IPD port
62  * setup before packet input/output comes online. It is called
63  * after cvmx-helper does the default IPD configuration, but
64  * before IPD is enabled. Users should set this pointer to a
65  * function before calling any cvmx-helper operations.
66  */
67 void (*cvmx_override_ipd_port_setup) (int ipd_port);
68
69 /* Port count per interface */
70 static int interface_port_count[4] = { 0, 0, 0, 0 };
71
72 /* Port last configured link info index by IPD/PKO port */
73 static cvmx_helper_link_info_t
74     port_link_info[CVMX_PIP_NUM_INPUT_PORTS];
75
76 /**
77  * Return the number of interfaces the chip has. Each interface
78  * may have multiple ports. Most chips support two interfaces,
79  * but the CNX0XX and CNX1XX are exceptions. These only support
80  * one interface.
81  *
82  * Returns Number of interfaces on chip
83  */
84 int cvmx_helper_get_number_of_interfaces(void)
85 {
86         if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
87                 return 4;
88         else
89                 return 3;
90 }
91
92 /**
93  * Return the number of ports on an interface. Depending on the
94  * chip and configuration, this can be 1-16. A value of 0
95  * specifies that the interface doesn't exist or isn't usable.
96  *
97  * @interface: Interface to get the port count for
98  *
99  * Returns Number of ports on interface. Can be Zero.
100  */
101 int cvmx_helper_ports_on_interface(int interface)
102 {
103         return interface_port_count[interface];
104 }
105
106 /**
107  * Get the operating mode of an interface. Depending on the Octeon
108  * chip and configuration, this function returns an enumeration
109  * of the type of packet I/O supported by an interface.
110  *
111  * @interface: Interface to probe
112  *
113  * Returns Mode of the interface. Unknown or unsupported interfaces return
114  *         DISABLED.
115  */
116 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
117 {
118         union cvmx_gmxx_inf_mode mode;
119         if (interface == 2)
120                 return CVMX_HELPER_INTERFACE_MODE_NPI;
121
122         if (interface == 3) {
123                 if (OCTEON_IS_MODEL(OCTEON_CN56XX)
124                     || OCTEON_IS_MODEL(OCTEON_CN52XX))
125                         return CVMX_HELPER_INTERFACE_MODE_LOOP;
126                 else
127                         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
128         }
129
130         if (interface == 0
131             && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
132             && cvmx_sysinfo_get()->board_rev_major == 1) {
133                 /*
134                  * Lie about interface type of CN3005 board.  This
135                  * board has a switch on port 1 like the other
136                  * evaluation boards, but it is connected over RGMII
137                  * instead of GMII.  Report GMII mode so that the
138                  * speed is forced to 1 Gbit full duplex.  Other than
139                  * some initial configuration (which does not use the
140                  * output of this function) there is no difference in
141                  * setup between GMII and RGMII modes.
142                  */
143                 return CVMX_HELPER_INTERFACE_MODE_GMII;
144         }
145
146         /* Interface 1 is always disabled on CN31XX and CN30XX */
147         if ((interface == 1)
148             && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
149                 || OCTEON_IS_MODEL(OCTEON_CN50XX)
150                 || OCTEON_IS_MODEL(OCTEON_CN52XX)))
151                 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
152
153         mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
154
155         if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
156                 switch (mode.cn56xx.mode) {
157                 case 0:
158                         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
159                 case 1:
160                         return CVMX_HELPER_INTERFACE_MODE_XAUI;
161                 case 2:
162                         return CVMX_HELPER_INTERFACE_MODE_SGMII;
163                 case 3:
164                         return CVMX_HELPER_INTERFACE_MODE_PICMG;
165                 default:
166                         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
167                 }
168         } else {
169                 if (!mode.s.en)
170                         return CVMX_HELPER_INTERFACE_MODE_DISABLED;
171
172                 if (mode.s.type) {
173                         if (OCTEON_IS_MODEL(OCTEON_CN38XX)
174                             || OCTEON_IS_MODEL(OCTEON_CN58XX))
175                                 return CVMX_HELPER_INTERFACE_MODE_SPI;
176                         else
177                                 return CVMX_HELPER_INTERFACE_MODE_GMII;
178                 } else
179                         return CVMX_HELPER_INTERFACE_MODE_RGMII;
180         }
181 }
182
183 /**
184  * Configure the IPD/PIP tagging and QoS options for a specific
185  * port. This function determines the POW work queue entry
186  * contents for a port. The setup performed here is controlled by
187  * the defines in executive-config.h.
188  *
189  * @ipd_port: Port to configure. This follows the IPD numbering, not the
190  *                 per interface numbering
191  *
192  * Returns Zero on success, negative on failure
193  */
194 static int __cvmx_helper_port_setup_ipd(int ipd_port)
195 {
196         union cvmx_pip_prt_cfgx port_config;
197         union cvmx_pip_prt_tagx tag_config;
198
199         port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
200         tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
201
202         /* Have each port go to a different POW queue */
203         port_config.s.qos = ipd_port & 0x7;
204
205         /* Process the headers and place the IP header in the work queue */
206         port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
207
208         tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
209         tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
210         tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
211         tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
212         tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
213         tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
214         tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
215         tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
216         tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
217         tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
218         tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
219         tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
220         tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
221         tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
222         tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
223         tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
224         /* Put all packets in group 0. Other groups can be used by the app */
225         tag_config.s.grp = 0;
226
227         cvmx_pip_config_port(ipd_port, port_config, tag_config);
228
229         /* Give the user a chance to override our setting for each port */
230         if (cvmx_override_ipd_port_setup)
231                 cvmx_override_ipd_port_setup(ipd_port);
232
233         return 0;
234 }
235
236 /**
237  * This function probes an interface to determine the actual
238  * number of hardware ports connected to it. It doesn't setup the
239  * ports or enable them. The main goal here is to set the global
240  * interface_port_count[interface] correctly. Hardware setup of the
241  * ports will be performed later.
242  *
243  * @interface: Interface to probe
244  *
245  * Returns Zero on success, negative on failure
246  */
247 int cvmx_helper_interface_probe(int interface)
248 {
249         /* At this stage in the game we don't want packets to be moving yet.
250            The following probe calls should perform hardware setup
251            needed to determine port counts. Receive must still be disabled */
252         switch (cvmx_helper_interface_get_mode(interface)) {
253                 /* These types don't support ports to IPD/PKO */
254         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
255         case CVMX_HELPER_INTERFACE_MODE_PCIE:
256                 interface_port_count[interface] = 0;
257                 break;
258                 /* XAUI is a single high speed port */
259         case CVMX_HELPER_INTERFACE_MODE_XAUI:
260                 interface_port_count[interface] =
261                     __cvmx_helper_xaui_probe(interface);
262                 break;
263                 /*
264                  * RGMII/GMII/MII are all treated about the same. Most
265                  * functions refer to these ports as RGMII.
266                  */
267         case CVMX_HELPER_INTERFACE_MODE_RGMII:
268         case CVMX_HELPER_INTERFACE_MODE_GMII:
269                 interface_port_count[interface] =
270                     __cvmx_helper_rgmii_probe(interface);
271                 break;
272                 /*
273                  * SPI4 can have 1-16 ports depending on the device at
274                  * the other end.
275                  */
276         case CVMX_HELPER_INTERFACE_MODE_SPI:
277                 interface_port_count[interface] =
278                     __cvmx_helper_spi_probe(interface);
279                 break;
280                 /*
281                  * SGMII can have 1-4 ports depending on how many are
282                  * hooked up.
283                  */
284         case CVMX_HELPER_INTERFACE_MODE_SGMII:
285         case CVMX_HELPER_INTERFACE_MODE_PICMG:
286                 interface_port_count[interface] =
287                     __cvmx_helper_sgmii_probe(interface);
288                 break;
289                 /* PCI target Network Packet Interface */
290         case CVMX_HELPER_INTERFACE_MODE_NPI:
291                 interface_port_count[interface] =
292                     __cvmx_helper_npi_probe(interface);
293                 break;
294                 /*
295                  * Special loopback only ports. These are not the same
296                  * as other ports in loopback mode.
297                  */
298         case CVMX_HELPER_INTERFACE_MODE_LOOP:
299                 interface_port_count[interface] =
300                     __cvmx_helper_loop_probe(interface);
301                 break;
302         }
303
304         interface_port_count[interface] =
305             __cvmx_helper_board_interface_probe(interface,
306                                                 interface_port_count
307                                                 [interface]);
308
309         /* Make sure all global variables propagate to other cores */
310         CVMX_SYNCWS;
311
312         return 0;
313 }
314
315 /**
316  * Setup the IPD/PIP for the ports on an interface. Packet
317  * classification and tagging are set for every port on the
318  * interface. The number of ports on the interface must already
319  * have been probed.
320  *
321  * @interface: Interface to setup IPD/PIP for
322  *
323  * Returns Zero on success, negative on failure
324  */
325 static int __cvmx_helper_interface_setup_ipd(int interface)
326 {
327         int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
328         int num_ports = interface_port_count[interface];
329
330         while (num_ports--) {
331                 __cvmx_helper_port_setup_ipd(ipd_port);
332                 ipd_port++;
333         }
334         return 0;
335 }
336
337 /**
338  * Setup global setting for IPD/PIP not related to a specific
339  * interface or port. This must be called before IPD is enabled.
340  *
341  * Returns Zero on success, negative on failure.
342  */
343 static int __cvmx_helper_global_setup_ipd(void)
344 {
345         /* Setup the global packet input options */
346         cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
347                         CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
348                         CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
349                         /* The +8 is to account for the next ptr */
350                         (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
351                         /* The +8 is to account for the next ptr */
352                         (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
353                         CVMX_FPA_WQE_POOL,
354                         CVMX_IPD_OPC_MODE_STT,
355                         CVMX_HELPER_ENABLE_BACK_PRESSURE);
356         return 0;
357 }
358
359 /**
360  * Setup the PKO for the ports on an interface. The number of
361  * queues per port and the priority of each PKO output queue
362  * is set here. PKO must be disabled when this function is called.
363  *
364  * @interface: Interface to setup PKO for
365  *
366  * Returns Zero on success, negative on failure
367  */
368 static int __cvmx_helper_interface_setup_pko(int interface)
369 {
370         /*
371          * Each packet output queue has an associated priority. The
372          * higher the priority, the more often it can send a packet. A
373          * priority of 8 means it can send in all 8 rounds of
374          * contention. We're going to make each queue one less than
375          * the last.  The vector of priorities has been extended to
376          * support CN5xxx CPUs, where up to 16 queues can be
377          * associated to a port.  To keep backward compatibility we
378          * don't change the initial 8 priorities and replicate them in
379          * the second half.  With per-core PKO queues (PKO lockless
380          * operation) all queues have the same priority.
381          */
382         uint64_t priorities[16] =
383             { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
384
385         /*
386          * Setup the IPD/PIP and PKO for the ports discovered
387          * above. Here packet classification, tagging and output
388          * priorities are set.
389          */
390         int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
391         int num_ports = interface_port_count[interface];
392         while (num_ports--) {
393                 /*
394                  * Give the user a chance to override the per queue
395                  * priorities.
396                  */
397                 if (cvmx_override_pko_queue_priority)
398                         cvmx_override_pko_queue_priority(ipd_port, priorities);
399
400                 cvmx_pko_config_port(ipd_port,
401                                      cvmx_pko_get_base_queue_per_core(ipd_port,
402                                                                       0),
403                                      cvmx_pko_get_num_queues(ipd_port),
404                                      priorities);
405                 ipd_port++;
406         }
407         return 0;
408 }
409
410 /**
411  * Setup global setting for PKO not related to a specific
412  * interface or port. This must be called before PKO is enabled.
413  *
414  * Returns Zero on success, negative on failure.
415  */
416 static int __cvmx_helper_global_setup_pko(void)
417 {
418         /*
419          * Disable tagwait FAU timeout. This needs to be done before
420          * anyone might start packet output using tags.
421          */
422         union cvmx_iob_fau_timeout fau_to;
423         fau_to.u64 = 0;
424         fau_to.s.tout_val = 0xfff;
425         fau_to.s.tout_enb = 0;
426         cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
427         return 0;
428 }
429
430 /**
431  * Setup global backpressure setting.
432  *
433  * Returns Zero on success, negative on failure
434  */
435 static int __cvmx_helper_global_setup_backpressure(void)
436 {
437 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
438         /* Disable backpressure if configured to do so */
439         /* Disable backpressure (pause frame) generation */
440         int num_interfaces = cvmx_helper_get_number_of_interfaces();
441         int interface;
442         for (interface = 0; interface < num_interfaces; interface++) {
443                 switch (cvmx_helper_interface_get_mode(interface)) {
444                 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
445                 case CVMX_HELPER_INTERFACE_MODE_PCIE:
446                 case CVMX_HELPER_INTERFACE_MODE_NPI:
447                 case CVMX_HELPER_INTERFACE_MODE_LOOP:
448                 case CVMX_HELPER_INTERFACE_MODE_XAUI:
449                         break;
450                 case CVMX_HELPER_INTERFACE_MODE_RGMII:
451                 case CVMX_HELPER_INTERFACE_MODE_GMII:
452                 case CVMX_HELPER_INTERFACE_MODE_SPI:
453                 case CVMX_HELPER_INTERFACE_MODE_SGMII:
454                 case CVMX_HELPER_INTERFACE_MODE_PICMG:
455                         cvmx_gmx_set_backpressure_override(interface, 0xf);
456                         break;
457                 }
458         }
459 #endif
460
461         return 0;
462 }
463
464 /**
465  * Enable packet input/output from the hardware. This function is
466  * called after all internal setup is complete and IPD is enabled.
467  * After this function completes, packets will be accepted from the
468  * hardware ports. PKO should still be disabled to make sure packets
469  * aren't sent out partially setup hardware.
470  *
471  * @interface: Interface to enable
472  *
473  * Returns Zero on success, negative on failure
474  */
475 static int __cvmx_helper_packet_hardware_enable(int interface)
476 {
477         int result = 0;
478         switch (cvmx_helper_interface_get_mode(interface)) {
479                 /* These types don't support ports to IPD/PKO */
480         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
481         case CVMX_HELPER_INTERFACE_MODE_PCIE:
482                 /* Nothing to do */
483                 break;
484                 /* XAUI is a single high speed port */
485         case CVMX_HELPER_INTERFACE_MODE_XAUI:
486                 result = __cvmx_helper_xaui_enable(interface);
487                 break;
488                 /*
489                  * RGMII/GMII/MII are all treated about the same. Most
490                  * functions refer to these ports as RGMII
491                  */
492         case CVMX_HELPER_INTERFACE_MODE_RGMII:
493         case CVMX_HELPER_INTERFACE_MODE_GMII:
494                 result = __cvmx_helper_rgmii_enable(interface);
495                 break;
496                 /*
497                  * SPI4 can have 1-16 ports depending on the device at
498                  * the other end
499                  */
500         case CVMX_HELPER_INTERFACE_MODE_SPI:
501                 result = __cvmx_helper_spi_enable(interface);
502                 break;
503                 /*
504                  * SGMII can have 1-4 ports depending on how many are
505                  * hooked up
506                  */
507         case CVMX_HELPER_INTERFACE_MODE_SGMII:
508         case CVMX_HELPER_INTERFACE_MODE_PICMG:
509                 result = __cvmx_helper_sgmii_enable(interface);
510                 break;
511                 /* PCI target Network Packet Interface */
512         case CVMX_HELPER_INTERFACE_MODE_NPI:
513                 result = __cvmx_helper_npi_enable(interface);
514                 break;
515                 /*
516                  * Special loopback only ports. These are not the same
517                  * as other ports in loopback mode
518                  */
519         case CVMX_HELPER_INTERFACE_MODE_LOOP:
520                 result = __cvmx_helper_loop_enable(interface);
521                 break;
522         }
523         result |= __cvmx_helper_board_hardware_enable(interface);
524         return result;
525 }
526
527 /**
528  * Function to adjust internal IPD pointer alignments
529  *
530  * Returns 0 on success
531  *         !0 on failure
532  */
533 int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
534 {
535 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
536      (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
537 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
538         (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
539 #define FIX_IPD_OUTPORT 0
540         /* Ports 0-15 are interface 0, 16-31 are interface 1 */
541 #define INTERFACE(port) (port >> 4)
542 #define INDEX(port) (port & 0xf)
543         uint64_t *p64;
544         cvmx_pko_command_word0_t pko_command;
545         union cvmx_buf_ptr g_buffer, pkt_buffer;
546         cvmx_wqe_t *work;
547         int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
548         union cvmx_gmxx_prtx_cfg gmx_cfg;
549         int retry_cnt;
550         int retry_loop_cnt;
551         int mtu;
552         int i;
553         cvmx_helper_link_info_t link_info;
554
555         /* Save values for restore at end */
556         uint64_t prtx_cfg =
557             cvmx_read_csr(CVMX_GMXX_PRTX_CFG
558                           (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
559         uint64_t tx_ptr_en =
560             cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
561         uint64_t rx_ptr_en =
562             cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
563         uint64_t rxx_jabber =
564             cvmx_read_csr(CVMX_GMXX_RXX_JABBER
565                           (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
566         uint64_t frame_max =
567             cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
568                           (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
569
570         /* Configure port to gig FDX as required for loopback mode */
571         cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
572
573         /*
574          * Disable reception on all ports so if traffic is present it
575          * will not interfere.
576          */
577         cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
578
579         cvmx_wait(100000000ull);
580
581         for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
582                 retry_cnt = 100000;
583                 wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
584                 pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
585                 wqe_pcnt &= 0x7f;
586
587                 num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
588
589                 if (num_segs == 0)
590                         goto fix_ipd_exit;
591
592                 num_segs += 1;
593
594                 size =
595                     FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
596                     ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
597                     (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
598
599                 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
600                                1 << INDEX(FIX_IPD_OUTPORT));
601                 CVMX_SYNC;
602
603                 g_buffer.u64 = 0;
604                 g_buffer.s.addr =
605                     cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
606                 if (g_buffer.s.addr == 0) {
607                         cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
608                                      "buffer allocation failure.\n");
609                         goto fix_ipd_exit;
610                 }
611
612                 g_buffer.s.pool = CVMX_FPA_WQE_POOL;
613                 g_buffer.s.size = num_segs;
614
615                 pkt_buffer.u64 = 0;
616                 pkt_buffer.s.addr =
617                     cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
618                 if (pkt_buffer.s.addr == 0) {
619                         cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
620                                      "buffer allocation failure.\n");
621                         goto fix_ipd_exit;
622                 }
623                 pkt_buffer.s.i = 1;
624                 pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
625                 pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
626
627                 p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
628                 p64[0] = 0xffffffffffff0000ull;
629                 p64[1] = 0x08004510ull;
630                 p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
631                 p64[3] = 0x3a5fc0a81073c0a8ull;
632
633                 for (i = 0; i < num_segs; i++) {
634                         if (i > 0)
635                                 pkt_buffer.s.size =
636                                     FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
637
638                         if (i == (num_segs - 1))
639                                 pkt_buffer.s.i = 0;
640
641                         *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
642                                                        8 * i) = pkt_buffer.u64;
643                 }
644
645                 /* Build the PKO command */
646                 pko_command.u64 = 0;
647                 pko_command.s.segs = num_segs;
648                 pko_command.s.total_bytes = size;
649                 pko_command.s.dontfree = 0;
650                 pko_command.s.gather = 1;
651
652                 gmx_cfg.u64 =
653                     cvmx_read_csr(CVMX_GMXX_PRTX_CFG
654                                   (INDEX(FIX_IPD_OUTPORT),
655                                    INTERFACE(FIX_IPD_OUTPORT)));
656                 gmx_cfg.s.en = 1;
657                 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
658                                (INDEX(FIX_IPD_OUTPORT),
659                                 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
660                 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
661                                1 << INDEX(FIX_IPD_OUTPORT));
662                 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
663                                1 << INDEX(FIX_IPD_OUTPORT));
664
665                 mtu =
666                     cvmx_read_csr(CVMX_GMXX_RXX_JABBER
667                                   (INDEX(FIX_IPD_OUTPORT),
668                                    INTERFACE(FIX_IPD_OUTPORT)));
669                 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
670                                (INDEX(FIX_IPD_OUTPORT),
671                                 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
672                 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
673                                (INDEX(FIX_IPD_OUTPORT),
674                                 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
675
676                 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
677                                              cvmx_pko_get_base_queue
678                                              (FIX_IPD_OUTPORT),
679                                              CVMX_PKO_LOCK_CMD_QUEUE);
680                 cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
681                                             cvmx_pko_get_base_queue
682                                             (FIX_IPD_OUTPORT), pko_command,
683                                             g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
684
685                 CVMX_SYNC;
686
687                 do {
688                         work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
689                         retry_cnt--;
690                 } while ((work == NULL) && (retry_cnt > 0));
691
692                 if (!retry_cnt)
693                         cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
694                                      "get_work() timeout occured.\n");
695
696                 /* Free packet */
697                 if (work)
698                         cvmx_helper_free_packet_data(work);
699         }
700
701 fix_ipd_exit:
702
703         /* Return CSR configs to saved values */
704         cvmx_write_csr(CVMX_GMXX_PRTX_CFG
705                        (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
706                        prtx_cfg);
707         cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
708                        tx_ptr_en);
709         cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
710                        rx_ptr_en);
711         cvmx_write_csr(CVMX_GMXX_RXX_JABBER
712                        (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
713                        rxx_jabber);
714         cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
715                        (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
716                        frame_max);
717         cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
718         /* Set link to down so autonegotiation will set it up again */
719         link_info.u64 = 0;
720         cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info);
721
722         /*
723          * Bring the link back up as autonegotiation is not done in
724          * user applications.
725          */
726         cvmx_helper_link_autoconf(FIX_IPD_OUTPORT);
727
728         CVMX_SYNC;
729         if (num_segs)
730                 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
731
732         return !!num_segs;
733
734 }
735
736 /**
737  * Called after all internal packet IO paths are setup. This
738  * function enables IPD/PIP and begins packet input and output.
739  *
740  * Returns Zero on success, negative on failure
741  */
742 int cvmx_helper_ipd_and_packet_input_enable(void)
743 {
744         int num_interfaces;
745         int interface;
746
747         /* Enable IPD */
748         cvmx_ipd_enable();
749
750         /*
751          * Time to enable hardware ports packet input and output. Note
752          * that at this point IPD/PIP must be fully functional and PKO
753          * must be disabled
754          */
755         num_interfaces = cvmx_helper_get_number_of_interfaces();
756         for (interface = 0; interface < num_interfaces; interface++) {
757                 if (cvmx_helper_ports_on_interface(interface) > 0)
758                         __cvmx_helper_packet_hardware_enable(interface);
759         }
760
761         /* Finally enable PKO now that the entire path is up and running */
762         cvmx_pko_enable();
763
764         if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
765              || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
766             && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
767                 __cvmx_helper_errata_fix_ipd_ptr_alignment();
768         return 0;
769 }
770
771 /**
772  * Initialize the PIP, IPD, and PKO hardware to support
773  * simple priority based queues for the ethernet ports. Each
774  * port is configured with a number of priority queues based
775  * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
776  * priority than the previous.
777  *
778  * Returns Zero on success, non-zero on failure
779  */
780 int cvmx_helper_initialize_packet_io_global(void)
781 {
782         int result = 0;
783         int interface;
784         union cvmx_l2c_cfg l2c_cfg;
785         union cvmx_smix_en smix_en;
786         const int num_interfaces = cvmx_helper_get_number_of_interfaces();
787
788         /*
789          * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
790          * be disabled.
791          */
792         if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
793                 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
794
795         /*
796          * Tell L2 to give the IOB statically higher priority compared
797          * to the cores. This avoids conditions where IO blocks might
798          * be starved under very high L2 loads.
799          */
800         l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
801         l2c_cfg.s.lrf_arb_mode = 0;
802         l2c_cfg.s.rfb_arb_mode = 0;
803         cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
804
805         /* Make sure SMI/MDIO is enabled so we can query PHYs */
806         smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
807         if (!smix_en.s.en) {
808                 smix_en.s.en = 1;
809                 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
810         }
811
812         /* Newer chips actually have two SMI/MDIO interfaces */
813         if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
814             !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
815             !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
816                 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
817                 if (!smix_en.s.en) {
818                         smix_en.s.en = 1;
819                         cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
820                 }
821         }
822
823         cvmx_pko_initialize_global();
824         for (interface = 0; interface < num_interfaces; interface++) {
825                 result |= cvmx_helper_interface_probe(interface);
826                 if (cvmx_helper_ports_on_interface(interface) > 0)
827                         cvmx_dprintf("Interface %d has %d ports (%s)\n",
828                                      interface,
829                                      cvmx_helper_ports_on_interface(interface),
830                                      cvmx_helper_interface_mode_to_string
831                                      (cvmx_helper_interface_get_mode
832                                       (interface)));
833                 result |= __cvmx_helper_interface_setup_ipd(interface);
834                 result |= __cvmx_helper_interface_setup_pko(interface);
835         }
836
837         result |= __cvmx_helper_global_setup_ipd();
838         result |= __cvmx_helper_global_setup_pko();
839
840         /* Enable any flow control and backpressure */
841         result |= __cvmx_helper_global_setup_backpressure();
842
843 #if CVMX_HELPER_ENABLE_IPD
844         result |= cvmx_helper_ipd_and_packet_input_enable();
845 #endif
846         return result;
847 }
848
849 /**
850  * Does core local initialization for packet io
851  *
852  * Returns Zero on success, non-zero on failure
853  */
854 int cvmx_helper_initialize_packet_io_local(void)
855 {
856         return cvmx_pko_initialize_local();
857 }
858
859 /**
860  * Auto configure an IPD/PKO port link state and speed. This
861  * function basically does the equivalent of:
862  * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port));
863  *
864  * @ipd_port: IPD/PKO port to auto configure
865  *
866  * Returns Link state after configure
867  */
868 cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port)
869 {
870         cvmx_helper_link_info_t link_info;
871         int interface = cvmx_helper_get_interface_num(ipd_port);
872         int index = cvmx_helper_get_interface_index_num(ipd_port);
873
874         if (index >= cvmx_helper_ports_on_interface(interface)) {
875                 link_info.u64 = 0;
876                 return link_info;
877         }
878
879         link_info = cvmx_helper_link_get(ipd_port);
880         if (link_info.u64 == port_link_info[ipd_port].u64)
881                 return link_info;
882
883         /* If we fail to set the link speed, port_link_info will not change */
884         cvmx_helper_link_set(ipd_port, link_info);
885
886         /*
887          * port_link_info should be the current value, which will be
888          * different than expect if cvmx_helper_link_set() failed.
889          */
890         return port_link_info[ipd_port];
891 }
892
893 /**
894  * Return the link state of an IPD/PKO port as returned by
895  * auto negotiation. The result of this function may not match
896  * Octeon's link config if auto negotiation has changed since
897  * the last call to cvmx_helper_link_set().
898  *
899  * @ipd_port: IPD/PKO port to query
900  *
901  * Returns Link state
902  */
903 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
904 {
905         cvmx_helper_link_info_t result;
906         int interface = cvmx_helper_get_interface_num(ipd_port);
907         int index = cvmx_helper_get_interface_index_num(ipd_port);
908
909         /* The default result will be a down link unless the code below
910            changes it */
911         result.u64 = 0;
912
913         if (index >= cvmx_helper_ports_on_interface(interface))
914                 return result;
915
916         switch (cvmx_helper_interface_get_mode(interface)) {
917         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
918         case CVMX_HELPER_INTERFACE_MODE_PCIE:
919                 /* Network links are not supported */
920                 break;
921         case CVMX_HELPER_INTERFACE_MODE_XAUI:
922                 result = __cvmx_helper_xaui_link_get(ipd_port);
923                 break;
924         case CVMX_HELPER_INTERFACE_MODE_GMII:
925                 if (index == 0)
926                         result = __cvmx_helper_rgmii_link_get(ipd_port);
927                 else {
928                         result.s.full_duplex = 1;
929                         result.s.link_up = 1;
930                         result.s.speed = 1000;
931                 }
932                 break;
933         case CVMX_HELPER_INTERFACE_MODE_RGMII:
934                 result = __cvmx_helper_rgmii_link_get(ipd_port);
935                 break;
936         case CVMX_HELPER_INTERFACE_MODE_SPI:
937                 result = __cvmx_helper_spi_link_get(ipd_port);
938                 break;
939         case CVMX_HELPER_INTERFACE_MODE_SGMII:
940         case CVMX_HELPER_INTERFACE_MODE_PICMG:
941                 result = __cvmx_helper_sgmii_link_get(ipd_port);
942                 break;
943         case CVMX_HELPER_INTERFACE_MODE_NPI:
944         case CVMX_HELPER_INTERFACE_MODE_LOOP:
945                 /* Network links are not supported */
946                 break;
947         }
948         return result;
949 }
950
951 /**
952  * Configure an IPD/PKO port for the specified link state. This
953  * function does not influence auto negotiation at the PHY level.
954  * The passed link state must always match the link state returned
955  * by cvmx_helper_link_get(). It is normally best to use
956  * cvmx_helper_link_autoconf() instead.
957  *
958  * @ipd_port:  IPD/PKO port to configure
959  * @link_info: The new link state
960  *
961  * Returns Zero on success, negative on failure
962  */
963 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
964 {
965         int result = -1;
966         int interface = cvmx_helper_get_interface_num(ipd_port);
967         int index = cvmx_helper_get_interface_index_num(ipd_port);
968
969         if (index >= cvmx_helper_ports_on_interface(interface))
970                 return -1;
971
972         switch (cvmx_helper_interface_get_mode(interface)) {
973         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
974         case CVMX_HELPER_INTERFACE_MODE_PCIE:
975                 break;
976         case CVMX_HELPER_INTERFACE_MODE_XAUI:
977                 result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
978                 break;
979                 /*
980                  * RGMII/GMII/MII are all treated about the same. Most
981                  * functions refer to these ports as RGMII.
982                  */
983         case CVMX_HELPER_INTERFACE_MODE_RGMII:
984         case CVMX_HELPER_INTERFACE_MODE_GMII:
985                 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
986                 break;
987         case CVMX_HELPER_INTERFACE_MODE_SPI:
988                 result = __cvmx_helper_spi_link_set(ipd_port, link_info);
989                 break;
990         case CVMX_HELPER_INTERFACE_MODE_SGMII:
991         case CVMX_HELPER_INTERFACE_MODE_PICMG:
992                 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
993                 break;
994         case CVMX_HELPER_INTERFACE_MODE_NPI:
995         case CVMX_HELPER_INTERFACE_MODE_LOOP:
996                 break;
997         }
998         /* Set the port_link_info here so that the link status is updated
999            no matter how cvmx_helper_link_set is called. We don't change
1000            the value if link_set failed */
1001         if (result == 0)
1002                 port_link_info[ipd_port].u64 = link_info.u64;
1003         return result;
1004 }
1005
1006 /**
1007  * Configure a port for internal and/or external loopback. Internal loopback
1008  * causes packets sent by the port to be received by Octeon. External loopback
1009  * causes packets received from the wire to sent out again.
1010  *
1011  * @ipd_port: IPD/PKO port to loopback.
1012  * @enable_internal:
1013  *                 Non zero if you want internal loopback
1014  * @enable_external:
1015  *                 Non zero if you want external loopback
1016  *
1017  * Returns Zero on success, negative on failure.
1018  */
1019 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1020                                    int enable_external)
1021 {
1022         int result = -1;
1023         int interface = cvmx_helper_get_interface_num(ipd_port);
1024         int index = cvmx_helper_get_interface_index_num(ipd_port);
1025
1026         if (index >= cvmx_helper_ports_on_interface(interface))
1027                 return -1;
1028
1029         switch (cvmx_helper_interface_get_mode(interface)) {
1030         case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1031         case CVMX_HELPER_INTERFACE_MODE_PCIE:
1032         case CVMX_HELPER_INTERFACE_MODE_SPI:
1033         case CVMX_HELPER_INTERFACE_MODE_NPI:
1034         case CVMX_HELPER_INTERFACE_MODE_LOOP:
1035                 break;
1036         case CVMX_HELPER_INTERFACE_MODE_XAUI:
1037                 result =
1038                     __cvmx_helper_xaui_configure_loopback(ipd_port,
1039                                                           enable_internal,
1040                                                           enable_external);
1041                 break;
1042         case CVMX_HELPER_INTERFACE_MODE_RGMII:
1043         case CVMX_HELPER_INTERFACE_MODE_GMII:
1044                 result =
1045                     __cvmx_helper_rgmii_configure_loopback(ipd_port,
1046                                                            enable_internal,
1047                                                            enable_external);
1048                 break;
1049         case CVMX_HELPER_INTERFACE_MODE_SGMII:
1050         case CVMX_HELPER_INTERFACE_MODE_PICMG:
1051                 result =
1052                     __cvmx_helper_sgmii_configure_loopback(ipd_port,
1053                                                            enable_internal,
1054                                                            enable_external);
1055                 break;
1056         }
1057         return result;
1058 }