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