162306a36Sopenharmony_ci/***********************license start***************
262306a36Sopenharmony_ci * Author: Cavium Networks
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Contact: support@caviumnetworks.com
562306a36Sopenharmony_ci * This file is part of the OCTEON SDK
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
1062306a36Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
1162306a36Sopenharmony_ci * published by the Free Software Foundation.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
1462306a36Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
1562306a36Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
1662306a36Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more
1762306a36Sopenharmony_ci * details.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * You should have received a copy of the GNU General Public License
2062306a36Sopenharmony_ci * along with this file; if not, write to the Free Software
2162306a36Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2262306a36Sopenharmony_ci * or visit http://www.gnu.org/licenses/.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * This file may also be available under a different license from Cavium.
2562306a36Sopenharmony_ci * Contact Cavium Networks for more information
2662306a36Sopenharmony_ci ***********************license end**************************************/
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci/*
2962306a36Sopenharmony_ci *
3062306a36Sopenharmony_ci * Helper functions for common, but complicated tasks.
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci */
3362306a36Sopenharmony_ci#include <linux/bug.h>
3462306a36Sopenharmony_ci#include <asm/octeon/octeon.h>
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#include <asm/octeon/cvmx-config.h>
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include <asm/octeon/cvmx-fpa.h>
3962306a36Sopenharmony_ci#include <asm/octeon/cvmx-pip.h>
4062306a36Sopenharmony_ci#include <asm/octeon/cvmx-pko.h>
4162306a36Sopenharmony_ci#include <asm/octeon/cvmx-ipd.h>
4262306a36Sopenharmony_ci#include <asm/octeon/cvmx-spi.h>
4362306a36Sopenharmony_ci#include <asm/octeon/cvmx-helper.h>
4462306a36Sopenharmony_ci#include <asm/octeon/cvmx-helper-board.h>
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#include <asm/octeon/cvmx-pip-defs.h>
4762306a36Sopenharmony_ci#include <asm/octeon/cvmx-asxx-defs.h>
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* Port count per interface */
5062306a36Sopenharmony_cistatic int interface_port_count[9];
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/**
5362306a36Sopenharmony_ci * Return the number of interfaces the chip has. Each interface
5462306a36Sopenharmony_ci * may have multiple ports. Most chips support two interfaces,
5562306a36Sopenharmony_ci * but the CNX0XX and CNX1XX are exceptions. These only support
5662306a36Sopenharmony_ci * one interface.
5762306a36Sopenharmony_ci *
5862306a36Sopenharmony_ci * Returns Number of interfaces on chip
5962306a36Sopenharmony_ci */
6062306a36Sopenharmony_ciint cvmx_helper_get_number_of_interfaces(void)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
6362306a36Sopenharmony_ci		return 9;
6462306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
6562306a36Sopenharmony_ci		if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0))
6662306a36Sopenharmony_ci			return 7;
6762306a36Sopenharmony_ci		else
6862306a36Sopenharmony_ci			return 8;
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
7162306a36Sopenharmony_ci		return 4;
7262306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
7362306a36Sopenharmony_ci		return 5;
7462306a36Sopenharmony_ci	else
7562306a36Sopenharmony_ci		return 3;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/**
8062306a36Sopenharmony_ci * Return the number of ports on an interface. Depending on the
8162306a36Sopenharmony_ci * chip and configuration, this can be 1-16. A value of 0
8262306a36Sopenharmony_ci * specifies that the interface doesn't exist or isn't usable.
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * @interface: Interface to get the port count for
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * Returns Number of ports on interface. Can be Zero.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ciint cvmx_helper_ports_on_interface(int interface)
8962306a36Sopenharmony_ci{
9062306a36Sopenharmony_ci	return interface_port_count[interface];
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci/**
9562306a36Sopenharmony_ci * @INTERNAL
9662306a36Sopenharmony_ci * Return interface mode for CN68xx.
9762306a36Sopenharmony_ci */
9862306a36Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	union cvmx_mio_qlmx_cfg qlm_cfg;
10162306a36Sopenharmony_ci	switch (interface) {
10262306a36Sopenharmony_ci	case 0:
10362306a36Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
10462306a36Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
10562306a36Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15)
10662306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci		if (qlm_cfg.s.qlm_cfg == 2)
10962306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
11062306a36Sopenharmony_ci		else if (qlm_cfg.s.qlm_cfg == 3)
11162306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
11262306a36Sopenharmony_ci		else
11362306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
11462306a36Sopenharmony_ci	case 2:
11562306a36Sopenharmony_ci	case 3:
11662306a36Sopenharmony_ci	case 4:
11762306a36Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
11862306a36Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
11962306a36Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15)
12062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci		if (qlm_cfg.s.qlm_cfg == 2)
12362306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
12462306a36Sopenharmony_ci		else if (qlm_cfg.s.qlm_cfg == 3)
12562306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
12662306a36Sopenharmony_ci		else
12762306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
12862306a36Sopenharmony_ci	case 7:
12962306a36Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
13062306a36Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
13162306a36Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15) {
13262306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
13362306a36Sopenharmony_ci		} else if (qlm_cfg.s.qlm_cfg != 0) {
13462306a36Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
13562306a36Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg != 0)
13662306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
13762306a36Sopenharmony_ci		}
13862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
13962306a36Sopenharmony_ci	case 8:
14062306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
14162306a36Sopenharmony_ci	default:
14262306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/**
14762306a36Sopenharmony_ci * @INTERNAL
14862306a36Sopenharmony_ci * Return interface mode for an Octeon II
14962306a36Sopenharmony_ci */
15062306a36Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
15562306a36Sopenharmony_ci		return __cvmx_get_mode_cn68xx(interface);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	if (interface == 2)
15862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	if (interface == 3)
16162306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	/* Only present in CN63XX & CN66XX Octeon model */
16462306a36Sopenharmony_ci	if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
16562306a36Sopenharmony_ci	     (interface == 4 || interface == 5)) ||
16662306a36Sopenharmony_ci	    (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
16762306a36Sopenharmony_ci	     interface >= 4 && interface <= 7)) {
16862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
16962306a36Sopenharmony_ci	}
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
17262306a36Sopenharmony_ci		union cvmx_mio_qlmx_cfg mio_qlm_cfg;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci		/* QLM2 is SGMII0 and QLM1 is SGMII1 */
17562306a36Sopenharmony_ci		if (interface == 0)
17662306a36Sopenharmony_ci			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
17762306a36Sopenharmony_ci		else if (interface == 1)
17862306a36Sopenharmony_ci			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
17962306a36Sopenharmony_ci		else
18062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci		if (mio_qlm_cfg.s.qlm_spd == 15)
18362306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci		if (mio_qlm_cfg.s.qlm_cfg == 9)
18662306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
18762306a36Sopenharmony_ci		else if (mio_qlm_cfg.s.qlm_cfg == 11)
18862306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
18962306a36Sopenharmony_ci		else
19062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
19162306a36Sopenharmony_ci	} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
19262306a36Sopenharmony_ci		union cvmx_mio_qlmx_cfg qlm_cfg;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci		if (interface == 0) {
19562306a36Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
19662306a36Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
19762306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
19862306a36Sopenharmony_ci			else if (qlm_cfg.s.qlm_cfg == 3)
19962306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_XAUI;
20062306a36Sopenharmony_ci			else
20162306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
20262306a36Sopenharmony_ci		} else if (interface == 1) {
20362306a36Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
20462306a36Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
20562306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
20662306a36Sopenharmony_ci			else if (qlm_cfg.s.qlm_cfg == 3)
20762306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_XAUI;
20862306a36Sopenharmony_ci			else
20962306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
21062306a36Sopenharmony_ci		}
21162306a36Sopenharmony_ci	} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
21262306a36Sopenharmony_ci		if (interface == 0) {
21362306a36Sopenharmony_ci			union cvmx_mio_qlmx_cfg qlm_cfg;
21462306a36Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
21562306a36Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
21662306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
21762306a36Sopenharmony_ci		}
21862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
22262306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
22762306a36Sopenharmony_ci		switch (mode.cn61xx.mode) {
22862306a36Sopenharmony_ci		case 0:
22962306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
23062306a36Sopenharmony_ci		case 1:
23162306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
23262306a36Sopenharmony_ci		default:
23362306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
23462306a36Sopenharmony_ci		}
23562306a36Sopenharmony_ci	} else {
23662306a36Sopenharmony_ci		if (!mode.s.en)
23762306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci		if (mode.s.type)
24062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_GMII;
24162306a36Sopenharmony_ci		else
24262306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_RGMII;
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci/**
24762306a36Sopenharmony_ci * @INTERNAL
24862306a36Sopenharmony_ci * Return interface mode for CN7XXX.
24962306a36Sopenharmony_ci */
25062306a36Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	switch (interface) {
25762306a36Sopenharmony_ci	case 0:
25862306a36Sopenharmony_ci	case 1:
25962306a36Sopenharmony_ci		switch (mode.cn68xx.mode) {
26062306a36Sopenharmony_ci		case 0:
26162306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
26262306a36Sopenharmony_ci		case 1:
26362306a36Sopenharmony_ci		case 2:
26462306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
26562306a36Sopenharmony_ci		case 3:
26662306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
26762306a36Sopenharmony_ci		default:
26862306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
26962306a36Sopenharmony_ci		}
27062306a36Sopenharmony_ci	case 2:
27162306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
27262306a36Sopenharmony_ci	case 3:
27362306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
27462306a36Sopenharmony_ci	case 4:
27562306a36Sopenharmony_ci		/* TODO: Implement support for AGL (RGMII). */
27662306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
27762306a36Sopenharmony_ci	default:
27862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
27962306a36Sopenharmony_ci	}
28062306a36Sopenharmony_ci}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci/**
28362306a36Sopenharmony_ci * Get the operating mode of an interface. Depending on the Octeon
28462306a36Sopenharmony_ci * chip and configuration, this function returns an enumeration
28562306a36Sopenharmony_ci * of the type of packet I/O supported by an interface.
28662306a36Sopenharmony_ci *
28762306a36Sopenharmony_ci * @interface: Interface to probe
28862306a36Sopenharmony_ci *
28962306a36Sopenharmony_ci * Returns Mode of the interface. Unknown or unsupported interfaces return
29062306a36Sopenharmony_ci *	   DISABLED.
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_cicvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	if (interface < 0 ||
29762306a36Sopenharmony_ci	    interface >= cvmx_helper_get_number_of_interfaces())
29862306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/*
30162306a36Sopenharmony_ci	 * OCTEON III models
30262306a36Sopenharmony_ci	 */
30362306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
30462306a36Sopenharmony_ci		return __cvmx_get_mode_cn7xxx(interface);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/*
30762306a36Sopenharmony_ci	 * Octeon II models
30862306a36Sopenharmony_ci	 */
30962306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
31062306a36Sopenharmony_ci		return __cvmx_get_mode_octeon2(interface);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/*
31362306a36Sopenharmony_ci	 * Octeon and Octeon Plus models
31462306a36Sopenharmony_ci	 */
31562306a36Sopenharmony_ci	if (interface == 2)
31662306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (interface == 3) {
31962306a36Sopenharmony_ci		if (OCTEON_IS_MODEL(OCTEON_CN56XX)
32062306a36Sopenharmony_ci		    || OCTEON_IS_MODEL(OCTEON_CN52XX))
32162306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_LOOP;
32262306a36Sopenharmony_ci		else
32362306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/* Interface 1 is always disabled on CN31XX and CN30XX */
32762306a36Sopenharmony_ci	if ((interface == 1)
32862306a36Sopenharmony_ci	    && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
32962306a36Sopenharmony_ci		|| OCTEON_IS_MODEL(OCTEON_CN50XX)
33062306a36Sopenharmony_ci		|| OCTEON_IS_MODEL(OCTEON_CN52XX)))
33162306a36Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
33662306a36Sopenharmony_ci		switch (mode.cn52xx.mode) {
33762306a36Sopenharmony_ci		case 0:
33862306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
33962306a36Sopenharmony_ci		case 1:
34062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
34162306a36Sopenharmony_ci		case 2:
34262306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
34362306a36Sopenharmony_ci		case 3:
34462306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_PICMG;
34562306a36Sopenharmony_ci		default:
34662306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
34762306a36Sopenharmony_ci		}
34862306a36Sopenharmony_ci	} else {
34962306a36Sopenharmony_ci		if (!mode.s.en)
35062306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci		if (mode.s.type) {
35362306a36Sopenharmony_ci			if (OCTEON_IS_MODEL(OCTEON_CN38XX)
35462306a36Sopenharmony_ci			    || OCTEON_IS_MODEL(OCTEON_CN58XX))
35562306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SPI;
35662306a36Sopenharmony_ci			else
35762306a36Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_GMII;
35862306a36Sopenharmony_ci		} else
35962306a36Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_RGMII;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci/**
36562306a36Sopenharmony_ci * Configure the IPD/PIP tagging and QoS options for a specific
36662306a36Sopenharmony_ci * port. This function determines the POW work queue entry
36762306a36Sopenharmony_ci * contents for a port. The setup performed here is controlled by
36862306a36Sopenharmony_ci * the defines in executive-config.h.
36962306a36Sopenharmony_ci *
37062306a36Sopenharmony_ci * @ipd_port: Port to configure. This follows the IPD numbering, not the
37162306a36Sopenharmony_ci *		   per interface numbering
37262306a36Sopenharmony_ci *
37362306a36Sopenharmony_ci * Returns Zero on success, negative on failure
37462306a36Sopenharmony_ci */
37562306a36Sopenharmony_cistatic int __cvmx_helper_port_setup_ipd(int ipd_port)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	union cvmx_pip_prt_cfgx port_config;
37862306a36Sopenharmony_ci	union cvmx_pip_prt_tagx tag_config;
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
38162306a36Sopenharmony_ci	tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	/* Have each port go to a different POW queue */
38462306a36Sopenharmony_ci	port_config.s.qos = ipd_port & 0x7;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	/* Process the headers and place the IP header in the work queue */
38762306a36Sopenharmony_ci	port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
39062306a36Sopenharmony_ci	tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
39162306a36Sopenharmony_ci	tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
39262306a36Sopenharmony_ci	tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
39362306a36Sopenharmony_ci	tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
39462306a36Sopenharmony_ci	tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
39562306a36Sopenharmony_ci	tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
39662306a36Sopenharmony_ci	tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
39762306a36Sopenharmony_ci	tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
39862306a36Sopenharmony_ci	tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
39962306a36Sopenharmony_ci	tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
40062306a36Sopenharmony_ci	tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
40162306a36Sopenharmony_ci	tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
40262306a36Sopenharmony_ci	tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
40362306a36Sopenharmony_ci	tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
40462306a36Sopenharmony_ci	tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
40562306a36Sopenharmony_ci	/* Put all packets in group 0. Other groups can be used by the app */
40662306a36Sopenharmony_ci	tag_config.s.grp = 0;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	cvmx_pip_config_port(ipd_port, port_config, tag_config);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	return 0;
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci/**
41462306a36Sopenharmony_ci * This function sets the interface_port_count[interface] correctly,
41562306a36Sopenharmony_ci * without modifying any hardware configuration.  Hardware setup of
41662306a36Sopenharmony_ci * the ports will be performed later.
41762306a36Sopenharmony_ci *
41862306a36Sopenharmony_ci * @interface: Interface to probe
41962306a36Sopenharmony_ci *
42062306a36Sopenharmony_ci * Returns Zero on success, negative on failure
42162306a36Sopenharmony_ci */
42262306a36Sopenharmony_ciint cvmx_helper_interface_enumerate(int interface)
42362306a36Sopenharmony_ci{
42462306a36Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
42562306a36Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
42662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
42762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
42862306a36Sopenharmony_ci		interface_port_count[interface] = 0;
42962306a36Sopenharmony_ci		break;
43062306a36Sopenharmony_ci		/* XAUI is a single high speed port */
43162306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
43262306a36Sopenharmony_ci		interface_port_count[interface] =
43362306a36Sopenharmony_ci		    __cvmx_helper_xaui_enumerate(interface);
43462306a36Sopenharmony_ci		break;
43562306a36Sopenharmony_ci		/*
43662306a36Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
43762306a36Sopenharmony_ci		 * functions refer to these ports as RGMII.
43862306a36Sopenharmony_ci		 */
43962306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
44062306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
44162306a36Sopenharmony_ci		interface_port_count[interface] =
44262306a36Sopenharmony_ci		    __cvmx_helper_rgmii_enumerate(interface);
44362306a36Sopenharmony_ci		break;
44462306a36Sopenharmony_ci		/*
44562306a36Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
44662306a36Sopenharmony_ci		 * the other end.
44762306a36Sopenharmony_ci		 */
44862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
44962306a36Sopenharmony_ci		interface_port_count[interface] =
45062306a36Sopenharmony_ci		    __cvmx_helper_spi_enumerate(interface);
45162306a36Sopenharmony_ci		break;
45262306a36Sopenharmony_ci		/*
45362306a36Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
45462306a36Sopenharmony_ci		 * hooked up.
45562306a36Sopenharmony_ci		 */
45662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
45762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
45862306a36Sopenharmony_ci		interface_port_count[interface] =
45962306a36Sopenharmony_ci		    __cvmx_helper_sgmii_enumerate(interface);
46062306a36Sopenharmony_ci		break;
46162306a36Sopenharmony_ci		/* PCI target Network Packet Interface */
46262306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
46362306a36Sopenharmony_ci		interface_port_count[interface] =
46462306a36Sopenharmony_ci		    __cvmx_helper_npi_enumerate(interface);
46562306a36Sopenharmony_ci		break;
46662306a36Sopenharmony_ci		/*
46762306a36Sopenharmony_ci		 * Special loopback only ports. These are not the same
46862306a36Sopenharmony_ci		 * as other ports in loopback mode.
46962306a36Sopenharmony_ci		 */
47062306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
47162306a36Sopenharmony_ci		interface_port_count[interface] =
47262306a36Sopenharmony_ci		    __cvmx_helper_loop_enumerate(interface);
47362306a36Sopenharmony_ci		break;
47462306a36Sopenharmony_ci	}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	interface_port_count[interface] =
47762306a36Sopenharmony_ci	    __cvmx_helper_board_interface_probe(interface,
47862306a36Sopenharmony_ci						interface_port_count
47962306a36Sopenharmony_ci						[interface]);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* Make sure all global variables propagate to other cores */
48262306a36Sopenharmony_ci	CVMX_SYNCWS;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	return 0;
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci/**
48862306a36Sopenharmony_ci * This function probes an interface to determine the actual
48962306a36Sopenharmony_ci * number of hardware ports connected to it. It doesn't setup the
49062306a36Sopenharmony_ci * ports or enable them. The main goal here is to set the global
49162306a36Sopenharmony_ci * interface_port_count[interface] correctly. Hardware setup of the
49262306a36Sopenharmony_ci * ports will be performed later.
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * @interface: Interface to probe
49562306a36Sopenharmony_ci *
49662306a36Sopenharmony_ci * Returns Zero on success, negative on failure
49762306a36Sopenharmony_ci */
49862306a36Sopenharmony_ciint cvmx_helper_interface_probe(int interface)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	cvmx_helper_interface_enumerate(interface);
50162306a36Sopenharmony_ci	/* At this stage in the game we don't want packets to be moving yet.
50262306a36Sopenharmony_ci	   The following probe calls should perform hardware setup
50362306a36Sopenharmony_ci	   needed to determine port counts. Receive must still be disabled */
50462306a36Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
50562306a36Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
50662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
50762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
50862306a36Sopenharmony_ci		break;
50962306a36Sopenharmony_ci		/* XAUI is a single high speed port */
51062306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
51162306a36Sopenharmony_ci		__cvmx_helper_xaui_probe(interface);
51262306a36Sopenharmony_ci		break;
51362306a36Sopenharmony_ci		/*
51462306a36Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
51562306a36Sopenharmony_ci		 * functions refer to these ports as RGMII.
51662306a36Sopenharmony_ci		 */
51762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
51862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
51962306a36Sopenharmony_ci		__cvmx_helper_rgmii_probe(interface);
52062306a36Sopenharmony_ci		break;
52162306a36Sopenharmony_ci		/*
52262306a36Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
52362306a36Sopenharmony_ci		 * the other end.
52462306a36Sopenharmony_ci		 */
52562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
52662306a36Sopenharmony_ci		__cvmx_helper_spi_probe(interface);
52762306a36Sopenharmony_ci		break;
52862306a36Sopenharmony_ci		/*
52962306a36Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
53062306a36Sopenharmony_ci		 * hooked up.
53162306a36Sopenharmony_ci		 */
53262306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
53362306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
53462306a36Sopenharmony_ci		__cvmx_helper_sgmii_probe(interface);
53562306a36Sopenharmony_ci		break;
53662306a36Sopenharmony_ci		/* PCI target Network Packet Interface */
53762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
53862306a36Sopenharmony_ci		__cvmx_helper_npi_probe(interface);
53962306a36Sopenharmony_ci		break;
54062306a36Sopenharmony_ci		/*
54162306a36Sopenharmony_ci		 * Special loopback only ports. These are not the same
54262306a36Sopenharmony_ci		 * as other ports in loopback mode.
54362306a36Sopenharmony_ci		 */
54462306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
54562306a36Sopenharmony_ci		__cvmx_helper_loop_probe(interface);
54662306a36Sopenharmony_ci		break;
54762306a36Sopenharmony_ci	}
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	/* Make sure all global variables propagate to other cores */
55062306a36Sopenharmony_ci	CVMX_SYNCWS;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	return 0;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci/**
55662306a36Sopenharmony_ci * Setup the IPD/PIP for the ports on an interface. Packet
55762306a36Sopenharmony_ci * classification and tagging are set for every port on the
55862306a36Sopenharmony_ci * interface. The number of ports on the interface must already
55962306a36Sopenharmony_ci * have been probed.
56062306a36Sopenharmony_ci *
56162306a36Sopenharmony_ci * @interface: Interface to setup IPD/PIP for
56262306a36Sopenharmony_ci *
56362306a36Sopenharmony_ci * Returns Zero on success, negative on failure
56462306a36Sopenharmony_ci */
56562306a36Sopenharmony_cistatic int __cvmx_helper_interface_setup_ipd(int interface)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
56862306a36Sopenharmony_ci	int num_ports = interface_port_count[interface];
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	while (num_ports--) {
57162306a36Sopenharmony_ci		__cvmx_helper_port_setup_ipd(ipd_port);
57262306a36Sopenharmony_ci		ipd_port++;
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci	return 0;
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci/**
57862306a36Sopenharmony_ci * Setup global setting for IPD/PIP not related to a specific
57962306a36Sopenharmony_ci * interface or port. This must be called before IPD is enabled.
58062306a36Sopenharmony_ci *
58162306a36Sopenharmony_ci * Returns Zero on success, negative on failure.
58262306a36Sopenharmony_ci */
58362306a36Sopenharmony_cistatic int __cvmx_helper_global_setup_ipd(void)
58462306a36Sopenharmony_ci{
58562306a36Sopenharmony_ci	/* Setup the global packet input options */
58662306a36Sopenharmony_ci	cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
58762306a36Sopenharmony_ci			CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
58862306a36Sopenharmony_ci			CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
58962306a36Sopenharmony_ci			/* The +8 is to account for the next ptr */
59062306a36Sopenharmony_ci			(CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
59162306a36Sopenharmony_ci			/* The +8 is to account for the next ptr */
59262306a36Sopenharmony_ci			(CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
59362306a36Sopenharmony_ci			CVMX_FPA_WQE_POOL,
59462306a36Sopenharmony_ci			CVMX_IPD_OPC_MODE_STT,
59562306a36Sopenharmony_ci			CVMX_HELPER_ENABLE_BACK_PRESSURE);
59662306a36Sopenharmony_ci	return 0;
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci/**
60062306a36Sopenharmony_ci * Setup the PKO for the ports on an interface. The number of
60162306a36Sopenharmony_ci * queues per port and the priority of each PKO output queue
60262306a36Sopenharmony_ci * is set here. PKO must be disabled when this function is called.
60362306a36Sopenharmony_ci *
60462306a36Sopenharmony_ci * @interface: Interface to setup PKO for
60562306a36Sopenharmony_ci *
60662306a36Sopenharmony_ci * Returns Zero on success, negative on failure
60762306a36Sopenharmony_ci */
60862306a36Sopenharmony_cistatic int __cvmx_helper_interface_setup_pko(int interface)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	/*
61162306a36Sopenharmony_ci	 * Each packet output queue has an associated priority. The
61262306a36Sopenharmony_ci	 * higher the priority, the more often it can send a packet. A
61362306a36Sopenharmony_ci	 * priority of 8 means it can send in all 8 rounds of
61462306a36Sopenharmony_ci	 * contention. We're going to make each queue one less than
61562306a36Sopenharmony_ci	 * the last.  The vector of priorities has been extended to
61662306a36Sopenharmony_ci	 * support CN5xxx CPUs, where up to 16 queues can be
61762306a36Sopenharmony_ci	 * associated to a port.  To keep backward compatibility we
61862306a36Sopenharmony_ci	 * don't change the initial 8 priorities and replicate them in
61962306a36Sopenharmony_ci	 * the second half.  With per-core PKO queues (PKO lockless
62062306a36Sopenharmony_ci	 * operation) all queues have the same priority.
62162306a36Sopenharmony_ci	 */
62262306a36Sopenharmony_ci	uint64_t priorities[16] =
62362306a36Sopenharmony_ci	    { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	/*
62662306a36Sopenharmony_ci	 * Setup the IPD/PIP and PKO for the ports discovered
62762306a36Sopenharmony_ci	 * above. Here packet classification, tagging and output
62862306a36Sopenharmony_ci	 * priorities are set.
62962306a36Sopenharmony_ci	 */
63062306a36Sopenharmony_ci	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
63162306a36Sopenharmony_ci	int num_ports = interface_port_count[interface];
63262306a36Sopenharmony_ci	while (num_ports--) {
63362306a36Sopenharmony_ci		cvmx_pko_config_port(ipd_port,
63462306a36Sopenharmony_ci				     cvmx_pko_get_base_queue_per_core(ipd_port,
63562306a36Sopenharmony_ci								      0),
63662306a36Sopenharmony_ci				     cvmx_pko_get_num_queues(ipd_port),
63762306a36Sopenharmony_ci				     priorities);
63862306a36Sopenharmony_ci		ipd_port++;
63962306a36Sopenharmony_ci	}
64062306a36Sopenharmony_ci	return 0;
64162306a36Sopenharmony_ci}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci/**
64462306a36Sopenharmony_ci * Setup global setting for PKO not related to a specific
64562306a36Sopenharmony_ci * interface or port. This must be called before PKO is enabled.
64662306a36Sopenharmony_ci *
64762306a36Sopenharmony_ci * Returns Zero on success, negative on failure.
64862306a36Sopenharmony_ci */
64962306a36Sopenharmony_cistatic int __cvmx_helper_global_setup_pko(void)
65062306a36Sopenharmony_ci{
65162306a36Sopenharmony_ci	/*
65262306a36Sopenharmony_ci	 * Disable tagwait FAU timeout. This needs to be done before
65362306a36Sopenharmony_ci	 * anyone might start packet output using tags.
65462306a36Sopenharmony_ci	 */
65562306a36Sopenharmony_ci	union cvmx_iob_fau_timeout fau_to;
65662306a36Sopenharmony_ci	fau_to.u64 = 0;
65762306a36Sopenharmony_ci	fau_to.s.tout_val = 0xfff;
65862306a36Sopenharmony_ci	fau_to.s.tout_enb = 0;
65962306a36Sopenharmony_ci	cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
66262306a36Sopenharmony_ci		union cvmx_pko_reg_min_pkt min_pkt;
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci		min_pkt.u64 = 0;
66562306a36Sopenharmony_ci		min_pkt.s.size1 = 59;
66662306a36Sopenharmony_ci		min_pkt.s.size2 = 59;
66762306a36Sopenharmony_ci		min_pkt.s.size3 = 59;
66862306a36Sopenharmony_ci		min_pkt.s.size4 = 59;
66962306a36Sopenharmony_ci		min_pkt.s.size5 = 59;
67062306a36Sopenharmony_ci		min_pkt.s.size6 = 59;
67162306a36Sopenharmony_ci		min_pkt.s.size7 = 59;
67262306a36Sopenharmony_ci		cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	return 0;
67662306a36Sopenharmony_ci}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci/**
67962306a36Sopenharmony_ci * Setup global backpressure setting.
68062306a36Sopenharmony_ci *
68162306a36Sopenharmony_ci * Returns Zero on success, negative on failure
68262306a36Sopenharmony_ci */
68362306a36Sopenharmony_cistatic int __cvmx_helper_global_setup_backpressure(void)
68462306a36Sopenharmony_ci{
68562306a36Sopenharmony_ci#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
68662306a36Sopenharmony_ci	/* Disable backpressure if configured to do so */
68762306a36Sopenharmony_ci	/* Disable backpressure (pause frame) generation */
68862306a36Sopenharmony_ci	int num_interfaces = cvmx_helper_get_number_of_interfaces();
68962306a36Sopenharmony_ci	int interface;
69062306a36Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
69162306a36Sopenharmony_ci		switch (cvmx_helper_interface_get_mode(interface)) {
69262306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_DISABLED:
69362306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_PCIE:
69462306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_NPI:
69562306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_LOOP:
69662306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_XAUI:
69762306a36Sopenharmony_ci			break;
69862306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_RGMII:
69962306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_GMII:
70062306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_SPI:
70162306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_SGMII:
70262306a36Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_PICMG:
70362306a36Sopenharmony_ci			cvmx_gmx_set_backpressure_override(interface, 0xf);
70462306a36Sopenharmony_ci			break;
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci	}
70762306a36Sopenharmony_ci#endif
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	return 0;
71062306a36Sopenharmony_ci}
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci/**
71362306a36Sopenharmony_ci * Enable packet input/output from the hardware. This function is
71462306a36Sopenharmony_ci * called after all internal setup is complete and IPD is enabled.
71562306a36Sopenharmony_ci * After this function completes, packets will be accepted from the
71662306a36Sopenharmony_ci * hardware ports. PKO should still be disabled to make sure packets
71762306a36Sopenharmony_ci * aren't sent out partially setup hardware.
71862306a36Sopenharmony_ci *
71962306a36Sopenharmony_ci * @interface: Interface to enable
72062306a36Sopenharmony_ci *
72162306a36Sopenharmony_ci * Returns Zero on success, negative on failure
72262306a36Sopenharmony_ci */
72362306a36Sopenharmony_cistatic int __cvmx_helper_packet_hardware_enable(int interface)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci	int result = 0;
72662306a36Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
72762306a36Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
72862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
72962306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
73062306a36Sopenharmony_ci		/* Nothing to do */
73162306a36Sopenharmony_ci		break;
73262306a36Sopenharmony_ci		/* XAUI is a single high speed port */
73362306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
73462306a36Sopenharmony_ci		result = __cvmx_helper_xaui_enable(interface);
73562306a36Sopenharmony_ci		break;
73662306a36Sopenharmony_ci		/*
73762306a36Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
73862306a36Sopenharmony_ci		 * functions refer to these ports as RGMII
73962306a36Sopenharmony_ci		 */
74062306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
74162306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
74262306a36Sopenharmony_ci		result = __cvmx_helper_rgmii_enable(interface);
74362306a36Sopenharmony_ci		break;
74462306a36Sopenharmony_ci		/*
74562306a36Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
74662306a36Sopenharmony_ci		 * the other end
74762306a36Sopenharmony_ci		 */
74862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
74962306a36Sopenharmony_ci		result = __cvmx_helper_spi_enable(interface);
75062306a36Sopenharmony_ci		break;
75162306a36Sopenharmony_ci		/*
75262306a36Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
75362306a36Sopenharmony_ci		 * hooked up
75462306a36Sopenharmony_ci		 */
75562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
75662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
75762306a36Sopenharmony_ci		result = __cvmx_helper_sgmii_enable(interface);
75862306a36Sopenharmony_ci		break;
75962306a36Sopenharmony_ci		/* PCI target Network Packet Interface */
76062306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
76162306a36Sopenharmony_ci		result = __cvmx_helper_npi_enable(interface);
76262306a36Sopenharmony_ci		break;
76362306a36Sopenharmony_ci		/*
76462306a36Sopenharmony_ci		 * Special loopback only ports. These are not the same
76562306a36Sopenharmony_ci		 * as other ports in loopback mode
76662306a36Sopenharmony_ci		 */
76762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
76862306a36Sopenharmony_ci		result = __cvmx_helper_loop_enable(interface);
76962306a36Sopenharmony_ci		break;
77062306a36Sopenharmony_ci	}
77162306a36Sopenharmony_ci	return result;
77262306a36Sopenharmony_ci}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci/**
77562306a36Sopenharmony_ci * Function to adjust internal IPD pointer alignments
77662306a36Sopenharmony_ci *
77762306a36Sopenharmony_ci * Returns 0 on success
77862306a36Sopenharmony_ci *	   !0 on failure
77962306a36Sopenharmony_ci */
78062306a36Sopenharmony_cistatic int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
78162306a36Sopenharmony_ci{
78262306a36Sopenharmony_ci#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
78362306a36Sopenharmony_ci     (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
78462306a36Sopenharmony_ci#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
78562306a36Sopenharmony_ci	(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
78662306a36Sopenharmony_ci#define FIX_IPD_OUTPORT 0
78762306a36Sopenharmony_ci	/* Ports 0-15 are interface 0, 16-31 are interface 1 */
78862306a36Sopenharmony_ci#define INTERFACE(port) (port >> 4)
78962306a36Sopenharmony_ci#define INDEX(port) (port & 0xf)
79062306a36Sopenharmony_ci	uint64_t *p64;
79162306a36Sopenharmony_ci	union cvmx_pko_command_word0 pko_command;
79262306a36Sopenharmony_ci	union cvmx_buf_ptr g_buffer, pkt_buffer;
79362306a36Sopenharmony_ci	struct cvmx_wqe *work;
79462306a36Sopenharmony_ci	int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
79562306a36Sopenharmony_ci	union cvmx_gmxx_prtx_cfg gmx_cfg;
79662306a36Sopenharmony_ci	int retry_cnt;
79762306a36Sopenharmony_ci	int retry_loop_cnt;
79862306a36Sopenharmony_ci	int i;
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	/* Save values for restore at end */
80162306a36Sopenharmony_ci	uint64_t prtx_cfg =
80262306a36Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
80362306a36Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
80462306a36Sopenharmony_ci	uint64_t tx_ptr_en =
80562306a36Sopenharmony_ci	    cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
80662306a36Sopenharmony_ci	uint64_t rx_ptr_en =
80762306a36Sopenharmony_ci	    cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
80862306a36Sopenharmony_ci	uint64_t rxx_jabber =
80962306a36Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_RXX_JABBER
81062306a36Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
81162306a36Sopenharmony_ci	uint64_t frame_max =
81262306a36Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
81362306a36Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_ci	/* Configure port to gig FDX as required for loopback mode */
81662306a36Sopenharmony_ci	cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci	/*
81962306a36Sopenharmony_ci	 * Disable reception on all ports so if traffic is present it
82062306a36Sopenharmony_ci	 * will not interfere.
82162306a36Sopenharmony_ci	 */
82262306a36Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	__delay(100000000ull);
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
82762306a36Sopenharmony_ci		retry_cnt = 100000;
82862306a36Sopenharmony_ci		wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
82962306a36Sopenharmony_ci		pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
83062306a36Sopenharmony_ci		wqe_pcnt &= 0x7f;
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci		if (num_segs == 0)
83562306a36Sopenharmony_ci			goto fix_ipd_exit;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci		num_segs += 1;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci		size =
84062306a36Sopenharmony_ci		    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
84162306a36Sopenharmony_ci		    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
84262306a36Sopenharmony_ci		    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
84562306a36Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
84662306a36Sopenharmony_ci		CVMX_SYNC;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci		g_buffer.u64 = 0;
84962306a36Sopenharmony_ci		g_buffer.s.addr =
85062306a36Sopenharmony_ci		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
85162306a36Sopenharmony_ci		if (g_buffer.s.addr == 0) {
85262306a36Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
85362306a36Sopenharmony_ci				     "buffer allocation failure.\n");
85462306a36Sopenharmony_ci			goto fix_ipd_exit;
85562306a36Sopenharmony_ci		}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci		g_buffer.s.pool = CVMX_FPA_WQE_POOL;
85862306a36Sopenharmony_ci		g_buffer.s.size = num_segs;
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci		pkt_buffer.u64 = 0;
86162306a36Sopenharmony_ci		pkt_buffer.s.addr =
86262306a36Sopenharmony_ci		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
86362306a36Sopenharmony_ci		if (pkt_buffer.s.addr == 0) {
86462306a36Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
86562306a36Sopenharmony_ci				     "buffer allocation failure.\n");
86662306a36Sopenharmony_ci			goto fix_ipd_exit;
86762306a36Sopenharmony_ci		}
86862306a36Sopenharmony_ci		pkt_buffer.s.i = 1;
86962306a36Sopenharmony_ci		pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
87062306a36Sopenharmony_ci		pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci		p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
87362306a36Sopenharmony_ci		p64[0] = 0xffffffffffff0000ull;
87462306a36Sopenharmony_ci		p64[1] = 0x08004510ull;
87562306a36Sopenharmony_ci		p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
87662306a36Sopenharmony_ci		p64[3] = 0x3a5fc0a81073c0a8ull;
87762306a36Sopenharmony_ci
87862306a36Sopenharmony_ci		for (i = 0; i < num_segs; i++) {
87962306a36Sopenharmony_ci			if (i > 0)
88062306a36Sopenharmony_ci				pkt_buffer.s.size =
88162306a36Sopenharmony_ci				    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci			if (i == (num_segs - 1))
88462306a36Sopenharmony_ci				pkt_buffer.s.i = 0;
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci			*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
88762306a36Sopenharmony_ci						       8 * i) = pkt_buffer.u64;
88862306a36Sopenharmony_ci		}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci		/* Build the PKO command */
89162306a36Sopenharmony_ci		pko_command.u64 = 0;
89262306a36Sopenharmony_ci		pko_command.s.segs = num_segs;
89362306a36Sopenharmony_ci		pko_command.s.total_bytes = size;
89462306a36Sopenharmony_ci		pko_command.s.dontfree = 0;
89562306a36Sopenharmony_ci		pko_command.s.gather = 1;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci		gmx_cfg.u64 =
89862306a36Sopenharmony_ci		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
89962306a36Sopenharmony_ci				  (INDEX(FIX_IPD_OUTPORT),
90062306a36Sopenharmony_ci				   INTERFACE(FIX_IPD_OUTPORT)));
90162306a36Sopenharmony_ci		gmx_cfg.s.en = 1;
90262306a36Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_PRTX_CFG
90362306a36Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
90462306a36Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
90562306a36Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
90662306a36Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
90762306a36Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
90862306a36Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
90962306a36Sopenharmony_ci
91062306a36Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_RXX_JABBER
91162306a36Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
91262306a36Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
91362306a36Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
91462306a36Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
91562306a36Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci		cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
91862306a36Sopenharmony_ci					     cvmx_pko_get_base_queue
91962306a36Sopenharmony_ci					     (FIX_IPD_OUTPORT),
92062306a36Sopenharmony_ci					     CVMX_PKO_LOCK_CMD_QUEUE);
92162306a36Sopenharmony_ci		cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
92262306a36Sopenharmony_ci					    cvmx_pko_get_base_queue
92362306a36Sopenharmony_ci					    (FIX_IPD_OUTPORT), pko_command,
92462306a36Sopenharmony_ci					    g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci		CVMX_SYNC;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci		do {
92962306a36Sopenharmony_ci			work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
93062306a36Sopenharmony_ci			retry_cnt--;
93162306a36Sopenharmony_ci		} while ((work == NULL) && (retry_cnt > 0));
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci		if (!retry_cnt)
93462306a36Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
93562306a36Sopenharmony_ci				     "get_work() timeout occurred.\n");
93662306a36Sopenharmony_ci
93762306a36Sopenharmony_ci		/* Free packet */
93862306a36Sopenharmony_ci		if (work)
93962306a36Sopenharmony_ci			cvmx_helper_free_packet_data(work);
94062306a36Sopenharmony_ci	}
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_cifix_ipd_exit:
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci	/* Return CSR configs to saved values */
94562306a36Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_PRTX_CFG
94662306a36Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
94762306a36Sopenharmony_ci		       prtx_cfg);
94862306a36Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
94962306a36Sopenharmony_ci		       tx_ptr_en);
95062306a36Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
95162306a36Sopenharmony_ci		       rx_ptr_en);
95262306a36Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_RXX_JABBER
95362306a36Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
95462306a36Sopenharmony_ci		       rxx_jabber);
95562306a36Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
95662306a36Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
95762306a36Sopenharmony_ci		       frame_max);
95862306a36Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	CVMX_SYNC;
96162306a36Sopenharmony_ci	if (num_segs)
96262306a36Sopenharmony_ci		cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	return !!num_segs;
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci/**
96962306a36Sopenharmony_ci * Called after all internal packet IO paths are setup. This
97062306a36Sopenharmony_ci * function enables IPD/PIP and begins packet input and output.
97162306a36Sopenharmony_ci *
97262306a36Sopenharmony_ci * Returns Zero on success, negative on failure
97362306a36Sopenharmony_ci */
97462306a36Sopenharmony_ciint cvmx_helper_ipd_and_packet_input_enable(void)
97562306a36Sopenharmony_ci{
97662306a36Sopenharmony_ci	int num_interfaces;
97762306a36Sopenharmony_ci	int interface;
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci	/* Enable IPD */
98062306a36Sopenharmony_ci	cvmx_ipd_enable();
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/*
98362306a36Sopenharmony_ci	 * Time to enable hardware ports packet input and output. Note
98462306a36Sopenharmony_ci	 * that at this point IPD/PIP must be fully functional and PKO
98562306a36Sopenharmony_ci	 * must be disabled
98662306a36Sopenharmony_ci	 */
98762306a36Sopenharmony_ci	num_interfaces = cvmx_helper_get_number_of_interfaces();
98862306a36Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
98962306a36Sopenharmony_ci		if (cvmx_helper_ports_on_interface(interface) > 0)
99062306a36Sopenharmony_ci			__cvmx_helper_packet_hardware_enable(interface);
99162306a36Sopenharmony_ci	}
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	/* Finally enable PKO now that the entire path is up and running */
99462306a36Sopenharmony_ci	cvmx_pko_enable();
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
99762306a36Sopenharmony_ci	     || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
99862306a36Sopenharmony_ci	    && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
99962306a36Sopenharmony_ci		__cvmx_helper_errata_fix_ipd_ptr_alignment();
100062306a36Sopenharmony_ci	return 0;
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci/**
100562306a36Sopenharmony_ci * Initialize the PIP, IPD, and PKO hardware to support
100662306a36Sopenharmony_ci * simple priority based queues for the ethernet ports. Each
100762306a36Sopenharmony_ci * port is configured with a number of priority queues based
100862306a36Sopenharmony_ci * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
100962306a36Sopenharmony_ci * priority than the previous.
101062306a36Sopenharmony_ci *
101162306a36Sopenharmony_ci * Returns Zero on success, non-zero on failure
101262306a36Sopenharmony_ci */
101362306a36Sopenharmony_ciint cvmx_helper_initialize_packet_io_global(void)
101462306a36Sopenharmony_ci{
101562306a36Sopenharmony_ci	int result = 0;
101662306a36Sopenharmony_ci	int interface;
101762306a36Sopenharmony_ci	union cvmx_l2c_cfg l2c_cfg;
101862306a36Sopenharmony_ci	const int num_interfaces = cvmx_helper_get_number_of_interfaces();
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	/*
102162306a36Sopenharmony_ci	 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
102262306a36Sopenharmony_ci	 * be disabled.
102362306a36Sopenharmony_ci	 */
102462306a36Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
102562306a36Sopenharmony_ci		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci	/*
102862306a36Sopenharmony_ci	 * Tell L2 to give the IOB statically higher priority compared
102962306a36Sopenharmony_ci	 * to the cores. This avoids conditions where IO blocks might
103062306a36Sopenharmony_ci	 * be starved under very high L2 loads.
103162306a36Sopenharmony_ci	 */
103262306a36Sopenharmony_ci	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
103362306a36Sopenharmony_ci	l2c_cfg.s.lrf_arb_mode = 0;
103462306a36Sopenharmony_ci	l2c_cfg.s.rfb_arb_mode = 0;
103562306a36Sopenharmony_ci	cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	cvmx_pko_initialize_global();
103862306a36Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
103962306a36Sopenharmony_ci		result |= cvmx_helper_interface_probe(interface);
104062306a36Sopenharmony_ci		if (cvmx_helper_ports_on_interface(interface) > 0)
104162306a36Sopenharmony_ci			cvmx_dprintf("Interface %d has %d ports (%s)\n",
104262306a36Sopenharmony_ci				     interface,
104362306a36Sopenharmony_ci				     cvmx_helper_ports_on_interface(interface),
104462306a36Sopenharmony_ci				     cvmx_helper_interface_mode_to_string
104562306a36Sopenharmony_ci				     (cvmx_helper_interface_get_mode
104662306a36Sopenharmony_ci				      (interface)));
104762306a36Sopenharmony_ci		result |= __cvmx_helper_interface_setup_ipd(interface);
104862306a36Sopenharmony_ci		result |= __cvmx_helper_interface_setup_pko(interface);
104962306a36Sopenharmony_ci	}
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci	result |= __cvmx_helper_global_setup_ipd();
105262306a36Sopenharmony_ci	result |= __cvmx_helper_global_setup_pko();
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	/* Enable any flow control and backpressure */
105562306a36Sopenharmony_ci	result |= __cvmx_helper_global_setup_backpressure();
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci#if CVMX_HELPER_ENABLE_IPD
105862306a36Sopenharmony_ci	result |= cvmx_helper_ipd_and_packet_input_enable();
105962306a36Sopenharmony_ci#endif
106062306a36Sopenharmony_ci	return result;
106162306a36Sopenharmony_ci}
106262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci/**
106562306a36Sopenharmony_ci * Return the link state of an IPD/PKO port as returned by
106662306a36Sopenharmony_ci * auto negotiation. The result of this function may not match
106762306a36Sopenharmony_ci * Octeon's link config if auto negotiation has changed since
106862306a36Sopenharmony_ci * the last call to cvmx_helper_link_set().
106962306a36Sopenharmony_ci *
107062306a36Sopenharmony_ci * @ipd_port: IPD/PKO port to query
107162306a36Sopenharmony_ci *
107262306a36Sopenharmony_ci * Returns Link state
107362306a36Sopenharmony_ci */
107462306a36Sopenharmony_ciunion cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	union cvmx_helper_link_info result;
107762306a36Sopenharmony_ci	int interface = cvmx_helper_get_interface_num(ipd_port);
107862306a36Sopenharmony_ci	int index = cvmx_helper_get_interface_index_num(ipd_port);
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	/* The default result will be a down link unless the code below
108162306a36Sopenharmony_ci	   changes it */
108262306a36Sopenharmony_ci	result.u64 = 0;
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	if (index >= cvmx_helper_ports_on_interface(interface))
108562306a36Sopenharmony_ci		return result;
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
108862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
108962306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
109062306a36Sopenharmony_ci		/* Network links are not supported */
109162306a36Sopenharmony_ci		break;
109262306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
109362306a36Sopenharmony_ci		result = __cvmx_helper_xaui_link_get(ipd_port);
109462306a36Sopenharmony_ci		break;
109562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
109662306a36Sopenharmony_ci		if (index == 0)
109762306a36Sopenharmony_ci			result = __cvmx_helper_rgmii_link_get(ipd_port);
109862306a36Sopenharmony_ci		else {
109962306a36Sopenharmony_ci			WARN_ONCE(1, "Using deprecated link status - please update your DT");
110062306a36Sopenharmony_ci			result.s.full_duplex = 1;
110162306a36Sopenharmony_ci			result.s.link_up = 1;
110262306a36Sopenharmony_ci			result.s.speed = 1000;
110362306a36Sopenharmony_ci		}
110462306a36Sopenharmony_ci		break;
110562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
110662306a36Sopenharmony_ci		result = __cvmx_helper_rgmii_link_get(ipd_port);
110762306a36Sopenharmony_ci		break;
110862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
110962306a36Sopenharmony_ci		result = __cvmx_helper_spi_link_get(ipd_port);
111062306a36Sopenharmony_ci		break;
111162306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
111262306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
111362306a36Sopenharmony_ci		result = __cvmx_helper_sgmii_link_get(ipd_port);
111462306a36Sopenharmony_ci		break;
111562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
111662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
111762306a36Sopenharmony_ci		/* Network links are not supported */
111862306a36Sopenharmony_ci		break;
111962306a36Sopenharmony_ci	}
112062306a36Sopenharmony_ci	return result;
112162306a36Sopenharmony_ci}
112262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_link_get);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci/**
112562306a36Sopenharmony_ci * Configure an IPD/PKO port for the specified link state. This
112662306a36Sopenharmony_ci * function does not influence auto negotiation at the PHY level.
112762306a36Sopenharmony_ci * The passed link state must always match the link state returned
112862306a36Sopenharmony_ci * by cvmx_helper_link_get().
112962306a36Sopenharmony_ci *
113062306a36Sopenharmony_ci * @ipd_port:  IPD/PKO port to configure
113162306a36Sopenharmony_ci * @link_info: The new link state
113262306a36Sopenharmony_ci *
113362306a36Sopenharmony_ci * Returns Zero on success, negative on failure
113462306a36Sopenharmony_ci */
113562306a36Sopenharmony_ciint cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)
113662306a36Sopenharmony_ci{
113762306a36Sopenharmony_ci	int result = -1;
113862306a36Sopenharmony_ci	int interface = cvmx_helper_get_interface_num(ipd_port);
113962306a36Sopenharmony_ci	int index = cvmx_helper_get_interface_index_num(ipd_port);
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	if (index >= cvmx_helper_ports_on_interface(interface))
114262306a36Sopenharmony_ci		return -1;
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
114562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
114662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
114762306a36Sopenharmony_ci		break;
114862306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
114962306a36Sopenharmony_ci		result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
115062306a36Sopenharmony_ci		break;
115162306a36Sopenharmony_ci		/*
115262306a36Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
115362306a36Sopenharmony_ci		 * functions refer to these ports as RGMII.
115462306a36Sopenharmony_ci		 */
115562306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
115662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
115762306a36Sopenharmony_ci		result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
115862306a36Sopenharmony_ci		break;
115962306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
116062306a36Sopenharmony_ci		result = __cvmx_helper_spi_link_set(ipd_port, link_info);
116162306a36Sopenharmony_ci		break;
116262306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
116362306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
116462306a36Sopenharmony_ci		result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
116562306a36Sopenharmony_ci		break;
116662306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
116762306a36Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
116862306a36Sopenharmony_ci		break;
116962306a36Sopenharmony_ci	}
117062306a36Sopenharmony_ci	return result;
117162306a36Sopenharmony_ci}
117262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1173