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