18c2ecf20Sopenharmony_ci/***********************license start***************
28c2ecf20Sopenharmony_ci * Author: Cavium Networks
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Contact: support@caviumnetworks.com
58c2ecf20Sopenharmony_ci * This file is part of the OCTEON SDK
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2003-2008 Cavium Networks
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * This file is free software; you can redistribute it and/or modify
108c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License, Version 2, as
118c2ecf20Sopenharmony_ci * published by the Free Software Foundation.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
148c2ecf20Sopenharmony_ci * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
158c2ecf20Sopenharmony_ci * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
168c2ecf20Sopenharmony_ci * NONINFRINGEMENT.  See the GNU General Public License for more
178c2ecf20Sopenharmony_ci * details.
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License
208c2ecf20Sopenharmony_ci * along with this file; if not, write to the Free Software
218c2ecf20Sopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
228c2ecf20Sopenharmony_ci * or visit http://www.gnu.org/licenses/.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * This file may also be available under a different license from Cavium.
258c2ecf20Sopenharmony_ci * Contact Cavium Networks for more information
268c2ecf20Sopenharmony_ci ***********************license end**************************************/
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci/*
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * Helper functions for common, but complicated tasks.
318c2ecf20Sopenharmony_ci *
328c2ecf20Sopenharmony_ci */
338c2ecf20Sopenharmony_ci#include <linux/bug.h>
348c2ecf20Sopenharmony_ci#include <asm/octeon/octeon.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-config.h>
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-fpa.h>
398c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pip.h>
408c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pko.h>
418c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-ipd.h>
428c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-spi.h>
438c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-helper.h>
448c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-helper-board.h>
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-pip-defs.h>
478c2ecf20Sopenharmony_ci#include <asm/octeon/cvmx-asxx-defs.h>
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* Port count per interface */
508c2ecf20Sopenharmony_cistatic int interface_port_count[9];
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/**
538c2ecf20Sopenharmony_ci * Return the number of interfaces the chip has. Each interface
548c2ecf20Sopenharmony_ci * may have multiple ports. Most chips support two interfaces,
558c2ecf20Sopenharmony_ci * but the CNX0XX and CNX1XX are exceptions. These only support
568c2ecf20Sopenharmony_ci * one interface.
578c2ecf20Sopenharmony_ci *
588c2ecf20Sopenharmony_ci * Returns Number of interfaces on chip
598c2ecf20Sopenharmony_ci */
608c2ecf20Sopenharmony_ciint cvmx_helper_get_number_of_interfaces(void)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
638c2ecf20Sopenharmony_ci		return 9;
648c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
658c2ecf20Sopenharmony_ci		return 4;
668c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
678c2ecf20Sopenharmony_ci		return 5;
688c2ecf20Sopenharmony_ci	else
698c2ecf20Sopenharmony_ci		return 3;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_get_number_of_interfaces);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/**
748c2ecf20Sopenharmony_ci * Return the number of ports on an interface. Depending on the
758c2ecf20Sopenharmony_ci * chip and configuration, this can be 1-16. A value of 0
768c2ecf20Sopenharmony_ci * specifies that the interface doesn't exist or isn't usable.
778c2ecf20Sopenharmony_ci *
788c2ecf20Sopenharmony_ci * @interface: Interface to get the port count for
798c2ecf20Sopenharmony_ci *
808c2ecf20Sopenharmony_ci * Returns Number of ports on interface. Can be Zero.
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_ciint cvmx_helper_ports_on_interface(int interface)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	return interface_port_count[interface];
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_ports_on_interface);
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci/**
898c2ecf20Sopenharmony_ci * @INTERNAL
908c2ecf20Sopenharmony_ci * Return interface mode for CN68xx.
918c2ecf20Sopenharmony_ci */
928c2ecf20Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_cn68xx(int interface)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	union cvmx_mio_qlmx_cfg qlm_cfg;
958c2ecf20Sopenharmony_ci	switch (interface) {
968c2ecf20Sopenharmony_ci	case 0:
978c2ecf20Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
988c2ecf20Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
998c2ecf20Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15)
1008c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci		if (qlm_cfg.s.qlm_cfg == 2)
1038c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
1048c2ecf20Sopenharmony_ci		else if (qlm_cfg.s.qlm_cfg == 3)
1058c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
1068c2ecf20Sopenharmony_ci		else
1078c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1088c2ecf20Sopenharmony_ci	case 2:
1098c2ecf20Sopenharmony_ci	case 3:
1108c2ecf20Sopenharmony_ci	case 4:
1118c2ecf20Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface));
1128c2ecf20Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
1138c2ecf20Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15)
1148c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci		if (qlm_cfg.s.qlm_cfg == 2)
1178c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
1188c2ecf20Sopenharmony_ci		else if (qlm_cfg.s.qlm_cfg == 3)
1198c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
1208c2ecf20Sopenharmony_ci		else
1218c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1228c2ecf20Sopenharmony_ci	case 7:
1238c2ecf20Sopenharmony_ci		qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3));
1248c2ecf20Sopenharmony_ci		/* QLM is disabled when QLM SPD is 15. */
1258c2ecf20Sopenharmony_ci		if (qlm_cfg.s.qlm_spd == 15) {
1268c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1278c2ecf20Sopenharmony_ci		} else if (qlm_cfg.s.qlm_cfg != 0) {
1288c2ecf20Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
1298c2ecf20Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg != 0)
1308c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1318c2ecf20Sopenharmony_ci		}
1328c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
1338c2ecf20Sopenharmony_ci	case 8:
1348c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
1358c2ecf20Sopenharmony_ci	default:
1368c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci/**
1418c2ecf20Sopenharmony_ci * @INTERNAL
1428c2ecf20Sopenharmony_ci * Return interface mode for an Octeon II
1438c2ecf20Sopenharmony_ci */
1448c2ecf20Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_octeon2(int interface)
1458c2ecf20Sopenharmony_ci{
1468c2ecf20Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
1498c2ecf20Sopenharmony_ci		return __cvmx_get_mode_cn68xx(interface);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (interface == 2)
1528c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (interface == 3)
1558c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	/* Only present in CN63XX & CN66XX Octeon model */
1588c2ecf20Sopenharmony_ci	if ((OCTEON_IS_MODEL(OCTEON_CN63XX) &&
1598c2ecf20Sopenharmony_ci	     (interface == 4 || interface == 5)) ||
1608c2ecf20Sopenharmony_ci	    (OCTEON_IS_MODEL(OCTEON_CN66XX) &&
1618c2ecf20Sopenharmony_ci	     interface >= 4 && interface <= 7)) {
1628c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1638c2ecf20Sopenharmony_ci	}
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN66XX)) {
1668c2ecf20Sopenharmony_ci		union cvmx_mio_qlmx_cfg mio_qlm_cfg;
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci		/* QLM2 is SGMII0 and QLM1 is SGMII1 */
1698c2ecf20Sopenharmony_ci		if (interface == 0)
1708c2ecf20Sopenharmony_ci			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
1718c2ecf20Sopenharmony_ci		else if (interface == 1)
1728c2ecf20Sopenharmony_ci			mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1));
1738c2ecf20Sopenharmony_ci		else
1748c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci		if (mio_qlm_cfg.s.qlm_spd == 15)
1778c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci		if (mio_qlm_cfg.s.qlm_cfg == 9)
1808c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
1818c2ecf20Sopenharmony_ci		else if (mio_qlm_cfg.s.qlm_cfg == 11)
1828c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
1838c2ecf20Sopenharmony_ci		else
1848c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1858c2ecf20Sopenharmony_ci	} else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) {
1868c2ecf20Sopenharmony_ci		union cvmx_mio_qlmx_cfg qlm_cfg;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		if (interface == 0) {
1898c2ecf20Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2));
1908c2ecf20Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
1918c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
1928c2ecf20Sopenharmony_ci			else if (qlm_cfg.s.qlm_cfg == 3)
1938c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_XAUI;
1948c2ecf20Sopenharmony_ci			else
1958c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
1968c2ecf20Sopenharmony_ci		} else if (interface == 1) {
1978c2ecf20Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
1988c2ecf20Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
1998c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
2008c2ecf20Sopenharmony_ci			else if (qlm_cfg.s.qlm_cfg == 3)
2018c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_XAUI;
2028c2ecf20Sopenharmony_ci			else
2038c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2048c2ecf20Sopenharmony_ci		}
2058c2ecf20Sopenharmony_ci	} else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) {
2068c2ecf20Sopenharmony_ci		if (interface == 0) {
2078c2ecf20Sopenharmony_ci			union cvmx_mio_qlmx_cfg qlm_cfg;
2088c2ecf20Sopenharmony_ci			qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0));
2098c2ecf20Sopenharmony_ci			if (qlm_cfg.s.qlm_cfg == 2)
2108c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SGMII;
2118c2ecf20Sopenharmony_ci		}
2128c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2138c2ecf20Sopenharmony_ci	}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	if (interface == 1 && OCTEON_IS_MODEL(OCTEON_CN63XX))
2168c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
2218c2ecf20Sopenharmony_ci		switch (mode.cn61xx.mode) {
2228c2ecf20Sopenharmony_ci		case 0:
2238c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
2248c2ecf20Sopenharmony_ci		case 1:
2258c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
2268c2ecf20Sopenharmony_ci		default:
2278c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci	} else {
2308c2ecf20Sopenharmony_ci		if (!mode.s.en)
2318c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci		if (mode.s.type)
2348c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_GMII;
2358c2ecf20Sopenharmony_ci		else
2368c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_RGMII;
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci/**
2418c2ecf20Sopenharmony_ci * @INTERNAL
2428c2ecf20Sopenharmony_ci * Return interface mode for CN7XXX.
2438c2ecf20Sopenharmony_ci */
2448c2ecf20Sopenharmony_cistatic cvmx_helper_interface_mode_t __cvmx_get_mode_cn7xxx(int interface)
2458c2ecf20Sopenharmony_ci{
2468c2ecf20Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	switch (interface) {
2518c2ecf20Sopenharmony_ci	case 0:
2528c2ecf20Sopenharmony_ci	case 1:
2538c2ecf20Sopenharmony_ci		switch (mode.cn68xx.mode) {
2548c2ecf20Sopenharmony_ci		case 0:
2558c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2568c2ecf20Sopenharmony_ci		case 1:
2578c2ecf20Sopenharmony_ci		case 2:
2588c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
2598c2ecf20Sopenharmony_ci		case 3:
2608c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
2618c2ecf20Sopenharmony_ci		default:
2628c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
2638c2ecf20Sopenharmony_ci		}
2648c2ecf20Sopenharmony_ci	case 2:
2658c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
2668c2ecf20Sopenharmony_ci	case 3:
2678c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_LOOP;
2688c2ecf20Sopenharmony_ci	case 4:
2698c2ecf20Sopenharmony_ci		/* TODO: Implement support for AGL (RGMII). */
2708c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2718c2ecf20Sopenharmony_ci	default:
2728c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2738c2ecf20Sopenharmony_ci	}
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/**
2778c2ecf20Sopenharmony_ci * Get the operating mode of an interface. Depending on the Octeon
2788c2ecf20Sopenharmony_ci * chip and configuration, this function returns an enumeration
2798c2ecf20Sopenharmony_ci * of the type of packet I/O supported by an interface.
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * @interface: Interface to probe
2828c2ecf20Sopenharmony_ci *
2838c2ecf20Sopenharmony_ci * Returns Mode of the interface. Unknown or unsupported interfaces return
2848c2ecf20Sopenharmony_ci *	   DISABLED.
2858c2ecf20Sopenharmony_ci */
2868c2ecf20Sopenharmony_cicvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	union cvmx_gmxx_inf_mode mode;
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	if (interface < 0 ||
2918c2ecf20Sopenharmony_ci	    interface >= cvmx_helper_get_number_of_interfaces())
2928c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	/*
2958c2ecf20Sopenharmony_ci	 * OCTEON III models
2968c2ecf20Sopenharmony_ci	 */
2978c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN7XXX))
2988c2ecf20Sopenharmony_ci		return __cvmx_get_mode_cn7xxx(interface);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	/*
3018c2ecf20Sopenharmony_ci	 * Octeon II models
3028c2ecf20Sopenharmony_ci	 */
3038c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX))
3048c2ecf20Sopenharmony_ci		return __cvmx_get_mode_octeon2(interface);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	/*
3078c2ecf20Sopenharmony_ci	 * Octeon and Octeon Plus models
3088c2ecf20Sopenharmony_ci	 */
3098c2ecf20Sopenharmony_ci	if (interface == 2)
3108c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_NPI;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	if (interface == 3) {
3138c2ecf20Sopenharmony_ci		if (OCTEON_IS_MODEL(OCTEON_CN56XX)
3148c2ecf20Sopenharmony_ci		    || OCTEON_IS_MODEL(OCTEON_CN52XX))
3158c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_LOOP;
3168c2ecf20Sopenharmony_ci		else
3178c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	/* Interface 1 is always disabled on CN31XX and CN30XX */
3218c2ecf20Sopenharmony_ci	if ((interface == 1)
3228c2ecf20Sopenharmony_ci	    && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX)
3238c2ecf20Sopenharmony_ci		|| OCTEON_IS_MODEL(OCTEON_CN50XX)
3248c2ecf20Sopenharmony_ci		|| OCTEON_IS_MODEL(OCTEON_CN52XX)))
3258c2ecf20Sopenharmony_ci		return CVMX_HELPER_INTERFACE_MODE_DISABLED;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface));
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) {
3308c2ecf20Sopenharmony_ci		switch (mode.cn52xx.mode) {
3318c2ecf20Sopenharmony_ci		case 0:
3328c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
3338c2ecf20Sopenharmony_ci		case 1:
3348c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_XAUI;
3358c2ecf20Sopenharmony_ci		case 2:
3368c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_SGMII;
3378c2ecf20Sopenharmony_ci		case 3:
3388c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_PICMG;
3398c2ecf20Sopenharmony_ci		default:
3408c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
3418c2ecf20Sopenharmony_ci		}
3428c2ecf20Sopenharmony_ci	} else {
3438c2ecf20Sopenharmony_ci		if (!mode.s.en)
3448c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_DISABLED;
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci		if (mode.s.type) {
3478c2ecf20Sopenharmony_ci			if (OCTEON_IS_MODEL(OCTEON_CN38XX)
3488c2ecf20Sopenharmony_ci			    || OCTEON_IS_MODEL(OCTEON_CN58XX))
3498c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_SPI;
3508c2ecf20Sopenharmony_ci			else
3518c2ecf20Sopenharmony_ci				return CVMX_HELPER_INTERFACE_MODE_GMII;
3528c2ecf20Sopenharmony_ci		} else
3538c2ecf20Sopenharmony_ci			return CVMX_HELPER_INTERFACE_MODE_RGMII;
3548c2ecf20Sopenharmony_ci	}
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_interface_get_mode);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci/**
3598c2ecf20Sopenharmony_ci * Configure the IPD/PIP tagging and QoS options for a specific
3608c2ecf20Sopenharmony_ci * port. This function determines the POW work queue entry
3618c2ecf20Sopenharmony_ci * contents for a port. The setup performed here is controlled by
3628c2ecf20Sopenharmony_ci * the defines in executive-config.h.
3638c2ecf20Sopenharmony_ci *
3648c2ecf20Sopenharmony_ci * @ipd_port: Port to configure. This follows the IPD numbering, not the
3658c2ecf20Sopenharmony_ci *		   per interface numbering
3668c2ecf20Sopenharmony_ci *
3678c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
3688c2ecf20Sopenharmony_ci */
3698c2ecf20Sopenharmony_cistatic int __cvmx_helper_port_setup_ipd(int ipd_port)
3708c2ecf20Sopenharmony_ci{
3718c2ecf20Sopenharmony_ci	union cvmx_pip_prt_cfgx port_config;
3728c2ecf20Sopenharmony_ci	union cvmx_pip_prt_tagx tag_config;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port));
3758c2ecf20Sopenharmony_ci	tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port));
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/* Have each port go to a different POW queue */
3788c2ecf20Sopenharmony_ci	port_config.s.qos = ipd_port & 0x7;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	/* Process the headers and place the IP header in the work queue */
3818c2ecf20Sopenharmony_ci	port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE;
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP;
3848c2ecf20Sopenharmony_ci	tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP;
3858c2ecf20Sopenharmony_ci	tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT;
3868c2ecf20Sopenharmony_ci	tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT;
3878c2ecf20Sopenharmony_ci	tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER;
3888c2ecf20Sopenharmony_ci	tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP;
3898c2ecf20Sopenharmony_ci	tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP;
3908c2ecf20Sopenharmony_ci	tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT;
3918c2ecf20Sopenharmony_ci	tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT;
3928c2ecf20Sopenharmony_ci	tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL;
3938c2ecf20Sopenharmony_ci	tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT;
3948c2ecf20Sopenharmony_ci	tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
3958c2ecf20Sopenharmony_ci	tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
3968c2ecf20Sopenharmony_ci	tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
3978c2ecf20Sopenharmony_ci	tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
3988c2ecf20Sopenharmony_ci	tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE;
3998c2ecf20Sopenharmony_ci	/* Put all packets in group 0. Other groups can be used by the app */
4008c2ecf20Sopenharmony_ci	tag_config.s.grp = 0;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	cvmx_pip_config_port(ipd_port, port_config, tag_config);
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_ci	return 0;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci/**
4088c2ecf20Sopenharmony_ci * This function sets the interface_port_count[interface] correctly,
4098c2ecf20Sopenharmony_ci * without modifying any hardware configuration.  Hardware setup of
4108c2ecf20Sopenharmony_ci * the ports will be performed later.
4118c2ecf20Sopenharmony_ci *
4128c2ecf20Sopenharmony_ci * @interface: Interface to probe
4138c2ecf20Sopenharmony_ci *
4148c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
4158c2ecf20Sopenharmony_ci */
4168c2ecf20Sopenharmony_ciint cvmx_helper_interface_enumerate(int interface)
4178c2ecf20Sopenharmony_ci{
4188c2ecf20Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
4198c2ecf20Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
4208c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
4218c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
4228c2ecf20Sopenharmony_ci		interface_port_count[interface] = 0;
4238c2ecf20Sopenharmony_ci		break;
4248c2ecf20Sopenharmony_ci		/* XAUI is a single high speed port */
4258c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
4268c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4278c2ecf20Sopenharmony_ci		    __cvmx_helper_xaui_enumerate(interface);
4288c2ecf20Sopenharmony_ci		break;
4298c2ecf20Sopenharmony_ci		/*
4308c2ecf20Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
4318c2ecf20Sopenharmony_ci		 * functions refer to these ports as RGMII.
4328c2ecf20Sopenharmony_ci		 */
4338c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
4348c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
4358c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4368c2ecf20Sopenharmony_ci		    __cvmx_helper_rgmii_enumerate(interface);
4378c2ecf20Sopenharmony_ci		break;
4388c2ecf20Sopenharmony_ci		/*
4398c2ecf20Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
4408c2ecf20Sopenharmony_ci		 * the other end.
4418c2ecf20Sopenharmony_ci		 */
4428c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
4438c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4448c2ecf20Sopenharmony_ci		    __cvmx_helper_spi_enumerate(interface);
4458c2ecf20Sopenharmony_ci		break;
4468c2ecf20Sopenharmony_ci		/*
4478c2ecf20Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
4488c2ecf20Sopenharmony_ci		 * hooked up.
4498c2ecf20Sopenharmony_ci		 */
4508c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
4518c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
4528c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4538c2ecf20Sopenharmony_ci		    __cvmx_helper_sgmii_enumerate(interface);
4548c2ecf20Sopenharmony_ci		break;
4558c2ecf20Sopenharmony_ci		/* PCI target Network Packet Interface */
4568c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
4578c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4588c2ecf20Sopenharmony_ci		    __cvmx_helper_npi_enumerate(interface);
4598c2ecf20Sopenharmony_ci		break;
4608c2ecf20Sopenharmony_ci		/*
4618c2ecf20Sopenharmony_ci		 * Special loopback only ports. These are not the same
4628c2ecf20Sopenharmony_ci		 * as other ports in loopback mode.
4638c2ecf20Sopenharmony_ci		 */
4648c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
4658c2ecf20Sopenharmony_ci		interface_port_count[interface] =
4668c2ecf20Sopenharmony_ci		    __cvmx_helper_loop_enumerate(interface);
4678c2ecf20Sopenharmony_ci		break;
4688c2ecf20Sopenharmony_ci	}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	interface_port_count[interface] =
4718c2ecf20Sopenharmony_ci	    __cvmx_helper_board_interface_probe(interface,
4728c2ecf20Sopenharmony_ci						interface_port_count
4738c2ecf20Sopenharmony_ci						[interface]);
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	/* Make sure all global variables propagate to other cores */
4768c2ecf20Sopenharmony_ci	CVMX_SYNCWS;
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	return 0;
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci/**
4828c2ecf20Sopenharmony_ci * This function probes an interface to determine the actual
4838c2ecf20Sopenharmony_ci * number of hardware ports connected to it. It doesn't setup the
4848c2ecf20Sopenharmony_ci * ports or enable them. The main goal here is to set the global
4858c2ecf20Sopenharmony_ci * interface_port_count[interface] correctly. Hardware setup of the
4868c2ecf20Sopenharmony_ci * ports will be performed later.
4878c2ecf20Sopenharmony_ci *
4888c2ecf20Sopenharmony_ci * @interface: Interface to probe
4898c2ecf20Sopenharmony_ci *
4908c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
4918c2ecf20Sopenharmony_ci */
4928c2ecf20Sopenharmony_ciint cvmx_helper_interface_probe(int interface)
4938c2ecf20Sopenharmony_ci{
4948c2ecf20Sopenharmony_ci	cvmx_helper_interface_enumerate(interface);
4958c2ecf20Sopenharmony_ci	/* At this stage in the game we don't want packets to be moving yet.
4968c2ecf20Sopenharmony_ci	   The following probe calls should perform hardware setup
4978c2ecf20Sopenharmony_ci	   needed to determine port counts. Receive must still be disabled */
4988c2ecf20Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
4998c2ecf20Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
5008c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
5018c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
5028c2ecf20Sopenharmony_ci		break;
5038c2ecf20Sopenharmony_ci		/* XAUI is a single high speed port */
5048c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
5058c2ecf20Sopenharmony_ci		__cvmx_helper_xaui_probe(interface);
5068c2ecf20Sopenharmony_ci		break;
5078c2ecf20Sopenharmony_ci		/*
5088c2ecf20Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
5098c2ecf20Sopenharmony_ci		 * functions refer to these ports as RGMII.
5108c2ecf20Sopenharmony_ci		 */
5118c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
5128c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
5138c2ecf20Sopenharmony_ci		__cvmx_helper_rgmii_probe(interface);
5148c2ecf20Sopenharmony_ci		break;
5158c2ecf20Sopenharmony_ci		/*
5168c2ecf20Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
5178c2ecf20Sopenharmony_ci		 * the other end.
5188c2ecf20Sopenharmony_ci		 */
5198c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
5208c2ecf20Sopenharmony_ci		__cvmx_helper_spi_probe(interface);
5218c2ecf20Sopenharmony_ci		break;
5228c2ecf20Sopenharmony_ci		/*
5238c2ecf20Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
5248c2ecf20Sopenharmony_ci		 * hooked up.
5258c2ecf20Sopenharmony_ci		 */
5268c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
5278c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
5288c2ecf20Sopenharmony_ci		__cvmx_helper_sgmii_probe(interface);
5298c2ecf20Sopenharmony_ci		break;
5308c2ecf20Sopenharmony_ci		/* PCI target Network Packet Interface */
5318c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
5328c2ecf20Sopenharmony_ci		__cvmx_helper_npi_probe(interface);
5338c2ecf20Sopenharmony_ci		break;
5348c2ecf20Sopenharmony_ci		/*
5358c2ecf20Sopenharmony_ci		 * Special loopback only ports. These are not the same
5368c2ecf20Sopenharmony_ci		 * as other ports in loopback mode.
5378c2ecf20Sopenharmony_ci		 */
5388c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
5398c2ecf20Sopenharmony_ci		__cvmx_helper_loop_probe(interface);
5408c2ecf20Sopenharmony_ci		break;
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci	/* Make sure all global variables propagate to other cores */
5448c2ecf20Sopenharmony_ci	CVMX_SYNCWS;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	return 0;
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci/**
5508c2ecf20Sopenharmony_ci * Setup the IPD/PIP for the ports on an interface. Packet
5518c2ecf20Sopenharmony_ci * classification and tagging are set for every port on the
5528c2ecf20Sopenharmony_ci * interface. The number of ports on the interface must already
5538c2ecf20Sopenharmony_ci * have been probed.
5548c2ecf20Sopenharmony_ci *
5558c2ecf20Sopenharmony_ci * @interface: Interface to setup IPD/PIP for
5568c2ecf20Sopenharmony_ci *
5578c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
5588c2ecf20Sopenharmony_ci */
5598c2ecf20Sopenharmony_cistatic int __cvmx_helper_interface_setup_ipd(int interface)
5608c2ecf20Sopenharmony_ci{
5618c2ecf20Sopenharmony_ci	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
5628c2ecf20Sopenharmony_ci	int num_ports = interface_port_count[interface];
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	while (num_ports--) {
5658c2ecf20Sopenharmony_ci		__cvmx_helper_port_setup_ipd(ipd_port);
5668c2ecf20Sopenharmony_ci		ipd_port++;
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci	return 0;
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci/**
5728c2ecf20Sopenharmony_ci * Setup global setting for IPD/PIP not related to a specific
5738c2ecf20Sopenharmony_ci * interface or port. This must be called before IPD is enabled.
5748c2ecf20Sopenharmony_ci *
5758c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure.
5768c2ecf20Sopenharmony_ci */
5778c2ecf20Sopenharmony_cistatic int __cvmx_helper_global_setup_ipd(void)
5788c2ecf20Sopenharmony_ci{
5798c2ecf20Sopenharmony_ci	/* Setup the global packet input options */
5808c2ecf20Sopenharmony_ci	cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8,
5818c2ecf20Sopenharmony_ci			CVMX_HELPER_FIRST_MBUFF_SKIP / 8,
5828c2ecf20Sopenharmony_ci			CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8,
5838c2ecf20Sopenharmony_ci			/* The +8 is to account for the next ptr */
5848c2ecf20Sopenharmony_ci			(CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128,
5858c2ecf20Sopenharmony_ci			/* The +8 is to account for the next ptr */
5868c2ecf20Sopenharmony_ci			(CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128,
5878c2ecf20Sopenharmony_ci			CVMX_FPA_WQE_POOL,
5888c2ecf20Sopenharmony_ci			CVMX_IPD_OPC_MODE_STT,
5898c2ecf20Sopenharmony_ci			CVMX_HELPER_ENABLE_BACK_PRESSURE);
5908c2ecf20Sopenharmony_ci	return 0;
5918c2ecf20Sopenharmony_ci}
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci/**
5948c2ecf20Sopenharmony_ci * Setup the PKO for the ports on an interface. The number of
5958c2ecf20Sopenharmony_ci * queues per port and the priority of each PKO output queue
5968c2ecf20Sopenharmony_ci * is set here. PKO must be disabled when this function is called.
5978c2ecf20Sopenharmony_ci *
5988c2ecf20Sopenharmony_ci * @interface: Interface to setup PKO for
5998c2ecf20Sopenharmony_ci *
6008c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
6018c2ecf20Sopenharmony_ci */
6028c2ecf20Sopenharmony_cistatic int __cvmx_helper_interface_setup_pko(int interface)
6038c2ecf20Sopenharmony_ci{
6048c2ecf20Sopenharmony_ci	/*
6058c2ecf20Sopenharmony_ci	 * Each packet output queue has an associated priority. The
6068c2ecf20Sopenharmony_ci	 * higher the priority, the more often it can send a packet. A
6078c2ecf20Sopenharmony_ci	 * priority of 8 means it can send in all 8 rounds of
6088c2ecf20Sopenharmony_ci	 * contention. We're going to make each queue one less than
6098c2ecf20Sopenharmony_ci	 * the last.  The vector of priorities has been extended to
6108c2ecf20Sopenharmony_ci	 * support CN5xxx CPUs, where up to 16 queues can be
6118c2ecf20Sopenharmony_ci	 * associated to a port.  To keep backward compatibility we
6128c2ecf20Sopenharmony_ci	 * don't change the initial 8 priorities and replicate them in
6138c2ecf20Sopenharmony_ci	 * the second half.  With per-core PKO queues (PKO lockless
6148c2ecf20Sopenharmony_ci	 * operation) all queues have the same priority.
6158c2ecf20Sopenharmony_ci	 */
6168c2ecf20Sopenharmony_ci	uint64_t priorities[16] =
6178c2ecf20Sopenharmony_ci	    { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 };
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	/*
6208c2ecf20Sopenharmony_ci	 * Setup the IPD/PIP and PKO for the ports discovered
6218c2ecf20Sopenharmony_ci	 * above. Here packet classification, tagging and output
6228c2ecf20Sopenharmony_ci	 * priorities are set.
6238c2ecf20Sopenharmony_ci	 */
6248c2ecf20Sopenharmony_ci	int ipd_port = cvmx_helper_get_ipd_port(interface, 0);
6258c2ecf20Sopenharmony_ci	int num_ports = interface_port_count[interface];
6268c2ecf20Sopenharmony_ci	while (num_ports--) {
6278c2ecf20Sopenharmony_ci		cvmx_pko_config_port(ipd_port,
6288c2ecf20Sopenharmony_ci				     cvmx_pko_get_base_queue_per_core(ipd_port,
6298c2ecf20Sopenharmony_ci								      0),
6308c2ecf20Sopenharmony_ci				     cvmx_pko_get_num_queues(ipd_port),
6318c2ecf20Sopenharmony_ci				     priorities);
6328c2ecf20Sopenharmony_ci		ipd_port++;
6338c2ecf20Sopenharmony_ci	}
6348c2ecf20Sopenharmony_ci	return 0;
6358c2ecf20Sopenharmony_ci}
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci/**
6388c2ecf20Sopenharmony_ci * Setup global setting for PKO not related to a specific
6398c2ecf20Sopenharmony_ci * interface or port. This must be called before PKO is enabled.
6408c2ecf20Sopenharmony_ci *
6418c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure.
6428c2ecf20Sopenharmony_ci */
6438c2ecf20Sopenharmony_cistatic int __cvmx_helper_global_setup_pko(void)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	/*
6468c2ecf20Sopenharmony_ci	 * Disable tagwait FAU timeout. This needs to be done before
6478c2ecf20Sopenharmony_ci	 * anyone might start packet output using tags.
6488c2ecf20Sopenharmony_ci	 */
6498c2ecf20Sopenharmony_ci	union cvmx_iob_fau_timeout fau_to;
6508c2ecf20Sopenharmony_ci	fau_to.u64 = 0;
6518c2ecf20Sopenharmony_ci	fau_to.s.tout_val = 0xfff;
6528c2ecf20Sopenharmony_ci	fau_to.s.tout_enb = 0;
6538c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
6568c2ecf20Sopenharmony_ci		union cvmx_pko_reg_min_pkt min_pkt;
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci		min_pkt.u64 = 0;
6598c2ecf20Sopenharmony_ci		min_pkt.s.size1 = 59;
6608c2ecf20Sopenharmony_ci		min_pkt.s.size2 = 59;
6618c2ecf20Sopenharmony_ci		min_pkt.s.size3 = 59;
6628c2ecf20Sopenharmony_ci		min_pkt.s.size4 = 59;
6638c2ecf20Sopenharmony_ci		min_pkt.s.size5 = 59;
6648c2ecf20Sopenharmony_ci		min_pkt.s.size6 = 59;
6658c2ecf20Sopenharmony_ci		min_pkt.s.size7 = 59;
6668c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64);
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	return 0;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci/**
6738c2ecf20Sopenharmony_ci * Setup global backpressure setting.
6748c2ecf20Sopenharmony_ci *
6758c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
6768c2ecf20Sopenharmony_ci */
6778c2ecf20Sopenharmony_cistatic int __cvmx_helper_global_setup_backpressure(void)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE
6808c2ecf20Sopenharmony_ci	/* Disable backpressure if configured to do so */
6818c2ecf20Sopenharmony_ci	/* Disable backpressure (pause frame) generation */
6828c2ecf20Sopenharmony_ci	int num_interfaces = cvmx_helper_get_number_of_interfaces();
6838c2ecf20Sopenharmony_ci	int interface;
6848c2ecf20Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
6858c2ecf20Sopenharmony_ci		switch (cvmx_helper_interface_get_mode(interface)) {
6868c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_DISABLED:
6878c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_PCIE:
6888c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_NPI:
6898c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_LOOP:
6908c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_XAUI:
6918c2ecf20Sopenharmony_ci			break;
6928c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_RGMII:
6938c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_GMII:
6948c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_SPI:
6958c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_SGMII:
6968c2ecf20Sopenharmony_ci		case CVMX_HELPER_INTERFACE_MODE_PICMG:
6978c2ecf20Sopenharmony_ci			cvmx_gmx_set_backpressure_override(interface, 0xf);
6988c2ecf20Sopenharmony_ci			break;
6998c2ecf20Sopenharmony_ci		}
7008c2ecf20Sopenharmony_ci	}
7018c2ecf20Sopenharmony_ci#endif
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	return 0;
7048c2ecf20Sopenharmony_ci}
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci/**
7078c2ecf20Sopenharmony_ci * Enable packet input/output from the hardware. This function is
7088c2ecf20Sopenharmony_ci * called after all internal setup is complete and IPD is enabled.
7098c2ecf20Sopenharmony_ci * After this function completes, packets will be accepted from the
7108c2ecf20Sopenharmony_ci * hardware ports. PKO should still be disabled to make sure packets
7118c2ecf20Sopenharmony_ci * aren't sent out partially setup hardware.
7128c2ecf20Sopenharmony_ci *
7138c2ecf20Sopenharmony_ci * @interface: Interface to enable
7148c2ecf20Sopenharmony_ci *
7158c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
7168c2ecf20Sopenharmony_ci */
7178c2ecf20Sopenharmony_cistatic int __cvmx_helper_packet_hardware_enable(int interface)
7188c2ecf20Sopenharmony_ci{
7198c2ecf20Sopenharmony_ci	int result = 0;
7208c2ecf20Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
7218c2ecf20Sopenharmony_ci		/* These types don't support ports to IPD/PKO */
7228c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
7238c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
7248c2ecf20Sopenharmony_ci		/* Nothing to do */
7258c2ecf20Sopenharmony_ci		break;
7268c2ecf20Sopenharmony_ci		/* XAUI is a single high speed port */
7278c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
7288c2ecf20Sopenharmony_ci		result = __cvmx_helper_xaui_enable(interface);
7298c2ecf20Sopenharmony_ci		break;
7308c2ecf20Sopenharmony_ci		/*
7318c2ecf20Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
7328c2ecf20Sopenharmony_ci		 * functions refer to these ports as RGMII
7338c2ecf20Sopenharmony_ci		 */
7348c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
7358c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
7368c2ecf20Sopenharmony_ci		result = __cvmx_helper_rgmii_enable(interface);
7378c2ecf20Sopenharmony_ci		break;
7388c2ecf20Sopenharmony_ci		/*
7398c2ecf20Sopenharmony_ci		 * SPI4 can have 1-16 ports depending on the device at
7408c2ecf20Sopenharmony_ci		 * the other end
7418c2ecf20Sopenharmony_ci		 */
7428c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
7438c2ecf20Sopenharmony_ci		result = __cvmx_helper_spi_enable(interface);
7448c2ecf20Sopenharmony_ci		break;
7458c2ecf20Sopenharmony_ci		/*
7468c2ecf20Sopenharmony_ci		 * SGMII can have 1-4 ports depending on how many are
7478c2ecf20Sopenharmony_ci		 * hooked up
7488c2ecf20Sopenharmony_ci		 */
7498c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
7508c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
7518c2ecf20Sopenharmony_ci		result = __cvmx_helper_sgmii_enable(interface);
7528c2ecf20Sopenharmony_ci		break;
7538c2ecf20Sopenharmony_ci		/* PCI target Network Packet Interface */
7548c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
7558c2ecf20Sopenharmony_ci		result = __cvmx_helper_npi_enable(interface);
7568c2ecf20Sopenharmony_ci		break;
7578c2ecf20Sopenharmony_ci		/*
7588c2ecf20Sopenharmony_ci		 * Special loopback only ports. These are not the same
7598c2ecf20Sopenharmony_ci		 * as other ports in loopback mode
7608c2ecf20Sopenharmony_ci		 */
7618c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
7628c2ecf20Sopenharmony_ci		result = __cvmx_helper_loop_enable(interface);
7638c2ecf20Sopenharmony_ci		break;
7648c2ecf20Sopenharmony_ci	}
7658c2ecf20Sopenharmony_ci	return result;
7668c2ecf20Sopenharmony_ci}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci/**
7698c2ecf20Sopenharmony_ci * Function to adjust internal IPD pointer alignments
7708c2ecf20Sopenharmony_ci *
7718c2ecf20Sopenharmony_ci * Returns 0 on success
7728c2ecf20Sopenharmony_ci *	   !0 on failure
7738c2ecf20Sopenharmony_ci */
7748c2ecf20Sopenharmony_cistatic int __cvmx_helper_errata_fix_ipd_ptr_alignment(void)
7758c2ecf20Sopenharmony_ci{
7768c2ecf20Sopenharmony_ci#define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \
7778c2ecf20Sopenharmony_ci     (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP)
7788c2ecf20Sopenharmony_ci#define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \
7798c2ecf20Sopenharmony_ci	(CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP)
7808c2ecf20Sopenharmony_ci#define FIX_IPD_OUTPORT 0
7818c2ecf20Sopenharmony_ci	/* Ports 0-15 are interface 0, 16-31 are interface 1 */
7828c2ecf20Sopenharmony_ci#define INTERFACE(port) (port >> 4)
7838c2ecf20Sopenharmony_ci#define INDEX(port) (port & 0xf)
7848c2ecf20Sopenharmony_ci	uint64_t *p64;
7858c2ecf20Sopenharmony_ci	union cvmx_pko_command_word0 pko_command;
7868c2ecf20Sopenharmony_ci	union cvmx_buf_ptr g_buffer, pkt_buffer;
7878c2ecf20Sopenharmony_ci	struct cvmx_wqe *work;
7888c2ecf20Sopenharmony_ci	int size, num_segs = 0, wqe_pcnt, pkt_pcnt;
7898c2ecf20Sopenharmony_ci	union cvmx_gmxx_prtx_cfg gmx_cfg;
7908c2ecf20Sopenharmony_ci	int retry_cnt;
7918c2ecf20Sopenharmony_ci	int retry_loop_cnt;
7928c2ecf20Sopenharmony_ci	int i;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	/* Save values for restore at end */
7958c2ecf20Sopenharmony_ci	uint64_t prtx_cfg =
7968c2ecf20Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
7978c2ecf20Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
7988c2ecf20Sopenharmony_ci	uint64_t tx_ptr_en =
7998c2ecf20Sopenharmony_ci	    cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
8008c2ecf20Sopenharmony_ci	uint64_t rx_ptr_en =
8018c2ecf20Sopenharmony_ci	    cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)));
8028c2ecf20Sopenharmony_ci	uint64_t rxx_jabber =
8038c2ecf20Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_RXX_JABBER
8048c2ecf20Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
8058c2ecf20Sopenharmony_ci	uint64_t frame_max =
8068c2ecf20Sopenharmony_ci	    cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX
8078c2ecf20Sopenharmony_ci			  (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)));
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	/* Configure port to gig FDX as required for loopback mode */
8108c2ecf20Sopenharmony_ci	cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT);
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	/*
8138c2ecf20Sopenharmony_ci	 * Disable reception on all ports so if traffic is present it
8148c2ecf20Sopenharmony_ci	 * will not interfere.
8158c2ecf20Sopenharmony_ci	 */
8168c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	__delay(100000000ull);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) {
8218c2ecf20Sopenharmony_ci		retry_cnt = 100000;
8228c2ecf20Sopenharmony_ci		wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT);
8238c2ecf20Sopenharmony_ci		pkt_pcnt = (wqe_pcnt >> 7) & 0x7f;
8248c2ecf20Sopenharmony_ci		wqe_pcnt &= 0x7f;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci		num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3;
8278c2ecf20Sopenharmony_ci
8288c2ecf20Sopenharmony_ci		if (num_segs == 0)
8298c2ecf20Sopenharmony_ci			goto fix_ipd_exit;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci		num_segs += 1;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci		size =
8348c2ecf20Sopenharmony_ci		    FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES +
8358c2ecf20Sopenharmony_ci		    ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) -
8368c2ecf20Sopenharmony_ci		    (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2);
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)),
8398c2ecf20Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
8408c2ecf20Sopenharmony_ci		CVMX_SYNC;
8418c2ecf20Sopenharmony_ci
8428c2ecf20Sopenharmony_ci		g_buffer.u64 = 0;
8438c2ecf20Sopenharmony_ci		g_buffer.s.addr =
8448c2ecf20Sopenharmony_ci		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL));
8458c2ecf20Sopenharmony_ci		if (g_buffer.s.addr == 0) {
8468c2ecf20Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
8478c2ecf20Sopenharmony_ci				     "buffer allocation failure.\n");
8488c2ecf20Sopenharmony_ci			goto fix_ipd_exit;
8498c2ecf20Sopenharmony_ci		}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci		g_buffer.s.pool = CVMX_FPA_WQE_POOL;
8528c2ecf20Sopenharmony_ci		g_buffer.s.size = num_segs;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci		pkt_buffer.u64 = 0;
8558c2ecf20Sopenharmony_ci		pkt_buffer.s.addr =
8568c2ecf20Sopenharmony_ci		    cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL));
8578c2ecf20Sopenharmony_ci		if (pkt_buffer.s.addr == 0) {
8588c2ecf20Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
8598c2ecf20Sopenharmony_ci				     "buffer allocation failure.\n");
8608c2ecf20Sopenharmony_ci			goto fix_ipd_exit;
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci		pkt_buffer.s.i = 1;
8638c2ecf20Sopenharmony_ci		pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL;
8648c2ecf20Sopenharmony_ci		pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES;
8658c2ecf20Sopenharmony_ci
8668c2ecf20Sopenharmony_ci		p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr);
8678c2ecf20Sopenharmony_ci		p64[0] = 0xffffffffffff0000ull;
8688c2ecf20Sopenharmony_ci		p64[1] = 0x08004510ull;
8698c2ecf20Sopenharmony_ci		p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull;
8708c2ecf20Sopenharmony_ci		p64[3] = 0x3a5fc0a81073c0a8ull;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci		for (i = 0; i < num_segs; i++) {
8738c2ecf20Sopenharmony_ci			if (i > 0)
8748c2ecf20Sopenharmony_ci				pkt_buffer.s.size =
8758c2ecf20Sopenharmony_ci				    FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES;
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci			if (i == (num_segs - 1))
8788c2ecf20Sopenharmony_ci				pkt_buffer.s.i = 0;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci			*(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr +
8818c2ecf20Sopenharmony_ci						       8 * i) = pkt_buffer.u64;
8828c2ecf20Sopenharmony_ci		}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci		/* Build the PKO command */
8858c2ecf20Sopenharmony_ci		pko_command.u64 = 0;
8868c2ecf20Sopenharmony_ci		pko_command.s.segs = num_segs;
8878c2ecf20Sopenharmony_ci		pko_command.s.total_bytes = size;
8888c2ecf20Sopenharmony_ci		pko_command.s.dontfree = 0;
8898c2ecf20Sopenharmony_ci		pko_command.s.gather = 1;
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci		gmx_cfg.u64 =
8928c2ecf20Sopenharmony_ci		    cvmx_read_csr(CVMX_GMXX_PRTX_CFG
8938c2ecf20Sopenharmony_ci				  (INDEX(FIX_IPD_OUTPORT),
8948c2ecf20Sopenharmony_ci				   INTERFACE(FIX_IPD_OUTPORT)));
8958c2ecf20Sopenharmony_ci		gmx_cfg.s.en = 1;
8968c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_PRTX_CFG
8978c2ecf20Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
8988c2ecf20Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64);
8998c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
9008c2ecf20Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
9018c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
9028c2ecf20Sopenharmony_ci			       1 << INDEX(FIX_IPD_OUTPORT));
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_RXX_JABBER
9058c2ecf20Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
9068c2ecf20Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
9078c2ecf20Sopenharmony_ci		cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
9088c2ecf20Sopenharmony_ci			       (INDEX(FIX_IPD_OUTPORT),
9098c2ecf20Sopenharmony_ci				INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4);
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT,
9128c2ecf20Sopenharmony_ci					     cvmx_pko_get_base_queue
9138c2ecf20Sopenharmony_ci					     (FIX_IPD_OUTPORT),
9148c2ecf20Sopenharmony_ci					     CVMX_PKO_LOCK_CMD_QUEUE);
9158c2ecf20Sopenharmony_ci		cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT,
9168c2ecf20Sopenharmony_ci					    cvmx_pko_get_base_queue
9178c2ecf20Sopenharmony_ci					    (FIX_IPD_OUTPORT), pko_command,
9188c2ecf20Sopenharmony_ci					    g_buffer, CVMX_PKO_LOCK_CMD_QUEUE);
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci		CVMX_SYNC;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci		do {
9238c2ecf20Sopenharmony_ci			work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
9248c2ecf20Sopenharmony_ci			retry_cnt--;
9258c2ecf20Sopenharmony_ci		} while ((work == NULL) && (retry_cnt > 0));
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_ci		if (!retry_cnt)
9288c2ecf20Sopenharmony_ci			cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT "
9298c2ecf20Sopenharmony_ci				     "get_work() timeout occurred.\n");
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci		/* Free packet */
9328c2ecf20Sopenharmony_ci		if (work)
9338c2ecf20Sopenharmony_ci			cvmx_helper_free_packet_data(work);
9348c2ecf20Sopenharmony_ci	}
9358c2ecf20Sopenharmony_ci
9368c2ecf20Sopenharmony_cifix_ipd_exit:
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	/* Return CSR configs to saved values */
9398c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_PRTX_CFG
9408c2ecf20Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
9418c2ecf20Sopenharmony_ci		       prtx_cfg);
9428c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
9438c2ecf20Sopenharmony_ci		       tx_ptr_en);
9448c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)),
9458c2ecf20Sopenharmony_ci		       rx_ptr_en);
9468c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_RXX_JABBER
9478c2ecf20Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
9488c2ecf20Sopenharmony_ci		       rxx_jabber);
9498c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX
9508c2ecf20Sopenharmony_ci		       (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)),
9518c2ecf20Sopenharmony_ci		       frame_max);
9528c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0);
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci	CVMX_SYNC;
9558c2ecf20Sopenharmony_ci	if (num_segs)
9568c2ecf20Sopenharmony_ci		cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n");
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci	return !!num_segs;
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_ci/**
9638c2ecf20Sopenharmony_ci * Called after all internal packet IO paths are setup. This
9648c2ecf20Sopenharmony_ci * function enables IPD/PIP and begins packet input and output.
9658c2ecf20Sopenharmony_ci *
9668c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
9678c2ecf20Sopenharmony_ci */
9688c2ecf20Sopenharmony_ciint cvmx_helper_ipd_and_packet_input_enable(void)
9698c2ecf20Sopenharmony_ci{
9708c2ecf20Sopenharmony_ci	int num_interfaces;
9718c2ecf20Sopenharmony_ci	int interface;
9728c2ecf20Sopenharmony_ci
9738c2ecf20Sopenharmony_ci	/* Enable IPD */
9748c2ecf20Sopenharmony_ci	cvmx_ipd_enable();
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci	/*
9778c2ecf20Sopenharmony_ci	 * Time to enable hardware ports packet input and output. Note
9788c2ecf20Sopenharmony_ci	 * that at this point IPD/PIP must be fully functional and PKO
9798c2ecf20Sopenharmony_ci	 * must be disabled
9808c2ecf20Sopenharmony_ci	 */
9818c2ecf20Sopenharmony_ci	num_interfaces = cvmx_helper_get_number_of_interfaces();
9828c2ecf20Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
9838c2ecf20Sopenharmony_ci		if (cvmx_helper_ports_on_interface(interface) > 0)
9848c2ecf20Sopenharmony_ci			__cvmx_helper_packet_hardware_enable(interface);
9858c2ecf20Sopenharmony_ci	}
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci	/* Finally enable PKO now that the entire path is up and running */
9888c2ecf20Sopenharmony_ci	cvmx_pko_enable();
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1)
9918c2ecf20Sopenharmony_ci	     || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1))
9928c2ecf20Sopenharmony_ci	    && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM))
9938c2ecf20Sopenharmony_ci		__cvmx_helper_errata_fix_ipd_ptr_alignment();
9948c2ecf20Sopenharmony_ci	return 0;
9958c2ecf20Sopenharmony_ci}
9968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_ipd_and_packet_input_enable);
9978c2ecf20Sopenharmony_ci
9988c2ecf20Sopenharmony_ci/**
9998c2ecf20Sopenharmony_ci * Initialize the PIP, IPD, and PKO hardware to support
10008c2ecf20Sopenharmony_ci * simple priority based queues for the ethernet ports. Each
10018c2ecf20Sopenharmony_ci * port is configured with a number of priority queues based
10028c2ecf20Sopenharmony_ci * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower
10038c2ecf20Sopenharmony_ci * priority than the previous.
10048c2ecf20Sopenharmony_ci *
10058c2ecf20Sopenharmony_ci * Returns Zero on success, non-zero on failure
10068c2ecf20Sopenharmony_ci */
10078c2ecf20Sopenharmony_ciint cvmx_helper_initialize_packet_io_global(void)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	int result = 0;
10108c2ecf20Sopenharmony_ci	int interface;
10118c2ecf20Sopenharmony_ci	union cvmx_l2c_cfg l2c_cfg;
10128c2ecf20Sopenharmony_ci	const int num_interfaces = cvmx_helper_get_number_of_interfaces();
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	/*
10158c2ecf20Sopenharmony_ci	 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to
10168c2ecf20Sopenharmony_ci	 * be disabled.
10178c2ecf20Sopenharmony_ci	 */
10188c2ecf20Sopenharmony_ci	if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0))
10198c2ecf20Sopenharmony_ci		__cvmx_helper_errata_qlm_disable_2nd_order_cdr(1);
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	/*
10228c2ecf20Sopenharmony_ci	 * Tell L2 to give the IOB statically higher priority compared
10238c2ecf20Sopenharmony_ci	 * to the cores. This avoids conditions where IO blocks might
10248c2ecf20Sopenharmony_ci	 * be starved under very high L2 loads.
10258c2ecf20Sopenharmony_ci	 */
10268c2ecf20Sopenharmony_ci	l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
10278c2ecf20Sopenharmony_ci	l2c_cfg.s.lrf_arb_mode = 0;
10288c2ecf20Sopenharmony_ci	l2c_cfg.s.rfb_arb_mode = 0;
10298c2ecf20Sopenharmony_ci	cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	cvmx_pko_initialize_global();
10328c2ecf20Sopenharmony_ci	for (interface = 0; interface < num_interfaces; interface++) {
10338c2ecf20Sopenharmony_ci		result |= cvmx_helper_interface_probe(interface);
10348c2ecf20Sopenharmony_ci		if (cvmx_helper_ports_on_interface(interface) > 0)
10358c2ecf20Sopenharmony_ci			cvmx_dprintf("Interface %d has %d ports (%s)\n",
10368c2ecf20Sopenharmony_ci				     interface,
10378c2ecf20Sopenharmony_ci				     cvmx_helper_ports_on_interface(interface),
10388c2ecf20Sopenharmony_ci				     cvmx_helper_interface_mode_to_string
10398c2ecf20Sopenharmony_ci				     (cvmx_helper_interface_get_mode
10408c2ecf20Sopenharmony_ci				      (interface)));
10418c2ecf20Sopenharmony_ci		result |= __cvmx_helper_interface_setup_ipd(interface);
10428c2ecf20Sopenharmony_ci		result |= __cvmx_helper_interface_setup_pko(interface);
10438c2ecf20Sopenharmony_ci	}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_ci	result |= __cvmx_helper_global_setup_ipd();
10468c2ecf20Sopenharmony_ci	result |= __cvmx_helper_global_setup_pko();
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	/* Enable any flow control and backpressure */
10498c2ecf20Sopenharmony_ci	result |= __cvmx_helper_global_setup_backpressure();
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci#if CVMX_HELPER_ENABLE_IPD
10528c2ecf20Sopenharmony_ci	result |= cvmx_helper_ipd_and_packet_input_enable();
10538c2ecf20Sopenharmony_ci#endif
10548c2ecf20Sopenharmony_ci	return result;
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_initialize_packet_io_global);
10578c2ecf20Sopenharmony_ci
10588c2ecf20Sopenharmony_ci/**
10598c2ecf20Sopenharmony_ci * Does core local initialization for packet io
10608c2ecf20Sopenharmony_ci *
10618c2ecf20Sopenharmony_ci * Returns Zero on success, non-zero on failure
10628c2ecf20Sopenharmony_ci */
10638c2ecf20Sopenharmony_ciint cvmx_helper_initialize_packet_io_local(void)
10648c2ecf20Sopenharmony_ci{
10658c2ecf20Sopenharmony_ci	return cvmx_pko_initialize_local();
10668c2ecf20Sopenharmony_ci}
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci/**
10698c2ecf20Sopenharmony_ci * Return the link state of an IPD/PKO port as returned by
10708c2ecf20Sopenharmony_ci * auto negotiation. The result of this function may not match
10718c2ecf20Sopenharmony_ci * Octeon's link config if auto negotiation has changed since
10728c2ecf20Sopenharmony_ci * the last call to cvmx_helper_link_set().
10738c2ecf20Sopenharmony_ci *
10748c2ecf20Sopenharmony_ci * @ipd_port: IPD/PKO port to query
10758c2ecf20Sopenharmony_ci *
10768c2ecf20Sopenharmony_ci * Returns Link state
10778c2ecf20Sopenharmony_ci */
10788c2ecf20Sopenharmony_ciunion cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
10798c2ecf20Sopenharmony_ci{
10808c2ecf20Sopenharmony_ci	union cvmx_helper_link_info result;
10818c2ecf20Sopenharmony_ci	int interface = cvmx_helper_get_interface_num(ipd_port);
10828c2ecf20Sopenharmony_ci	int index = cvmx_helper_get_interface_index_num(ipd_port);
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	/* The default result will be a down link unless the code below
10858c2ecf20Sopenharmony_ci	   changes it */
10868c2ecf20Sopenharmony_ci	result.u64 = 0;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	if (index >= cvmx_helper_ports_on_interface(interface))
10898c2ecf20Sopenharmony_ci		return result;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
10928c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
10938c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
10948c2ecf20Sopenharmony_ci		/* Network links are not supported */
10958c2ecf20Sopenharmony_ci		break;
10968c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
10978c2ecf20Sopenharmony_ci		result = __cvmx_helper_xaui_link_get(ipd_port);
10988c2ecf20Sopenharmony_ci		break;
10998c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
11008c2ecf20Sopenharmony_ci		if (index == 0)
11018c2ecf20Sopenharmony_ci			result = __cvmx_helper_rgmii_link_get(ipd_port);
11028c2ecf20Sopenharmony_ci		else {
11038c2ecf20Sopenharmony_ci			WARN_ONCE(1, "Using deprecated link status - please update your DT");
11048c2ecf20Sopenharmony_ci			result.s.full_duplex = 1;
11058c2ecf20Sopenharmony_ci			result.s.link_up = 1;
11068c2ecf20Sopenharmony_ci			result.s.speed = 1000;
11078c2ecf20Sopenharmony_ci		}
11088c2ecf20Sopenharmony_ci		break;
11098c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
11108c2ecf20Sopenharmony_ci		result = __cvmx_helper_rgmii_link_get(ipd_port);
11118c2ecf20Sopenharmony_ci		break;
11128c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
11138c2ecf20Sopenharmony_ci		result = __cvmx_helper_spi_link_get(ipd_port);
11148c2ecf20Sopenharmony_ci		break;
11158c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
11168c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
11178c2ecf20Sopenharmony_ci		result = __cvmx_helper_sgmii_link_get(ipd_port);
11188c2ecf20Sopenharmony_ci		break;
11198c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
11208c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
11218c2ecf20Sopenharmony_ci		/* Network links are not supported */
11228c2ecf20Sopenharmony_ci		break;
11238c2ecf20Sopenharmony_ci	}
11248c2ecf20Sopenharmony_ci	return result;
11258c2ecf20Sopenharmony_ci}
11268c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_link_get);
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci/**
11298c2ecf20Sopenharmony_ci * Configure an IPD/PKO port for the specified link state. This
11308c2ecf20Sopenharmony_ci * function does not influence auto negotiation at the PHY level.
11318c2ecf20Sopenharmony_ci * The passed link state must always match the link state returned
11328c2ecf20Sopenharmony_ci * by cvmx_helper_link_get().
11338c2ecf20Sopenharmony_ci *
11348c2ecf20Sopenharmony_ci * @ipd_port:  IPD/PKO port to configure
11358c2ecf20Sopenharmony_ci * @link_info: The new link state
11368c2ecf20Sopenharmony_ci *
11378c2ecf20Sopenharmony_ci * Returns Zero on success, negative on failure
11388c2ecf20Sopenharmony_ci */
11398c2ecf20Sopenharmony_ciint cvmx_helper_link_set(int ipd_port, union cvmx_helper_link_info link_info)
11408c2ecf20Sopenharmony_ci{
11418c2ecf20Sopenharmony_ci	int result = -1;
11428c2ecf20Sopenharmony_ci	int interface = cvmx_helper_get_interface_num(ipd_port);
11438c2ecf20Sopenharmony_ci	int index = cvmx_helper_get_interface_index_num(ipd_port);
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	if (index >= cvmx_helper_ports_on_interface(interface))
11468c2ecf20Sopenharmony_ci		return -1;
11478c2ecf20Sopenharmony_ci
11488c2ecf20Sopenharmony_ci	switch (cvmx_helper_interface_get_mode(interface)) {
11498c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_DISABLED:
11508c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PCIE:
11518c2ecf20Sopenharmony_ci		break;
11528c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_XAUI:
11538c2ecf20Sopenharmony_ci		result = __cvmx_helper_xaui_link_set(ipd_port, link_info);
11548c2ecf20Sopenharmony_ci		break;
11558c2ecf20Sopenharmony_ci		/*
11568c2ecf20Sopenharmony_ci		 * RGMII/GMII/MII are all treated about the same. Most
11578c2ecf20Sopenharmony_ci		 * functions refer to these ports as RGMII.
11588c2ecf20Sopenharmony_ci		 */
11598c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_RGMII:
11608c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_GMII:
11618c2ecf20Sopenharmony_ci		result = __cvmx_helper_rgmii_link_set(ipd_port, link_info);
11628c2ecf20Sopenharmony_ci		break;
11638c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SPI:
11648c2ecf20Sopenharmony_ci		result = __cvmx_helper_spi_link_set(ipd_port, link_info);
11658c2ecf20Sopenharmony_ci		break;
11668c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_SGMII:
11678c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_PICMG:
11688c2ecf20Sopenharmony_ci		result = __cvmx_helper_sgmii_link_set(ipd_port, link_info);
11698c2ecf20Sopenharmony_ci		break;
11708c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_NPI:
11718c2ecf20Sopenharmony_ci	case CVMX_HELPER_INTERFACE_MODE_LOOP:
11728c2ecf20Sopenharmony_ci		break;
11738c2ecf20Sopenharmony_ci	}
11748c2ecf20Sopenharmony_ci	return result;
11758c2ecf20Sopenharmony_ci}
11768c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(cvmx_helper_link_set);
1177