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>
49 /* Port count per interface */
50 static int interface_port_count[9];
53 * Return the number of interfaces the chip has. Each interface
54 * may have multiple ports. Most chips support two interfaces,
55 * but the CNX0XX and CNX1XX are exceptions. These only support
58 * Returns Number of interfaces on chip
60 int cvmx_helper_get_number_of_interfaces(void)
62 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
64 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
66 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
71 EXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
74 * Return the number of ports on an interface. Depending on the
75 * chip and configuration, this can be 1-16. A value of 0
76 * specifies that the interface doesn't exist or isn't usable.
78 * @interface: Interface to get the port count for
80 * Returns Number of ports on interface. Can be Zero.
82 int cvmx_helper_ports_on_interface(int interface)
84 return interface_port_count[interface];
86 EXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
90 * Return interface mode for CN68xx.
92 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
94 union cvmx_mio_qlmx_cfg qlm_cfg;
97 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
98 /* QLM is disabled when QLM SPD is 15. */
99 if (qlm_cfg.s.qlm_spd == 15)
100 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
102 if (qlm_cfg.s.qlm_cfg == 2)
103 return CVMX_HELPER_INTERFACE_MODE_SGMII;
104 else if (qlm_cfg.s.qlm_cfg == 3)
105 return CVMX_HELPER_INTERFACE_MODE_XAUI;
107 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
111 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
112 /* QLM is disabled when QLM SPD is 15. */
113 if (qlm_cfg.s.qlm_spd == 15)
114 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
116 if (qlm_cfg.s.qlm_cfg == 2)
117 return CVMX_HELPER_INTERFACE_MODE_SGMII;
118 else if (qlm_cfg.s.qlm_cfg == 3)
119 return CVMX_HELPER_INTERFACE_MODE_XAUI;
121 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
123 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
124 /* QLM is disabled when QLM SPD is 15. */
125 if (qlm_cfg.s.qlm_spd == 15) {
126 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
127 } else if (qlm_cfg.s.qlm_cfg != 0) {
128 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
129 if (qlm_cfg.s.qlm_cfg != 0)
130 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
132 return CVMX_HELPER_INTERFACE_MODE_NPI;
134 return CVMX_HELPER_INTERFACE_MODE_LOOP;
136 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
142 * Return interface mode for an Octeon II
144 static cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
146 union cvmx_gmxx_inf_mode mode;
148 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
149 return __cvmx_get_mode_cn68xx(interface);
152 return CVMX_HELPER_INTERFACE_MODE_NPI;
155 return CVMX_HELPER_INTERFACE_MODE_LOOP;
157 /* Only present in CN63XX & CN66XX Octeon model */
158 if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
159 (interface == 4 || interface == 5)) ||
160 (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
161 interface >= 4 && interface <= 7)) {
162 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
165 if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
166 union cvmx_mio_qlmx_cfg mio_qlm_cfg;
168 /* QLM2 is SGMII0 and QLM1 is SGMII1 */
170 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
171 else if (interface == 1)
172 mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
174 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
176 if (mio_qlm_cfg.s.qlm_spd == 15)
177 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
179 if (mio_qlm_cfg.s.qlm_cfg == 9)
180 return CVMX_HELPER_INTERFACE_MODE_SGMII;
181 else if (mio_qlm_cfg.s.qlm_cfg == 11)
182 return CVMX_HELPER_INTERFACE_MODE_XAUI;
184 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
185 } else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
186 union cvmx_mio_qlmx_cfg qlm_cfg;
188 if (interface == 0) {
189 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
190 if (qlm_cfg.s.qlm_cfg == 2)
191 return CVMX_HELPER_INTERFACE_MODE_SGMII;
192 else if (qlm_cfg.s.qlm_cfg == 3)
193 return CVMX_HELPER_INTERFACE_MODE_XAUI;
195 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
196 } else if (interface == 1) {
197 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
198 if (qlm_cfg.s.qlm_cfg == 2)
199 return CVMX_HELPER_INTERFACE_MODE_SGMII;
200 else if (qlm_cfg.s.qlm_cfg == 3)
201 return CVMX_HELPER_INTERFACE_MODE_XAUI;
203 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
205 } else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
206 if (interface == 0) {
207 union cvmx_mio_qlmx_cfg qlm_cfg;
208 qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
209 if (qlm_cfg.s.qlm_cfg == 2)
210 return CVMX_HELPER_INTERFACE_MODE_SGMII;
212 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
215 if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
216 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
218 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
220 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
221 switch (mode.cn61xx.mode) {
223 return CVMX_HELPER_INTERFACE_MODE_SGMII;
225 return CVMX_HELPER_INTERFACE_MODE_XAUI;
227 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
231 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
234 return CVMX_HELPER_INTERFACE_MODE_GMII;
236 return CVMX_HELPER_INTERFACE_MODE_RGMII;
242 * Return interface mode for CN7XXX.
244 static cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
246 union cvmx_gmxx_inf_mode mode;
248 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
253 switch (mode.cn68xx.mode) {
255 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
258 return CVMX_HELPER_INTERFACE_MODE_SGMII;
260 return CVMX_HELPER_INTERFACE_MODE_XAUI;
262 return CVMX_HELPER_INTERFACE_MODE_SGMII;
265 return CVMX_HELPER_INTERFACE_MODE_NPI;
267 return CVMX_HELPER_INTERFACE_MODE_LOOP;
269 /* TODO: Implement support for AGL (RGMII). */
270 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
272 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
277 * Get the operating mode of an interface. Depending on the Octeon
278 * chip and configuration, this function returns an enumeration
279 * of the type of packet I/O supported by an interface.
281 * @interface: Interface to probe
283 * Returns Mode of the interface. Unknown or unsupported interfaces return
286 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
288 union cvmx_gmxx_inf_mode mode;
291 interface >= cvmx_helper_get_number_of_interfaces())
292 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
297 if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
298 return __cvmx_get_mode_cn7xxx(interface);
303 if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
304 return __cvmx_get_mode_octeon2(interface);
307 * Octeon and Octeon Plus models
310 return CVMX_HELPER_INTERFACE_MODE_NPI;
312 if (interface == 3) {
313 if (OCTEON_IS_MODEL(OCTEON_CN56XX)
314 || OCTEON_IS_MODEL(OCTEON_CN52XX))
315 return CVMX_HELPER_INTERFACE_MODE_LOOP;
317 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
321 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5
322 && cvmx_sysinfo_get()->board_rev_major == 1) {
324 * Lie about interface type of CN3005 board. This
325 * board has a switch on port 1 like the other
326 * evaluation boards, but it is connected over RGMII
327 * instead of GMII. Report GMII mode so that the
328 * speed is forced to 1 Gbit full duplex. Other than
329 * some initial configuration (which does not use the
330 * output of this function) there is no difference in
331 * setup between GMII and RGMII modes.
333 return CVMX_HELPER_INTERFACE_MODE_GMII;
336 /* Interface 1 is always disabled on CN31XX and CN30XX */
338 && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
339 || OCTEON_IS_MODEL(OCTEON_CN50XX)
340 || OCTEON_IS_MODEL(OCTEON_CN52XX)))
341 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
343 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
345 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
346 switch (mode.cn52xx.mode) {
348 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
350 return CVMX_HELPER_INTERFACE_MODE_XAUI;
352 return CVMX_HELPER_INTERFACE_MODE_SGMII;
354 return CVMX_HELPER_INTERFACE_MODE_PICMG;
356 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
360 return CVMX_HELPER_INTERFACE_MODE_DISABLED;
363 if (OCTEON_IS_MODEL(OCTEON_CN38XX)
364 || OCTEON_IS_MODEL(OCTEON_CN58XX))
365 return CVMX_HELPER_INTERFACE_MODE_SPI;
367 return CVMX_HELPER_INTERFACE_MODE_GMII;
369 return CVMX_HELPER_INTERFACE_MODE_RGMII;
372 EXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
375 * Configure the IPD/PIP tagging and QoS options for a specific
376 * port. This function determines the POW work queue entry
377 * contents for a port. The setup performed here is controlled by
378 * the defines in executive-config.h.
380 * @ipd_port: Port to configure. This follows the IPD numbering, not the
381 * per interface numbering
383 * Returns Zero on success, negative on failure
385 static int __cvmx_helper_port_setup_ipd(int ipd_port)
387 union cvmx_pip_prt_cfgx port_config;
388 union cvmx_pip_prt_tagx tag_config;
390 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
391 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
393 /* Have each port go to a different POW queue */
394 port_config.s.qos = ipd_port & 0x7;
396 /* Process the headers and place the IP header in the work queue */
397 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
399 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
400 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
401 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
402 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
403 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
404 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
405 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
406 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
407 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
408 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
409 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
410 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
411 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
412 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
413 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
414 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
415 /* Put all packets in group 0. Other groups can be used by the app */
416 tag_config.s.grp = 0;
418 cvmx_pip_config_port(ipd_port, port_config, tag_config);
424 * This function sets the interface_port_count[interface] correctly,
425 * without modifying any hardware configuration. Hardware setup of
426 * the ports will be performed later.
428 * @interface: Interface to probe
430 * Returns Zero on success, negative on failure
432 int cvmx_helper_interface_enumerate(int interface)
434 switch (cvmx_helper_interface_get_mode(interface)) {
435 /* These types don't support ports to IPD/PKO */
436 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
437 case CVMX_HELPER_INTERFACE_MODE_PCIE:
438 interface_port_count[interface] = 0;
440 /* XAUI is a single high speed port */
441 case CVMX_HELPER_INTERFACE_MODE_XAUI:
442 interface_port_count[interface] =
443 __cvmx_helper_xaui_enumerate(interface);
446 * RGMII/GMII/MII are all treated about the same. Most
447 * functions refer to these ports as RGMII.
449 case CVMX_HELPER_INTERFACE_MODE_RGMII:
450 case CVMX_HELPER_INTERFACE_MODE_GMII:
451 interface_port_count[interface] =
452 __cvmx_helper_rgmii_enumerate(interface);
455 * SPI4 can have 1-16 ports depending on the device at
458 case CVMX_HELPER_INTERFACE_MODE_SPI:
459 interface_port_count[interface] =
460 __cvmx_helper_spi_enumerate(interface);
463 * SGMII can have 1-4 ports depending on how many are
466 case CVMX_HELPER_INTERFACE_MODE_SGMII:
467 case CVMX_HELPER_INTERFACE_MODE_PICMG:
468 interface_port_count[interface] =
469 __cvmx_helper_sgmii_enumerate(interface);
471 /* PCI target Network Packet Interface */
472 case CVMX_HELPER_INTERFACE_MODE_NPI:
473 interface_port_count[interface] =
474 __cvmx_helper_npi_enumerate(interface);
477 * Special loopback only ports. These are not the same
478 * as other ports in loopback mode.
480 case CVMX_HELPER_INTERFACE_MODE_LOOP:
481 interface_port_count[interface] =
482 __cvmx_helper_loop_enumerate(interface);
486 interface_port_count[interface] =
487 __cvmx_helper_board_interface_probe(interface,
491 /* Make sure all global variables propagate to other cores */
498 * This function probes an interface to determine the actual
499 * number of hardware ports connected to it. It doesn't setup the
500 * ports or enable them. The main goal here is to set the global
501 * interface_port_count[interface] correctly. Hardware setup of the
502 * ports will be performed later.
504 * @interface: Interface to probe
506 * Returns Zero on success, negative on failure
508 int cvmx_helper_interface_probe(int interface)
510 cvmx_helper_interface_enumerate(interface);
511 /* At this stage in the game we don't want packets to be moving yet.
512 The following probe calls should perform hardware setup
513 needed to determine port counts. Receive must still be disabled */
514 switch (cvmx_helper_interface_get_mode(interface)) {
515 /* These types don't support ports to IPD/PKO */
516 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
517 case CVMX_HELPER_INTERFACE_MODE_PCIE:
519 /* XAUI is a single high speed port */
520 case CVMX_HELPER_INTERFACE_MODE_XAUI:
521 __cvmx_helper_xaui_probe(interface);
524 * RGMII/GMII/MII are all treated about the same. Most
525 * functions refer to these ports as RGMII.
527 case CVMX_HELPER_INTERFACE_MODE_RGMII:
528 case CVMX_HELPER_INTERFACE_MODE_GMII:
529 __cvmx_helper_rgmii_probe(interface);
532 * SPI4 can have 1-16 ports depending on the device at
535 case CVMX_HELPER_INTERFACE_MODE_SPI:
536 __cvmx_helper_spi_probe(interface);
539 * SGMII can have 1-4 ports depending on how many are
542 case CVMX_HELPER_INTERFACE_MODE_SGMII:
543 case CVMX_HELPER_INTERFACE_MODE_PICMG:
544 __cvmx_helper_sgmii_probe(interface);
546 /* PCI target Network Packet Interface */
547 case CVMX_HELPER_INTERFACE_MODE_NPI:
548 __cvmx_helper_npi_probe(interface);
551 * Special loopback only ports. These are not the same
552 * as other ports in loopback mode.
554 case CVMX_HELPER_INTERFACE_MODE_LOOP:
555 __cvmx_helper_loop_probe(interface);
559 /* Make sure all global variables propagate to other cores */
566 * Setup the IPD/PIP for the ports on an interface. Packet
567 * classification and tagging are set for every port on the
568 * interface. The number of ports on the interface must already
571 * @interface: Interface to setup IPD/PIP for
573 * Returns Zero on success, negative on failure
575 static int __cvmx_helper_interface_setup_ipd(int interface)
577 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
578 int num_ports = interface_port_count[interface];
580 while (num_ports--) {
581 __cvmx_helper_port_setup_ipd(ipd_port);
588 * Setup global setting for IPD/PIP not related to a specific
589 * interface or port. This must be called before IPD is enabled.
591 * Returns Zero on success, negative on failure.
593 static int __cvmx_helper_global_setup_ipd(void)
595 /* Setup the global packet input options */
596 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
597 CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
598 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
599 /* The +8 is to account for the next ptr */
600 (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
601 /* The +8 is to account for the next ptr */
602 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
604 CVMX_IPD_OPC_MODE_STT,
605 CVMX_HELPER_ENABLE_BACK_PRESSURE);
610 * Setup the PKO for the ports on an interface. The number of
611 * queues per port and the priority of each PKO output queue
612 * is set here. PKO must be disabled when this function is called.
614 * @interface: Interface to setup PKO for
616 * Returns Zero on success, negative on failure
618 static int __cvmx_helper_interface_setup_pko(int interface)
621 * Each packet output queue has an associated priority. The
622 * higher the priority, the more often it can send a packet. A
623 * priority of 8 means it can send in all 8 rounds of
624 * contention. We're going to make each queue one less than
625 * the last. The vector of priorities has been extended to
626 * support CN5xxx CPUs, where up to 16 queues can be
627 * associated to a port. To keep backward compatibility we
628 * don't change the initial 8 priorities and replicate them in
629 * the second half. With per-core PKO queues (PKO lockless
630 * operation) all queues have the same priority.
632 uint64_t priorities[16] =
633 { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
636 * Setup the IPD/PIP and PKO for the ports discovered
637 * above. Here packet classification, tagging and output
638 * priorities are set.
640 int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
641 int num_ports = interface_port_count[interface];
642 while (num_ports--) {
643 cvmx_pko_config_port(ipd_port,
644 cvmx_pko_get_base_queue_per_core(ipd_port,
646 cvmx_pko_get_num_queues(ipd_port),
654 * Setup global setting for PKO not related to a specific
655 * interface or port. This must be called before PKO is enabled.
657 * Returns Zero on success, negative on failure.
659 static int __cvmx_helper_global_setup_pko(void)
662 * Disable tagwait FAU timeout. This needs to be done before
663 * anyone might start packet output using tags.
665 union cvmx_iob_fau_timeout fau_to;
667 fau_to.s.tout_val = 0xfff;
668 fau_to.s.tout_enb = 0;
669 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
671 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
672 union cvmx_pko_reg_min_pkt min_pkt;
675 min_pkt.s.size1 = 59;
676 min_pkt.s.size2 = 59;
677 min_pkt.s.size3 = 59;
678 min_pkt.s.size4 = 59;
679 min_pkt.s.size5 = 59;
680 min_pkt.s.size6 = 59;
681 min_pkt.s.size7 = 59;
682 cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
689 * Setup global backpressure setting.
691 * Returns Zero on success, negative on failure
693 static int __cvmx_helper_global_setup_backpressure(void)
695 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
696 /* Disable backpressure if configured to do so */
697 /* Disable backpressure (pause frame) generation */
698 int num_interfaces = cvmx_helper_get_number_of_interfaces();
700 for (interface = 0; interface < num_interfaces; interface++) {
701 switch (cvmx_helper_interface_get_mode(interface)) {
702 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
703 case CVMX_HELPER_INTERFACE_MODE_PCIE:
704 case CVMX_HELPER_INTERFACE_MODE_NPI:
705 case CVMX_HELPER_INTERFACE_MODE_LOOP:
706 case CVMX_HELPER_INTERFACE_MODE_XAUI:
708 case CVMX_HELPER_INTERFACE_MODE_RGMII:
709 case CVMX_HELPER_INTERFACE_MODE_GMII:
710 case CVMX_HELPER_INTERFACE_MODE_SPI:
711 case CVMX_HELPER_INTERFACE_MODE_SGMII:
712 case CVMX_HELPER_INTERFACE_MODE_PICMG:
713 cvmx_gmx_set_backpressure_override(interface, 0xf);
723 * Enable packet input/output from the hardware. This function is
724 * called after all internal setup is complete and IPD is enabled.
725 * After this function completes, packets will be accepted from the
726 * hardware ports. PKO should still be disabled to make sure packets
727 * aren't sent out partially setup hardware.
729 * @interface: Interface to enable
731 * Returns Zero on success, negative on failure
733 static int __cvmx_helper_packet_hardware_enable(int interface)
736 switch (cvmx_helper_interface_get_mode(interface)) {
737 /* These types don't support ports to IPD/PKO */
738 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
739 case CVMX_HELPER_INTERFACE_MODE_PCIE:
742 /* XAUI is a single high speed port */
743 case CVMX_HELPER_INTERFACE_MODE_XAUI:
744 result = __cvmx_helper_xaui_enable(interface);
747 * RGMII/GMII/MII are all treated about the same. Most
748 * functions refer to these ports as RGMII
750 case CVMX_HELPER_INTERFACE_MODE_RGMII:
751 case CVMX_HELPER_INTERFACE_MODE_GMII:
752 result = __cvmx_helper_rgmii_enable(interface);
755 * SPI4 can have 1-16 ports depending on the device at
758 case CVMX_HELPER_INTERFACE_MODE_SPI:
759 result = __cvmx_helper_spi_enable(interface);
762 * SGMII can have 1-4 ports depending on how many are
765 case CVMX_HELPER_INTERFACE_MODE_SGMII:
766 case CVMX_HELPER_INTERFACE_MODE_PICMG:
767 result = __cvmx_helper_sgmii_enable(interface);
769 /* PCI target Network Packet Interface */
770 case CVMX_HELPER_INTERFACE_MODE_NPI:
771 result = __cvmx_helper_npi_enable(interface);
774 * Special loopback only ports. These are not the same
775 * as other ports in loopback mode
777 case CVMX_HELPER_INTERFACE_MODE_LOOP:
778 result = __cvmx_helper_loop_enable(interface);
781 result |= __cvmx_helper_board_hardware_enable(interface);
786 * Function to adjust internal IPD pointer alignments
788 * Returns 0 on success
791 static int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
793 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
794 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
795 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
796 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
797 #define FIX_IPD_OUTPORT 0
798 /* Ports 0-15 are interface 0, 16-31 are interface 1 */
799 #define INTERFACE(port) (port >> 4)
800 #define INDEX(port) (port & 0xf)
802 cvmx_pko_command_word0_t pko_command;
803 union cvmx_buf_ptr g_buffer, pkt_buffer;
805 int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
806 union cvmx_gmxx_prtx_cfg gmx_cfg;
811 /* Save values for restore at end */
813 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
814 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
816 cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
818 cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
819 uint64_t rxx_jabber =
820 cvmx_read_csr(CVMX_GMXX_RXX_JABBER
821 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
823 cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
824 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
826 /* Configure port to gig FDX as required for loopback mode */
827 cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
830 * Disable reception on all ports so if traffic is present it
831 * will not interfere.
833 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
835 __delay(100000000ull);
837 for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
839 wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
840 pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
843 num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
851 FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
852 ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
853 (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
855 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
856 1 << INDEX(FIX_IPD_OUTPORT));
861 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
862 if (g_buffer.s.addr == 0) {
863 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
864 "buffer allocation failure.\n");
868 g_buffer.s.pool = CVMX_FPA_WQE_POOL;
869 g_buffer.s.size = num_segs;
873 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
874 if (pkt_buffer.s.addr == 0) {
875 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
876 "buffer allocation failure.\n");
880 pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
881 pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
883 p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
884 p64[0] = 0xffffffffffff0000ull;
885 p64[1] = 0x08004510ull;
886 p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
887 p64[3] = 0x3a5fc0a81073c0a8ull;
889 for (i = 0; i < num_segs; i++) {
892 FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
894 if (i == (num_segs - 1))
897 *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
898 8 * i) = pkt_buffer.u64;
901 /* Build the PKO command */
903 pko_command.s.segs = num_segs;
904 pko_command.s.total_bytes = size;
905 pko_command.s.dontfree = 0;
906 pko_command.s.gather = 1;
909 cvmx_read_csr(CVMX_GMXX_PRTX_CFG
910 (INDEX(FIX_IPD_OUTPORT),
911 INTERFACE(FIX_IPD_OUTPORT)));
913 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
914 (INDEX(FIX_IPD_OUTPORT),
915 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
916 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
917 1 << INDEX(FIX_IPD_OUTPORT));
918 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
919 1 << INDEX(FIX_IPD_OUTPORT));
921 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
922 (INDEX(FIX_IPD_OUTPORT),
923 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
924 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
925 (INDEX(FIX_IPD_OUTPORT),
926 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
928 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
929 cvmx_pko_get_base_queue
931 CVMX_PKO_LOCK_CMD_QUEUE);
932 cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
933 cvmx_pko_get_base_queue
934 (FIX_IPD_OUTPORT), pko_command,
935 g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
940 work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
942 } while ((work == NULL) && (retry_cnt > 0));
945 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
946 "get_work() timeout occurred.\n");
950 cvmx_helper_free_packet_data(work);
955 /* Return CSR configs to saved values */
956 cvmx_write_csr(CVMX_GMXX_PRTX_CFG
957 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
959 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
961 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
963 cvmx_write_csr(CVMX_GMXX_RXX_JABBER
964 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
966 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
967 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
969 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
973 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
980 * Called after all internal packet IO paths are setup. This
981 * function enables IPD/PIP and begins packet input and output.
983 * Returns Zero on success, negative on failure
985 int cvmx_helper_ipd_and_packet_input_enable(void)
994 * Time to enable hardware ports packet input and output. Note
995 * that at this point IPD/PIP must be fully functional and PKO
998 num_interfaces = cvmx_helper_get_number_of_interfaces();
999 for (interface = 0; interface < num_interfaces; interface++) {
1000 if (cvmx_helper_ports_on_interface(interface) > 0)
1001 __cvmx_helper_packet_hardware_enable(interface);
1004 /* Finally enable PKO now that the entire path is up and running */
1007 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
1008 || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
1009 && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
1010 __cvmx_helper_errata_fix_ipd_ptr_alignment();
1013 EXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
1016 * Initialize the PIP, IPD, and PKO hardware to support
1017 * simple priority based queues for the ethernet ports. Each
1018 * port is configured with a number of priority queues based
1019 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
1020 * priority than the previous.
1022 * Returns Zero on success, non-zero on failure
1024 int cvmx_helper_initialize_packet_io_global(void)
1028 union cvmx_l2c_cfg l2c_cfg;
1029 union cvmx_smix_en smix_en;
1030 const int num_interfaces = cvmx_helper_get_number_of_interfaces();
1033 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
1036 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
1037 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
1040 * Tell L2 to give the IOB statically higher priority compared
1041 * to the cores. This avoids conditions where IO blocks might
1042 * be starved under very high L2 loads.
1044 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
1045 l2c_cfg.s.lrf_arb_mode = 0;
1046 l2c_cfg.s.rfb_arb_mode = 0;
1047 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
1049 /* Make sure SMI/MDIO is enabled so we can query PHYs */
1050 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0));
1051 if (!smix_en.s.en) {
1053 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64);
1056 /* Newer chips actually have two SMI/MDIO interfaces */
1057 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) &&
1058 !OCTEON_IS_MODEL(OCTEON_CN58XX) &&
1059 !OCTEON_IS_MODEL(OCTEON_CN50XX)) {
1060 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1));
1061 if (!smix_en.s.en) {
1063 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64);
1067 cvmx_pko_initialize_global();
1068 for (interface = 0; interface < num_interfaces; interface++) {
1069 result |= cvmx_helper_interface_probe(interface);
1070 if (cvmx_helper_ports_on_interface(interface) > 0)
1071 cvmx_dprintf("Interface %d has %d ports (%s)\n",
1073 cvmx_helper_ports_on_interface(interface),
1074 cvmx_helper_interface_mode_to_string
1075 (cvmx_helper_interface_get_mode
1077 result |= __cvmx_helper_interface_setup_ipd(interface);
1078 result |= __cvmx_helper_interface_setup_pko(interface);
1081 result |= __cvmx_helper_global_setup_ipd();
1082 result |= __cvmx_helper_global_setup_pko();
1084 /* Enable any flow control and backpressure */
1085 result |= __cvmx_helper_global_setup_backpressure();
1087 #if CVMX_HELPER_ENABLE_IPD
1088 result |= cvmx_helper_ipd_and_packet_input_enable();
1092 EXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
1095 * Does core local initialization for packet io
1097 * Returns Zero on success, non-zero on failure
1099 int cvmx_helper_initialize_packet_io_local(void)
1101 return cvmx_pko_initialize_local();
1105 * Return the link state of an IPD/PKO port as returned by
1106 * auto negotiation. The result of this function may not match
1107 * Octeon's link config if auto negotiation has changed since
1108 * the last call to cvmx_helper_link_set().
1110 * @ipd_port: IPD/PKO port to query
1112 * Returns Link state
1114 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port)
1116 cvmx_helper_link_info_t result;
1117 int interface = cvmx_helper_get_interface_num(ipd_port);
1118 int index = cvmx_helper_get_interface_index_num(ipd_port);
1120 /* The default result will be a down link unless the code below
1124 if (index >= cvmx_helper_ports_on_interface(interface))
1127 switch (cvmx_helper_interface_get_mode(interface)) {
1128 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1129 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1130 /* Network links are not supported */
1132 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1133 result = __cvmx_helper_xaui_link_get(ipd_port);
1135 case CVMX_HELPER_INTERFACE_MODE_GMII:
1137 result = __cvmx_helper_rgmii_link_get(ipd_port);
1139 result.s.full_duplex = 1;
1140 result.s.link_up = 1;
1141 result.s.speed = 1000;
1144 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1145 result = __cvmx_helper_rgmii_link_get(ipd_port);
1147 case CVMX_HELPER_INTERFACE_MODE_SPI:
1148 result = __cvmx_helper_spi_link_get(ipd_port);
1150 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1151 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1152 result = __cvmx_helper_sgmii_link_get(ipd_port);
1154 case CVMX_HELPER_INTERFACE_MODE_NPI:
1155 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1156 /* Network links are not supported */
1161 EXPORT_SYMBOL_GPL(cvmx_helper_link_get);
1164 * Configure an IPD/PKO port for the specified link state. This
1165 * function does not influence auto negotiation at the PHY level.
1166 * The passed link state must always match the link state returned
1167 * by cvmx_helper_link_get().
1169 * @ipd_port: IPD/PKO port to configure
1170 * @link_info: The new link state
1172 * Returns Zero on success, negative on failure
1174 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info)
1177 int interface = cvmx_helper_get_interface_num(ipd_port);
1178 int index = cvmx_helper_get_interface_index_num(ipd_port);
1180 if (index >= cvmx_helper_ports_on_interface(interface))
1183 switch (cvmx_helper_interface_get_mode(interface)) {
1184 case CVMX_HELPER_INTERFACE_MODE_DISABLED:
1185 case CVMX_HELPER_INTERFACE_MODE_PCIE:
1187 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1188 result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
1191 * RGMII/GMII/MII are all treated about the same. Most
1192 * functions refer to these ports as RGMII.
1194 case CVMX_HELPER_INTERFACE_MODE_RGMII:
1195 case CVMX_HELPER_INTERFACE_MODE_GMII:
1196 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
1198 case CVMX_HELPER_INTERFACE_MODE_SPI:
1199 result = __cvmx_helper_spi_link_set(ipd_port, link_info);
1201 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1202 case CVMX_HELPER_INTERFACE_MODE_PICMG:
1203 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
1205 case CVMX_HELPER_INTERFACE_MODE_NPI:
1206 case CVMX_HELPER_INTERFACE_MODE_LOOP:
1211 EXPORT_SYMBOL_GPL(cvmx_helper_link_set);