1 /***********************license start***************
2 * Author: Cavium Networks
4 * Contact: support@caviumnetworks.com
5 * This file is part of the OCTEON SDK
7 * Copyright (c) 2003-2008 Cavium Networks
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.
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
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/.
24 * This file may also be available under a different license from Cavium.
25 * Contact Cavium Networks for more information
26 ***********************license end**************************************/
30 * Helper functions for common, but complicated tasks.
33 #include <asm/octeon/octeon.h>
35 #include "cvmx-config.h"
42 #include "cvmx-helper.h"
43 #include "cvmx-helper-board.h"
45 #include "cvmx-pip-defs.h"
46 #include "cvmx-smix-defs.h"
47 #include "cvmx-asxx-defs.h"
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.
56 void (*cvmx_override_pko_queue_priority
) (int pko_port
,
57 uint64_t priorities
[16]);
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.
67 void (*cvmx_override_ipd_port_setup
) (int ipd_port
);
69 /* Port count per interface */
70 static int interface_port_count
[4] = { 0, 0, 0, 0 };
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
];
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
82 * Returns Number of interfaces on chip
84 int cvmx_helper_get_number_of_interfaces(void)
86 if (OCTEON_IS_MODEL(OCTEON_CN56XX
) || OCTEON_IS_MODEL(OCTEON_CN52XX
))
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.
97 * @interface: Interface to get the port count for
99 * Returns Number of ports on interface. Can be Zero.
101 int cvmx_helper_ports_on_interface(int interface
)
103 return interface_port_count
[interface
];
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.
111 * @interface: Interface to probe
113 * Returns Mode of the interface. Unknown or unsupported interfaces return
116 cvmx_helper_interface_mode_t
cvmx_helper_interface_get_mode(int interface
)
118 union cvmx_gmxx_inf_mode mode
;
120 return CVMX_HELPER_INTERFACE_MODE_NPI
;
122 if (interface
== 3) {
123 if (OCTEON_IS_MODEL(OCTEON_CN56XX
)
124 || OCTEON_IS_MODEL(OCTEON_CN52XX
))
125 return CVMX_HELPER_INTERFACE_MODE_LOOP
;
127 return CVMX_HELPER_INTERFACE_MODE_DISABLED
;
131 && cvmx_sysinfo_get()->board_type
== CVMX_BOARD_TYPE_CN3005_EVB_HS5
132 && cvmx_sysinfo_get()->board_rev_major
== 1) {
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.
143 return CVMX_HELPER_INTERFACE_MODE_GMII
;
146 /* Interface 1 is always disabled on CN31XX and CN30XX */
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
;
153 mode
.u64
= cvmx_read_csr(CVMX_GMXX_INF_MODE(interface
));
155 if (OCTEON_IS_MODEL(OCTEON_CN56XX
) || OCTEON_IS_MODEL(OCTEON_CN52XX
)) {
156 switch (mode
.cn56xx
.mode
) {
158 return CVMX_HELPER_INTERFACE_MODE_DISABLED
;
160 return CVMX_HELPER_INTERFACE_MODE_XAUI
;
162 return CVMX_HELPER_INTERFACE_MODE_SGMII
;
164 return CVMX_HELPER_INTERFACE_MODE_PICMG
;
166 return CVMX_HELPER_INTERFACE_MODE_DISABLED
;
170 return CVMX_HELPER_INTERFACE_MODE_DISABLED
;
173 if (OCTEON_IS_MODEL(OCTEON_CN38XX
)
174 || OCTEON_IS_MODEL(OCTEON_CN58XX
))
175 return CVMX_HELPER_INTERFACE_MODE_SPI
;
177 return CVMX_HELPER_INTERFACE_MODE_GMII
;
179 return CVMX_HELPER_INTERFACE_MODE_RGMII
;
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.
189 * @ipd_port: Port to configure. This follows the IPD numbering, not the
190 * per interface numbering
192 * Returns Zero on success, negative on failure
194 static int __cvmx_helper_port_setup_ipd(int ipd_port
)
196 union cvmx_pip_prt_cfgx port_config
;
197 union cvmx_pip_prt_tagx tag_config
;
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
));
202 /* Have each port go to a different POW queue */
203 port_config
.s
.qos
= ipd_port
& 0x7;
205 /* Process the headers and place the IP header in the work queue */
206 port_config
.s
.mode
= CVMX_HELPER_INPUT_PORT_SKIP_MODE
;
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;
227 cvmx_pip_config_port(ipd_port
, port_config
, tag_config
);
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
);
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.
243 * @interface: Interface to probe
245 * Returns Zero on success, negative on failure
247 int cvmx_helper_interface_probe(int interface
)
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;
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
);
264 * RGMII/GMII/MII are all treated about the same. Most
265 * functions refer to these ports as RGMII.
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
);
273 * SPI4 can have 1-16 ports depending on the device at
276 case CVMX_HELPER_INTERFACE_MODE_SPI
:
277 interface_port_count
[interface
] =
278 __cvmx_helper_spi_probe(interface
);
281 * SGMII can have 1-4 ports depending on how many are
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
);
289 /* PCI target Network Packet Interface */
290 case CVMX_HELPER_INTERFACE_MODE_NPI
:
291 interface_port_count
[interface
] =
292 __cvmx_helper_npi_probe(interface
);
295 * Special loopback only ports. These are not the same
296 * as other ports in loopback mode.
298 case CVMX_HELPER_INTERFACE_MODE_LOOP
:
299 interface_port_count
[interface
] =
300 __cvmx_helper_loop_probe(interface
);
304 interface_port_count
[interface
] =
305 __cvmx_helper_board_interface_probe(interface
,
309 /* Make sure all global variables propagate to other cores */
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
321 * @interface: Interface to setup IPD/PIP for
323 * Returns Zero on success, negative on failure
325 static int __cvmx_helper_interface_setup_ipd(int interface
)
327 int ipd_port
= cvmx_helper_get_ipd_port(interface
, 0);
328 int num_ports
= interface_port_count
[interface
];
330 while (num_ports
--) {
331 __cvmx_helper_port_setup_ipd(ipd_port
);
338 * Setup global setting for IPD/PIP not related to a specific
339 * interface or port. This must be called before IPD is enabled.
341 * Returns Zero on success, negative on failure.
343 static int __cvmx_helper_global_setup_ipd(void)
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,
354 CVMX_IPD_OPC_MODE_STT
,
355 CVMX_HELPER_ENABLE_BACK_PRESSURE
);
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.
364 * @interface: Interface to setup PKO for
366 * Returns Zero on success, negative on failure
368 static int __cvmx_helper_interface_setup_pko(int interface
)
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.
382 uint64_t priorities
[16] =
383 { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
386 * Setup the IPD/PIP and PKO for the ports discovered
387 * above. Here packet classification, tagging and output
388 * priorities are set.
390 int ipd_port
= cvmx_helper_get_ipd_port(interface
, 0);
391 int num_ports
= interface_port_count
[interface
];
392 while (num_ports
--) {
394 * Give the user a chance to override the per queue
397 if (cvmx_override_pko_queue_priority
)
398 cvmx_override_pko_queue_priority(ipd_port
, priorities
);
400 cvmx_pko_config_port(ipd_port
,
401 cvmx_pko_get_base_queue_per_core(ipd_port
,
403 cvmx_pko_get_num_queues(ipd_port
),
411 * Setup global setting for PKO not related to a specific
412 * interface or port. This must be called before PKO is enabled.
414 * Returns Zero on success, negative on failure.
416 static int __cvmx_helper_global_setup_pko(void)
419 * Disable tagwait FAU timeout. This needs to be done before
420 * anyone might start packet output using tags.
422 union cvmx_iob_fau_timeout fau_to
;
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
);
431 * Setup global backpressure setting.
433 * Returns Zero on success, negative on failure
435 static int __cvmx_helper_global_setup_backpressure(void)
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();
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
:
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);
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.
471 * @interface: Interface to enable
473 * Returns Zero on success, negative on failure
475 static int __cvmx_helper_packet_hardware_enable(int interface
)
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
:
484 /* XAUI is a single high speed port */
485 case CVMX_HELPER_INTERFACE_MODE_XAUI
:
486 result
= __cvmx_helper_xaui_enable(interface
);
489 * RGMII/GMII/MII are all treated about the same. Most
490 * functions refer to these ports as RGMII
492 case CVMX_HELPER_INTERFACE_MODE_RGMII
:
493 case CVMX_HELPER_INTERFACE_MODE_GMII
:
494 result
= __cvmx_helper_rgmii_enable(interface
);
497 * SPI4 can have 1-16 ports depending on the device at
500 case CVMX_HELPER_INTERFACE_MODE_SPI
:
501 result
= __cvmx_helper_spi_enable(interface
);
504 * SGMII can have 1-4 ports depending on how many are
507 case CVMX_HELPER_INTERFACE_MODE_SGMII
:
508 case CVMX_HELPER_INTERFACE_MODE_PICMG
:
509 result
= __cvmx_helper_sgmii_enable(interface
);
511 /* PCI target Network Packet Interface */
512 case CVMX_HELPER_INTERFACE_MODE_NPI
:
513 result
= __cvmx_helper_npi_enable(interface
);
516 * Special loopback only ports. These are not the same
517 * as other ports in loopback mode
519 case CVMX_HELPER_INTERFACE_MODE_LOOP
:
520 result
= __cvmx_helper_loop_enable(interface
);
523 result
|= __cvmx_helper_board_hardware_enable(interface
);
528 * Function to adjust internal IPD pointer alignments
530 * Returns 0 on success
533 int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
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)
544 cvmx_pko_command_word0_t pko_command
;
545 union cvmx_buf_ptr g_buffer
, pkt_buffer
;
547 int size
, num_segs
= 0, wqe_pcnt
, pkt_pcnt
;
548 union cvmx_gmxx_prtx_cfg gmx_cfg
;
553 cvmx_helper_link_info_t link_info
;
555 /* Save values for restore at end */
557 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
558 (INDEX(FIX_IPD_OUTPORT
), INTERFACE(FIX_IPD_OUTPORT
)));
560 cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT
)));
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
)));
567 cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
568 (INDEX(FIX_IPD_OUTPORT
), INTERFACE(FIX_IPD_OUTPORT
)));
570 /* Configure port to gig FDX as required for loopback mode */
571 cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT
);
574 * Disable reception on all ports so if traffic is present it
575 * will not interfere.
577 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT
)), 0);
579 cvmx_wait(100000000ull);
581 for (retry_loop_cnt
= 0; retry_loop_cnt
< 10; retry_loop_cnt
++) {
583 wqe_pcnt
= cvmx_read_csr(CVMX_IPD_PTR_COUNT
);
584 pkt_pcnt
= (wqe_pcnt
>> 7) & 0x7f;
587 num_segs
= (2 + pkt_pcnt
- wqe_pcnt
) & 3;
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);
599 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT
)),
600 1 << INDEX(FIX_IPD_OUTPORT
));
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");
612 g_buffer
.s
.pool
= CVMX_FPA_WQE_POOL
;
613 g_buffer
.s
.size
= num_segs
;
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");
624 pkt_buffer
.s
.pool
= CVMX_FPA_PACKET_POOL
;
625 pkt_buffer
.s
.size
= FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES
;
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
;
633 for (i
= 0; i
< num_segs
; i
++) {
636 FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES
;
638 if (i
== (num_segs
- 1))
641 *(uint64_t *) cvmx_phys_to_ptr(g_buffer
.s
.addr
+
642 8 * i
) = pkt_buffer
.u64
;
645 /* Build the PKO command */
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;
653 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
654 (INDEX(FIX_IPD_OUTPORT
),
655 INTERFACE(FIX_IPD_OUTPORT
)));
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
));
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);
676 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT
,
677 cvmx_pko_get_base_queue
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
);
688 work
= cvmx_pow_work_request_sync(CVMX_POW_WAIT
);
690 } while ((work
== NULL
) && (retry_cnt
> 0));
693 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
694 "get_work() timeout occured.\n");
698 cvmx_helper_free_packet_data(work
);
703 /* Return CSR configs to saved values */
704 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
705 (INDEX(FIX_IPD_OUTPORT
), INTERFACE(FIX_IPD_OUTPORT
)),
707 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT
)),
709 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT
)),
711 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
712 (INDEX(FIX_IPD_OUTPORT
), INTERFACE(FIX_IPD_OUTPORT
)),
714 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
715 (INDEX(FIX_IPD_OUTPORT
), INTERFACE(FIX_IPD_OUTPORT
)),
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 */
720 cvmx_helper_link_set(FIX_IPD_OUTPORT
, link_info
);
723 * Bring the link back up as autonegotiation is not done in
726 cvmx_helper_link_autoconf(FIX_IPD_OUTPORT
);
730 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
737 * Called after all internal packet IO paths are setup. This
738 * function enables IPD/PIP and begins packet input and output.
740 * Returns Zero on success, negative on failure
742 int cvmx_helper_ipd_and_packet_input_enable(void)
751 * Time to enable hardware ports packet input and output. Note
752 * that at this point IPD/PIP must be fully functional and PKO
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
);
761 /* Finally enable PKO now that the entire path is up and running */
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();
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.
778 * Returns Zero on success, non-zero on failure
780 int cvmx_helper_initialize_packet_io_global(void)
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();
789 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
792 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0
))
793 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
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.
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
);
805 /* Make sure SMI/MDIO is enabled so we can query PHYs */
806 smix_en
.u64
= cvmx_read_csr(CVMX_SMIX_EN(0));
809 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en
.u64
);
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));
819 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en
.u64
);
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",
829 cvmx_helper_ports_on_interface(interface
),
830 cvmx_helper_interface_mode_to_string
831 (cvmx_helper_interface_get_mode
833 result
|= __cvmx_helper_interface_setup_ipd(interface
);
834 result
|= __cvmx_helper_interface_setup_pko(interface
);
837 result
|= __cvmx_helper_global_setup_ipd();
838 result
|= __cvmx_helper_global_setup_pko();
840 /* Enable any flow control and backpressure */
841 result
|= __cvmx_helper_global_setup_backpressure();
843 #if CVMX_HELPER_ENABLE_IPD
844 result
|= cvmx_helper_ipd_and_packet_input_enable();
850 * Does core local initialization for packet io
852 * Returns Zero on success, non-zero on failure
854 int cvmx_helper_initialize_packet_io_local(void)
856 return cvmx_pko_initialize_local();
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));
864 * @ipd_port: IPD/PKO port to auto configure
866 * Returns Link state after configure
868 cvmx_helper_link_info_t
cvmx_helper_link_autoconf(int ipd_port
)
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
);
874 if (index
>= cvmx_helper_ports_on_interface(interface
)) {
879 link_info
= cvmx_helper_link_get(ipd_port
);
880 if (link_info
.u64
== port_link_info
[ipd_port
].u64
)
883 /* If we fail to set the link speed, port_link_info will not change */
884 cvmx_helper_link_set(ipd_port
, link_info
);
887 * port_link_info should be the current value, which will be
888 * different than expect if cvmx_helper_link_set() failed.
890 return port_link_info
[ipd_port
];
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().
899 * @ipd_port: IPD/PKO port to query
903 cvmx_helper_link_info_t
cvmx_helper_link_get(int ipd_port
)
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
);
909 /* The default result will be a down link unless the code below
913 if (index
>= cvmx_helper_ports_on_interface(interface
))
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 */
921 case CVMX_HELPER_INTERFACE_MODE_XAUI
:
922 result
= __cvmx_helper_xaui_link_get(ipd_port
);
924 case CVMX_HELPER_INTERFACE_MODE_GMII
:
926 result
= __cvmx_helper_rgmii_link_get(ipd_port
);
928 result
.s
.full_duplex
= 1;
929 result
.s
.link_up
= 1;
930 result
.s
.speed
= 1000;
933 case CVMX_HELPER_INTERFACE_MODE_RGMII
:
934 result
= __cvmx_helper_rgmii_link_get(ipd_port
);
936 case CVMX_HELPER_INTERFACE_MODE_SPI
:
937 result
= __cvmx_helper_spi_link_get(ipd_port
);
939 case CVMX_HELPER_INTERFACE_MODE_SGMII
:
940 case CVMX_HELPER_INTERFACE_MODE_PICMG
:
941 result
= __cvmx_helper_sgmii_link_get(ipd_port
);
943 case CVMX_HELPER_INTERFACE_MODE_NPI
:
944 case CVMX_HELPER_INTERFACE_MODE_LOOP
:
945 /* Network links are not supported */
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.
958 * @ipd_port: IPD/PKO port to configure
959 * @link_info: The new link state
961 * Returns Zero on success, negative on failure
963 int cvmx_helper_link_set(int ipd_port
, cvmx_helper_link_info_t link_info
)
966 int interface
= cvmx_helper_get_interface_num(ipd_port
);
967 int index
= cvmx_helper_get_interface_index_num(ipd_port
);
969 if (index
>= cvmx_helper_ports_on_interface(interface
))
972 switch (cvmx_helper_interface_get_mode(interface
)) {
973 case CVMX_HELPER_INTERFACE_MODE_DISABLED
:
974 case CVMX_HELPER_INTERFACE_MODE_PCIE
:
976 case CVMX_HELPER_INTERFACE_MODE_XAUI
:
977 result
= __cvmx_helper_xaui_link_set(ipd_port
, link_info
);
980 * RGMII/GMII/MII are all treated about the same. Most
981 * functions refer to these ports as RGMII.
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
);
987 case CVMX_HELPER_INTERFACE_MODE_SPI
:
988 result
= __cvmx_helper_spi_link_set(ipd_port
, link_info
);
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
);
994 case CVMX_HELPER_INTERFACE_MODE_NPI
:
995 case CVMX_HELPER_INTERFACE_MODE_LOOP
:
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 */
1002 port_link_info
[ipd_port
].u64
= link_info
.u64
;
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.
1011 * @ipd_port: IPD/PKO port to loopback.
1013 * Non zero if you want internal loopback
1015 * Non zero if you want external loopback
1017 * Returns Zero on success, negative on failure.
1019 int cvmx_helper_configure_loopback(int ipd_port
, int enable_internal
,
1020 int enable_external
)
1023 int interface
= cvmx_helper_get_interface_num(ipd_port
);
1024 int index
= cvmx_helper_get_interface_index_num(ipd_port
);
1026 if (index
>= cvmx_helper_ports_on_interface(interface
))
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
:
1036 case CVMX_HELPER_INTERFACE_MODE_XAUI
:
1038 __cvmx_helper_xaui_configure_loopback(ipd_port
,
1042 case CVMX_HELPER_INTERFACE_MODE_RGMII
:
1043 case CVMX_HELPER_INTERFACE_MODE_GMII
:
1045 __cvmx_helper_rgmii_configure_loopback(ipd_port
,
1049 case CVMX_HELPER_INTERFACE_MODE_SGMII
:
1050 case CVMX_HELPER_INTERFACE_MODE_PICMG
:
1052 __cvmx_helper_sgmii_configure_loopback(ipd_port
,