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 <asm/octeon/cvmx-config.h>
37 #include <asm/octeon/cvmx-fpa.h>
38 #include <asm/octeon/cvmx-pip.h>
39 #include <asm/octeon/cvmx-pko.h>
40 #include <asm/octeon/cvmx-ipd.h>
41 #include <asm/octeon/cvmx-spi.h>
42 #include <asm/octeon/cvmx-helper.h>
43 #include <asm/octeon/cvmx-helper-board.h>
45 #include <asm/octeon/cvmx-pip-defs.h>
46 #include <asm/octeon/cvmx-smix-defs.h>
47 #include <asm/octeon/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[9];
73 * Return the number of interfaces the chip has. Each interface
74 * may have multiple ports. Most chips support two interfaces,
75 * but the CNX0XX and CNX1XX are exceptions. These only support
78 * Returns Number of interfaces on chip
80 int cvmx_helper_get_number_of_interfaces(void)
82 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
84 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
86 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
91 EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
94 * Return the number of ports on an interface. Depending on the
95 * chip and configuration, this can be 1-16. A value of 0
96 * specifies that the interface doesn't exist or isn't usable.
98 * @interface: Interface to get the port count for
100 * Returns Number of ports on interface. Can be Zero.
102 int cvmx_helper_ports_on_interface(int interface)
104 return interface_port_count[interface];
106 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
110 * Return interface mode for CN68xx.
112 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
114 union cvmx_mio_qlmx_cfg qlm_cfg;
117 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
118 /* QLM is disabled when QLM SPD is 15. */
119 if (qlm_cfg.s.qlm_spd == 15)
120 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
122 if (qlm_cfg.s.qlm_cfg == 2)
123 return CVMX_HELPER_INTERFACE_MODE_SGMII;
124 else if (qlm_cfg.s.qlm_cfg == 3)
125 return CVMX_HELPER_INTERFACE_MODE_XAUI;
127 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
131 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
132 /* QLM is disabled when QLM SPD is 15. */
133 if (qlm_cfg.s.qlm_spd == 15)
134 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
136 if (qlm_cfg.s.qlm_cfg == 2)
137 return CVMX_HELPER_INTERFACE_MODE_SGMII;
138 else if (qlm_cfg.s.qlm_cfg == 3)
139 return CVMX_HELPER_INTERFACE_MODE_XAUI;
141 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
143 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
144 /* QLM is disabled when QLM SPD is 15. */
145 if (qlm_cfg.s.qlm_spd == 15) {
146 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
147 } else if (qlm_cfg.s.qlm_cfg != 0) {
148 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
149 if (qlm_cfg.s.qlm_cfg != 0)
150 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
152 return CVMX_HELPER_INTERFACE_MODE_NPI;
154 return CVMX_HELPER_INTERFACE_MODE_LOOP;
156 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
162 * Return interface mode for an Octeon II
164 static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
166 union cvmx_gmxx_inf_mode mode;
168 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
169 return __cvmx_get_mode_cn68xx(interface);
172 return CVMX_HELPER_INTERFACE_MODE_NPI;
175 return CVMX_HELPER_INTERFACE_MODE_LOOP;
177 /* Only present in CN63XX & CN66XX Octeon model */
178 if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
179 (interface == 4 || interface == 5)) ||
180 (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
181 interface >= 4 && interface <= 7)) {
182 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
185 if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
186 union cvmx_mio_qlmx_cfg mio_qlm_cfg;
188 /* QLM2 is SGMII0 and QLM1 is SGMII1 */
190 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
191 else if (interface == 1)
192 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
194 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
196 if (mio_qlm_cfg.s.qlm_spd == 15)
197 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
199 if (mio_qlm_cfg.s.qlm_cfg == 9)
200 return CVMX_HELPER_INTERFACE_MODE_SGMII;
201 else if (mio_qlm_cfg.s.qlm_cfg == 11)
202 return CVMX_HELPER_INTERFACE_MODE_XAUI;
204 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
205 } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
206 union cvmx_mio_qlmx_cfg qlm_cfg;
208 if (interface == 0) {
209 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
210 if (qlm_cfg.s.qlm_cfg == 2)
211 return CVMX_HELPER_INTERFACE_MODE_SGMII;
212 else if (qlm_cfg.s.qlm_cfg == 3)
213 return CVMX_HELPER_INTERFACE_MODE_XAUI;
215 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
216 } else if (interface == 1) {
217 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
218 if (qlm_cfg.s.qlm_cfg == 2)
219 return CVMX_HELPER_INTERFACE_MODE_SGMII;
220 else if (qlm_cfg.s.qlm_cfg == 3)
221 return CVMX_HELPER_INTERFACE_MODE_XAUI;
223 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
225 } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
226 if (interface == 0) {
227 union cvmx_mio_qlmx_cfg qlm_cfg;
228 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
229 if (qlm_cfg.s.qlm_cfg == 2)
230 return CVMX_HELPER_INTERFACE_MODE_SGMII;
232 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
235 if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
236 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
238 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
240 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
241 switch (mode.cn63xx.mode) {
243 return CVMX_HELPER_INTERFACE_MODE_SGMII;
245 return CVMX_HELPER_INTERFACE_MODE_XAUI;
247 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
251 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
254 return CVMX_HELPER_INTERFACE_MODE_GMII;
256 return CVMX_HELPER_INTERFACE_MODE_RGMII;
262 * Return interface mode for CN7XXX.
264 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
266 union cvmx_gmxx_inf_mode mode;
268 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
273 switch (mode.cn68xx.mode) {
275 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
278 return CVMX_HELPER_INTERFACE_MODE_SGMII;
280 return CVMX_HELPER_INTERFACE_MODE_XAUI;
282 return CVMX_HELPER_INTERFACE_MODE_SGMII;
285 return CVMX_HELPER_INTERFACE_MODE_NPI;
287 return CVMX_HELPER_INTERFACE_MODE_LOOP;
289 /* TODO: Implement support for AGL (RGMII). */
290 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
292 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
297 * Get the operating mode of an interface. Depending on the Octeon
298 * chip and configuration, this function returns an enumeration
299 * of the type of packet I/O supported by an interface.
301 * @interface: Interface to probe
303 * Returns Mode of the interface. Unknown or unsupported interfaces return
306 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
308 union cvmx_gmxx_inf_mode mode;
311 interface >= cvmx_helper_get_number_of_interfaces())
312 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
317 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
318 return __cvmx_get_mode_cn7xxx(interface);
323 if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
324 return __cvmx_get_mode_octeon2(interface);
327 * Octeon and Octeon Plus models
330 return CVMX_HELPER_INTERFACE_MODE_NPI;
332 if (interface == 3) {
333 if (OCTEON_IS_MODEL(OCTEON_CN56XX)
334 || OCTEON_IS_MODEL(OCTEON_CN52XX))
335 return CVMX_HELPER_INTERFACE_MODE_LOOP;
337 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
341 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
342 && cvmx_sysinfo_get()->board_rev_major == 1) {
344 * Lie about interface type of CN3005 board. This
345 * board has a switch on port 1 like the other
346 * evaluation boards, but it is connected over RGMII
347 * instead of GMII. Report GMII mode so that the
348 * speed is forced to 1 Gbit full duplex. Other than
349 * some initial configuration (which does not use the
350 * output of this function) there is no difference in
351 * setup between GMII and RGMII modes.
353 return CVMX_HELPER_INTERFACE_MODE_GMII;
356 /* Interface 1 is always disabled on CN31XX and CN30XX */
358 && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
359 || OCTEON_IS_MODEL(OCTEON_CN50XX)
360 || OCTEON_IS_MODEL(OCTEON_CN52XX)))
361 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
363 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
365 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
366 switch (mode.cn56xx.mode) {
368 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
370 return CVMX_HELPER_INTERFACE_MODE_XAUI;
372 return CVMX_HELPER_INTERFACE_MODE_SGMII;
374 return CVMX_HELPER_INTERFACE_MODE_PICMG;
376 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
380 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
383 if (OCTEON_IS_MODEL(OCTEON_CN38XX)
384 || OCTEON_IS_MODEL(OCTEON_CN58XX))
385 return CVMX_HELPER_INTERFACE_MODE_SPI;
387 return CVMX_HELPER_INTERFACE_MODE_GMII;
389 return CVMX_HELPER_INTERFACE_MODE_RGMII;
392 EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
395 * Configure the IPD/PIP tagging and QoS options for a specific
396 * port. This function determines the POW work queue entry
397 * contents for a port. The setup performed here is controlled by
398 * the defines in executive-config.h.
400 * @ipd_port: Port to configure. This follows the IPD numbering, not the
401 * per interface numbering
403 * Returns Zero on success, negative on failure
405 static int __cvmx_helper_port_setup_ipd(int ipd_port)
407 union cvmx_pip_prt_cfgx port_config;
408 union cvmx_pip_prt_tagx tag_config;
410 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
411 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
413 /* Have each port go to a different POW queue */
414 port_config.s.qos = ipd_port & 0x7;
416 /* Process the headers and place the IP header in the work queue */
417 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
419 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
420 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
421 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
422 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
423 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
424 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
425 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
426 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
427 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
428 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
429 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
430 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
431 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
432 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
433 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
434 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
435 /* Put all packets in group 0. Other groups can be used by the app */
436 tag_config.s.grp = 0;
438 cvmx_pip_config_port(ipd_port, port_config, tag_config);
440 /* Give the user a chance to override our setting for each port */
441 if (cvmx_override_ipd_port_setup)
442 cvmx_override_ipd_port_setup(ipd_port);
448 * This function sets the interface_port_count[interface] correctly,
449 * without modifying any hardware configuration. Hardware setup of
450 * the ports will be performed later.
452 * @interface: Interface to probe
454 * Returns Zero on success, negative on failure
456 int cvmx_helper_interface_enumerate(int interface)
458 switch (cvmx_helper_interface_get_mode(interface)) {
459 /* These types don't support ports to IPD/PKO */
460 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
461 case CVMX_HELPER_INTERFACE_MODE_PCIE:
462 interface_port_count[interface] = 0;
464 /* XAUI is a single high speed port */
465 case CVMX_HELPER_INTERFACE_MODE_XAUI:
466 interface_port_count[interface] =
467 __cvmx_helper_xaui_enumerate(interface);
470 * RGMII/GMII/MII are all treated about the same. Most
471 * functions refer to these ports as RGMII.
473 case CVMX_HELPER_INTERFACE_MODE_RGMII:
474 case CVMX_HELPER_INTERFACE_MODE_GMII:
475 interface_port_count[interface] =
476 __cvmx_helper_rgmii_enumerate(interface);
479 * SPI4 can have 1-16 ports depending on the device at
482 case CVMX_HELPER_INTERFACE_MODE_SPI:
483 interface_port_count[interface] =
484 __cvmx_helper_spi_enumerate(interface);
487 * SGMII can have 1-4 ports depending on how many are
490 case CVMX_HELPER_INTERFACE_MODE_SGMII:
491 case CVMX_HELPER_INTERFACE_MODE_PICMG:
492 interface_port_count[interface] =
493 __cvmx_helper_sgmii_enumerate(interface);
495 /* PCI target Network Packet Interface */
496 case CVMX_HELPER_INTERFACE_MODE_NPI:
497 interface_port_count[interface] =
498 __cvmx_helper_npi_enumerate(interface);
501 * Special loopback only ports. These are not the same
502 * as other ports in loopback mode.
504 case CVMX_HELPER_INTERFACE_MODE_LOOP:
505 interface_port_count[interface] =
506 __cvmx_helper_loop_enumerate(interface);
510 interface_port_count[interface] =
511 __cvmx_helper_board_interface_probe(interface,
515 /* Make sure all global variables propagate to other cores */
522 * This function probes an interface to determine the actual
523 * number of hardware ports connected to it. It doesn't setup the
524 * ports or enable them. The main goal here is to set the global
525 * interface_port_count[interface] correctly. Hardware setup of the
526 * ports will be performed later.
528 * @interface: Interface to probe
530 * Returns Zero on success, negative on failure
532 int cvmx_helper_interface_probe(int interface)
534 cvmx_helper_interface_enumerate(interface);
535 /* At this stage in the game we don't want packets to be moving yet.
536 The following probe calls should perform hardware setup
537 needed to determine port counts. Receive must still be disabled */
538 switch (cvmx_helper_interface_get_mode(interface)) {
539 /* These types don't support ports to IPD/PKO */
540 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
541 case CVMX_HELPER_INTERFACE_MODE_PCIE:
543 /* XAUI is a single high speed port */
544 case CVMX_HELPER_INTERFACE_MODE_XAUI:
545 __cvmx_helper_xaui_probe(interface);
548 * RGMII/GMII/MII are all treated about the same. Most
549 * functions refer to these ports as RGMII.
551 case CVMX_HELPER_INTERFACE_MODE_RGMII:
552 case CVMX_HELPER_INTERFACE_MODE_GMII:
553 __cvmx_helper_rgmii_probe(interface);
556 * SPI4 can have 1-16 ports depending on the device at
559 case CVMX_HELPER_INTERFACE_MODE_SPI:
560 __cvmx_helper_spi_probe(interface);
563 * SGMII can have 1-4 ports depending on how many are
566 case CVMX_HELPER_INTERFACE_MODE_SGMII:
567 case CVMX_HELPER_INTERFACE_MODE_PICMG:
568 __cvmx_helper_sgmii_probe(interface);
570 /* PCI target Network Packet Interface */
571 case CVMX_HELPER_INTERFACE_MODE_NPI:
572 __cvmx_helper_npi_probe(interface);
575 * Special loopback only ports. These are not the same
576 * as other ports in loopback mode.
578 case CVMX_HELPER_INTERFACE_MODE_LOOP:
579 __cvmx_helper_loop_probe(interface);
583 /* Make sure all global variables propagate to other cores */
590 * Setup the IPD/PIP for the ports on an interface. Packet
591 * classification and tagging are set for every port on the
592 * interface. The number of ports on the interface must already
595 * @interface: Interface to setup IPD/PIP for
597 * Returns Zero on success, negative on failure
599 static int __cvmx_helper_interface_setup_ipd(int interface)
601 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
602 int num_ports = interface_port_count[interface];
604 while (num_ports--) {
605 __cvmx_helper_port_setup_ipd(ipd_port);
612 * Setup global setting for IPD/PIP not related to a specific
613 * interface or port. This must be called before IPD is enabled.
615 * Returns Zero on success, negative on failure.
617 static int __cvmx_helper_global_setup_ipd(void)
619 /* Setup the global packet input options */
620 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
621 CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
622 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
623 /* The +8 is to account for the next ptr */
624 (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
625 /* The +8 is to account for the next ptr */
626 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
628 CVMX_IPD_OPC_MODE_STT,
629 CVMX_HELPER_ENABLE_BACK_PRESSURE);
634 * Setup the PKO for the ports on an interface. The number of
635 * queues per port and the priority of each PKO output queue
636 * is set here. PKO must be disabled when this function is called.
638 * @interface: Interface to setup PKO for
640 * Returns Zero on success, negative on failure
642 static int __cvmx_helper_interface_setup_pko(int interface)
645 * Each packet output queue has an associated priority. The
646 * higher the priority, the more often it can send a packet. A
647 * priority of 8 means it can send in all 8 rounds of
648 * contention. We're going to make each queue one less than
649 * the last. The vector of priorities has been extended to
650 * support CN5xxx CPUs, where up to 16 queues can be
651 * associated to a port. To keep backward compatibility we
652 * don't change the initial 8 priorities and replicate them in
653 * the second half. With per-core PKO queues (PKO lockless
654 * operation) all queues have the same priority.
656 uint64_t priorities[16] =
657 { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
660 * Setup the IPD/PIP and PKO for the ports discovered
661 * above. Here packet classification, tagging and output
662 * priorities are set.
664 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
665 int num_ports = interface_port_count[interface];
666 while (num_ports--) {
668 * Give the user a chance to override the per queue
671 if (cvmx_override_pko_queue_priority)
672 cvmx_override_pko_queue_priority(ipd_port, priorities);
674 cvmx_pko_config_port(ipd_port,
675 cvmx_pko_get_base_queue_per_core(ipd_port,
677 cvmx_pko_get_num_queues(ipd_port),
685 * Setup global setting for PKO not related to a specific
686 * interface or port. This must be called before PKO is enabled.
688 * Returns Zero on success, negative on failure.
690 static int __cvmx_helper_global_setup_pko(void)
693 * Disable tagwait FAU timeout. This needs to be done before
694 * anyone might start packet output using tags.
696 union cvmx_iob_fau_timeout fau_to;
698 fau_to.s.tout_val = 0xfff;
699 fau_to.s.tout_enb = 0;
700 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
702 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
703 union cvmx_pko_reg_min_pkt min_pkt;
706 min_pkt.s.size1 = 59;
707 min_pkt.s.size2 = 59;
708 min_pkt.s.size3 = 59;
709 min_pkt.s.size4 = 59;
710 min_pkt.s.size5 = 59;
711 min_pkt.s.size6 = 59;
712 min_pkt.s.size7 = 59;
713 cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
720 * Setup global backpressure setting.
722 * Returns Zero on success, negative on failure
724 static int __cvmx_helper_global_setup_backpressure(void)
726 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
727 /* Disable backpressure if configured to do so */
728 /* Disable backpressure (pause frame) generation */
729 int num_interfaces = cvmx_helper_get_number_of_interfaces();
731 for (interface = 0; interface < num_interfaces; interface++) {
732 switch (cvmx_helper_interface_get_mode(interface)) {
733 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
734 case CVMX_HELPER_INTERFACE_MODE_PCIE:
735 case CVMX_HELPER_INTERFACE_MODE_NPI:
736 case CVMX_HELPER_INTERFACE_MODE_LOOP:
737 case CVMX_HELPER_INTERFACE_MODE_XAUI:
739 case CVMX_HELPER_INTERFACE_MODE_RGMII:
740 case CVMX_HELPER_INTERFACE_MODE_GMII:
741 case CVMX_HELPER_INTERFACE_MODE_SPI:
742 case CVMX_HELPER_INTERFACE_MODE_SGMII:
743 case CVMX_HELPER_INTERFACE_MODE_PICMG:
744 cvmx_gmx_set_backpressure_override(interface, 0xf);
754 * Enable packet input/output from the hardware. This function is
755 * called after all internal setup is complete and IPD is enabled.
756 * After this function completes, packets will be accepted from the
757 * hardware ports. PKO should still be disabled to make sure packets
758 * aren't sent out partially setup hardware.
760 * @interface: Interface to enable
762 * Returns Zero on success, negative on failure
764 static int __cvmx_helper_packet_hardware_enable(int interface)
767 switch (cvmx_helper_interface_get_mode(interface)) {
768 /* These types don't support ports to IPD/PKO */
769 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
770 case CVMX_HELPER_INTERFACE_MODE_PCIE:
773 /* XAUI is a single high speed port */
774 case CVMX_HELPER_INTERFACE_MODE_XAUI:
775 result = __cvmx_helper_xaui_enable(interface);
778 * RGMII/GMII/MII are all treated about the same. Most
779 * functions refer to these ports as RGMII
781 case CVMX_HELPER_INTERFACE_MODE_RGMII:
782 case CVMX_HELPER_INTERFACE_MODE_GMII:
783 result = __cvmx_helper_rgmii_enable(interface);
786 * SPI4 can have 1-16 ports depending on the device at
789 case CVMX_HELPER_INTERFACE_MODE_SPI:
790 result = __cvmx_helper_spi_enable(interface);
793 * SGMII can have 1-4 ports depending on how many are
796 case CVMX_HELPER_INTERFACE_MODE_SGMII:
797 case CVMX_HELPER_INTERFACE_MODE_PICMG:
798 result = __cvmx_helper_sgmii_enable(interface);
800 /* PCI target Network Packet Interface */
801 case CVMX_HELPER_INTERFACE_MODE_NPI:
802 result = __cvmx_helper_npi_enable(interface);
805 * Special loopback only ports. These are not the same
806 * as other ports in loopback mode
808 case CVMX_HELPER_INTERFACE_MODE_LOOP:
809 result = __cvmx_helper_loop_enable(interface);
812 result |= __cvmx_helper_board_hardware_enable(interface);
817 * Function to adjust internal IPD pointer alignments
819 * Returns 0 on success
822 int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
824 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
825 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
826 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
827 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
828 #define FIX_IPD_OUTPORT 0
829 /* Ports 0-15 are interface 0, 16-31 are interface 1 */
830 #define INTERFACE(port) (port >> 4)
831 #define INDEX(port) (port & 0xf)
833 cvmx_pko_command_word0_t pko_command;
834 union cvmx_buf_ptr g_buffer, pkt_buffer;
836 int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
837 union cvmx_gmxx_prtx_cfg gmx_cfg;
842 /* Save values for restore at end */
844 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
845 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
847 cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
849 cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
850 uint64_t rxx_jabber =
851 cvmx_read_csr(CVMX_GMXX_RXX_JABBER
852 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
854 cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
855 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
857 /* Configure port to gig FDX as required for loopback mode */
858 cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
861 * Disable reception on all ports so if traffic is present it
862 * will not interfere.
864 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
866 __delay(100000000ull);
868 for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
870 wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
871 pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
874 num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
882 FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
883 ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
884 (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
886 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
887 1 << INDEX(FIX_IPD_OUTPORT));
892 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
893 if (g_buffer.s.addr == 0) {
894 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
895 "buffer allocation failure.\n");
899 g_buffer.s.pool = CVMX_FPA_WQE_POOL;
900 g_buffer.s.size = num_segs;
904 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
905 if (pkt_buffer.s.addr == 0) {
906 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
907 "buffer allocation failure.\n");
911 pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
912 pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
914 p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
915 p64[0] = 0xffffffffffff0000ull;
916 p64[1] = 0x08004510ull;
917 p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
918 p64[3] = 0x3a5fc0a81073c0a8ull;
920 for (i = 0; i < num_segs; i++) {
923 FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
925 if (i == (num_segs - 1))
928 *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
929 8 * i) = pkt_buffer.u64;
932 /* Build the PKO command */
934 pko_command.s.segs = num_segs;
935 pko_command.s.total_bytes = size;
936 pko_command.s.dontfree = 0;
937 pko_command.s.gather = 1;
940 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
941 (INDEX(FIX_IPD_OUTPORT),
942 INTERFACE(FIX_IPD_OUTPORT)));
944 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
945 (INDEX(FIX_IPD_OUTPORT),
946 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
947 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
948 1 << INDEX(FIX_IPD_OUTPORT));
949 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
950 1 << INDEX(FIX_IPD_OUTPORT));
952 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
953 (INDEX(FIX_IPD_OUTPORT),
954 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
955 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
956 (INDEX(FIX_IPD_OUTPORT),
957 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
959 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
960 cvmx_pko_get_base_queue
962 CVMX_PKO_LOCK_CMD_QUEUE);
963 cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
964 cvmx_pko_get_base_queue
965 (FIX_IPD_OUTPORT), pko_command,
966 g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
971 work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
973 } while ((work == NULL) && (retry_cnt > 0));
976 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
977 "get_work() timeout occurred.\n");
981 cvmx_helper_free_packet_data(work);
986 /* Return CSR configs to saved values */
987 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
988 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
990 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
992 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
994 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
995 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
997 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
998 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
1000 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
1004 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
1011 * Called after all internal packet IO paths are setup. This
1012 * function enables IPD/PIP and begins packet input and output.
1014 * Returns Zero on success, negative on failure
1016 int cvmx_helper_ipd_and_packet_input_enable(void)
1025 * Time to enable hardware ports packet input and output. Note
1026 * that at this point IPD/PIP must be fully functional and PKO
1029 num_interfaces = cvmx_helper_get_number_of_interfaces();
1030 for (interface = 0; interface < num_interfaces; interface++) {
1031 if (cvmx_helper_ports_on_interface(interface) > 0)
1032 __cvmx_helper_packet_hardware_enable(interface);
1035 /* Finally enable PKO now that the entire path is up and running */
1038 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
1039 || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
1040 && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
1041 __cvmx_helper_errata_fix_ipd_ptr_alignment();
1044 EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
1047 * Initialize the PIP, IPD, and PKO hardware to support
1048 * simple priority based queues for the ethernet ports. Each
1049 * port is configured with a number of priority queues based
1050 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1051 * priority than the previous.
1053 * Returns Zero on success, non-zero on failure
1055 int cvmx_helper_initialize_packet_io_global(void)
1059 union cvmx_l2c_cfg l2c_cfg;
1060 union cvmx_smix_en smix_en;
1061 const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1064 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1067 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1068 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1071 * Tell L2 to give the IOB statically higher priority compared
1072 * to the cores. This avoids conditions where IO blocks might
1073 * be starved under very high L2 loads.
1075 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1076 l2c_cfg.s.lrf_arb_mode = 0;
1077 l2c_cfg.s.rfb_arb_mode = 0;
1078 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1080 /* Make sure SMI/MDIO is enabled so we can query PHYs */
1081 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
1082 if (!smix_en.s.en) {
1084 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
1087 /* Newer chips actually have two SMI/MDIO interfaces */
1088 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
1089 !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
1090 !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
1091 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
1092 if (!smix_en.s.en) {
1094 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
1098 cvmx_pko_initialize_global();
1099 for (interface = 0; interface < num_interfaces; interface++) {
1100 result |= cvmx_helper_interface_probe(interface);
1101 if (cvmx_helper_ports_on_interface(interface) > 0)
1102 cvmx_dprintf("Interface %d has %d ports (%s)\n",
1104 cvmx_helper_ports_on_interface(interface),
1105 cvmx_helper_interface_mode_to_string
1106 (cvmx_helper_interface_get_mode
1108 result |= __cvmx_helper_interface_setup_ipd(interface);
1109 result |= __cvmx_helper_interface_setup_pko(interface);
1112 result |= __cvmx_helper_global_setup_ipd();
1113 result |= __cvmx_helper_global_setup_pko();
1115 /* Enable any flow control and backpressure */
1116 result |= __cvmx_helper_global_setup_backpressure();
1118 #if CVMX_HELPER_ENABLE_IPD
1119 result |= cvmx_helper_ipd_and_packet_input_enable();
1123 EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1126 * Does core local initialization for packet io
1128 * Returns Zero on success, non-zero on failure
1130 int cvmx_helper_initialize_packet_io_local(void)
1132 return cvmx_pko_initialize_local();
1136 * Return the link state of an IPD/PKO port as returned by
1137 * auto negotiation. The result of this function may not match
1138 * Octeon's link config if auto negotiation has changed since
1139 * the last call to cvmx_helper_link_set().
1141 * @ipd_port: IPD/PKO port to query
1143 * Returns Link state
1145 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1147 cvmx_helper_link_info_t result;
1148 int interface = cvmx_helper_get_interface_num(ipd_port);
1149 int index = cvmx_helper_get_interface_index_num(ipd_port);
1151 /* The default result will be a down link unless the code below
1155 if (index >= cvmx_helper_ports_on_interface(interface))
1158 switch (cvmx_helper_interface_get_mode(interface)) {
1159 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1160 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1161 /* Network links are not supported */
1163 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1164 result = __cvmx_helper_xaui_link_get(ipd_port);
1166 case CVMX_HELPER_INTERFACE_MODE_GMII:
1168 result = __cvmx_helper_rgmii_link_get(ipd_port);
1170 result.s.full_duplex = 1;
1171 result.s.link_up = 1;
1172 result.s.speed = 1000;
1175 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1176 result = __cvmx_helper_rgmii_link_get(ipd_port);
1178 case CVMX_HELPER_INTERFACE_MODE_SPI:
1179 result = __cvmx_helper_spi_link_get(ipd_port);
1181 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1182 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1183 result = __cvmx_helper_sgmii_link_get(ipd_port);
1185 case CVMX_HELPER_INTERFACE_MODE_NPI:
1186 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1187 /* Network links are not supported */
1192 EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1195 * Configure an IPD/PKO port for the specified link state. This
1196 * function does not influence auto negotiation at the PHY level.
1197 * The passed link state must always match the link state returned
1198 * by cvmx_helper_link_get().
1200 * @ipd_port: IPD/PKO port to configure
1201 * @link_info: The new link state
1203 * Returns Zero on success, negative on failure
1205 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1208 int interface = cvmx_helper_get_interface_num(ipd_port);
1209 int index = cvmx_helper_get_interface_index_num(ipd_port);
1211 if (index >= cvmx_helper_ports_on_interface(interface))
1214 switch (cvmx_helper_interface_get_mode(interface)) {
1215 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1216 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1218 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1219 result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1222 * RGMII/GMII/MII are all treated about the same. Most
1223 * functions refer to these ports as RGMII.
1225 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1226 case CVMX_HELPER_INTERFACE_MODE_GMII:
1227 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1229 case CVMX_HELPER_INTERFACE_MODE_SPI:
1230 result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1232 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1233 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1234 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1236 case CVMX_HELPER_INTERFACE_MODE_NPI:
1237 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1242 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1245 * Configure a port for internal and/or external loopback. Internal loopback
1246 * causes packets sent by the port to be received by Octeon. External loopback
1247 * causes packets received from the wire to sent out again.
1249 * @ipd_port: IPD/PKO port to loopback.
1251 * Non zero if you want internal loopback
1253 * Non zero if you want external loopback
1255 * Returns Zero on success, negative on failure.
1257 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal,
1258 int enable_external)
1261 int interface = cvmx_helper_get_interface_num(ipd_port);
1262 int index = cvmx_helper_get_interface_index_num(ipd_port);
1264 if (index >= cvmx_helper_ports_on_interface(interface))
1267 switch (cvmx_helper_interface_get_mode(interface)) {
1268 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1269 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1270 case CVMX_HELPER_INTERFACE_MODE_SPI:
1271 case CVMX_HELPER_INTERFACE_MODE_NPI:
1272 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1274 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1276 __cvmx_helper_xaui_configure_loopback(ipd_port,
1280 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1281 case CVMX_HELPER_INTERFACE_MODE_GMII:
1283 __cvmx_helper_rgmii_configure_loopback(ipd_port,
1287 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1288 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1290 __cvmx_helper_sgmii_configure_loopback(ipd_port,