cvmx-helper.c revision 259065
1254721Semaste/***********************license start*************** 2254721Semaste * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3254721Semaste * reserved. 4254721Semaste * 5254721Semaste * 6254721Semaste * Redistribution and use in source and binary forms, with or without 7254721Semaste * modification, are permitted provided that the following conditions are 8254721Semaste * met: 9254721Semaste * 10254721Semaste * * Redistributions of source code must retain the above copyright 11254721Semaste * notice, this list of conditions and the following disclaimer. 12254721Semaste * 13254721Semaste * * Redistributions in binary form must reproduce the above 14254721Semaste * copyright notice, this list of conditions and the following 15254721Semaste * disclaimer in the documentation and/or other materials provided 16254721Semaste * with the distribution. 17254721Semaste 18254721Semaste * * Neither the name of Cavium Inc. nor the names of 19254721Semaste * its contributors may be used to endorse or promote products 20254721Semaste * derived from this software without specific prior written 21254721Semaste * permission. 22254721Semaste 23254721Semaste * This Software, including technical data, may be subject to U.S. export control 24254721Semaste * laws, including the U.S. Export Administration Act and its associated 25254721Semaste * regulations, and may be subject to export or import regulations in other 26254721Semaste * countries. 27254721Semaste 28254721Semaste * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29254721Semaste * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30254721Semaste * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31254721Semaste * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32254721Semaste * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33254721Semaste * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34254721Semaste * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35254721Semaste * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36254721Semaste * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37254721Semaste * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38254721Semaste ***********************license end**************************************/ 39254721Semaste 40254721Semaste 41254721Semaste 42254721Semaste 43254721Semaste 44254721Semaste 45254721Semaste 46254721Semaste/** 47254721Semaste * @file 48254721Semaste * 49254721Semaste * Helper functions for common, but complicated tasks. 50254721Semaste * 51254721Semaste * <hr>$Revision: 70030 $<hr> 52254721Semaste */ 53254721Semaste#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54254721Semaste#include <linux/module.h> 55254721Semaste#include <asm/octeon/cvmx.h> 56254721Semaste#include <asm/octeon/cvmx-config.h> 57254721Semaste#include <asm/octeon/cvmx-bootmem.h> 58254721Semaste#include <asm/octeon/cvmx-sriox-defs.h> 59254721Semaste#include <asm/octeon/cvmx-npi-defs.h> 60254721Semaste#include <asm/octeon/cvmx-mio-defs.h> 61254721Semaste#include <asm/octeon/cvmx-pexp-defs.h> 62254721Semaste#include <asm/octeon/cvmx-pip-defs.h> 63254721Semaste#include <asm/octeon/cvmx-asxx-defs.h> 64254721Semaste#include <asm/octeon/cvmx-gmxx-defs.h> 65254721Semaste#include <asm/octeon/cvmx-smix-defs.h> 66254721Semaste#include <asm/octeon/cvmx-dbg-defs.h> 67254721Semaste#include <asm/octeon/cvmx-sso-defs.h> 68254721Semaste 69254721Semaste#include <asm/octeon/cvmx-gmx.h> 70254721Semaste#include <asm/octeon/cvmx-fpa.h> 71254721Semaste#include <asm/octeon/cvmx-pip.h> 72254721Semaste#include <asm/octeon/cvmx-pko.h> 73254721Semaste#include <asm/octeon/cvmx-ipd.h> 74254721Semaste#include <asm/octeon/cvmx-spi.h> 75263367Semaste#include <asm/octeon/cvmx-clock.h> 76254721Semaste#include <asm/octeon/cvmx-helper.h> 77254721Semaste#include <asm/octeon/cvmx-helper-board.h> 78254721Semaste#include <asm/octeon/cvmx-helper-errata.h> 79254721Semaste#include <asm/octeon/cvmx-helper-cfg.h> 80254721Semaste#else 81254721Semaste#if !defined(__FreeBSD__) || !defined(_KERNEL) 82254721Semaste#include "executive-config.h" 83254721Semaste#endif 84254721Semaste#include "cvmx.h" 85254721Semaste#include "cvmx-sysinfo.h" 86254721Semaste#include "cvmx-bootmem.h" 87254721Semaste#include "cvmx-version.h" 88254721Semaste#include "cvmx-helper-check-defines.h" 89254721Semaste#include "cvmx-gmx.h" 90254721Semaste#if !defined(__FreeBSD__) || !defined(_KERNEL) 91254721Semaste#include "cvmx-error.h" 92254721Semaste#include "cvmx-config.h" 93254721Semaste#endif 94254721Semaste 95254721Semaste#include "cvmx-fpa.h" 96254721Semaste#include "cvmx-pip.h" 97254721Semaste#include "cvmx-pko.h" 98254721Semaste#include "cvmx-ipd.h" 99254721Semaste#include "cvmx-spi.h" 100254721Semaste#include "cvmx-helper.h" 101254721Semaste#include "cvmx-helper-board.h" 102254721Semaste#include "cvmx-helper-errata.h" 103254721Semaste#include "cvmx-helper-cfg.h" 104254721Semaste#endif 105254721Semaste 106254721Semaste 107254721Semaste#ifdef CVMX_ENABLE_PKO_FUNCTIONS 108263367Semaste 109254721Semaste/** 110254721Semaste * cvmx_override_pko_queue_priority(int pko_port, uint64_t 111254721Semaste * priorities[16]) is a function pointer. It is meant to allow 112254721Semaste * customization of the PKO queue priorities based on the port 113254721Semaste * number. Users should set this pointer to a function before 114254721Semaste * calling any cvmx-helper operations. 115254721Semaste */ 116254721SemasteCVMX_SHARED void (*cvmx_override_pko_queue_priority)(int ipd_port, 117254721Semaste uint64_t *priorities) = NULL; 118254721Semaste#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 119254721SemasteEXPORT_SYMBOL(cvmx_override_pko_queue_priority); 120254721Semaste#endif 121263367Semaste 122254721Semaste/** 123254721Semaste * cvmx_override_ipd_port_setup(int ipd_port) is a function 124254721Semaste * pointer. It is meant to allow customization of the IPD 125254721Semaste * port/port kind setup before packet input/output comes online. 126254721Semaste * It is called after cvmx-helper does the default IPD configuration, 127254721Semaste * but before IPD is enabled. Users should set this pointer to a 128254721Semaste * function before calling any cvmx-helper operations. 129263367Semaste */ 130263367SemasteCVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL; 131254721Semaste 132254721Semaste/** 133263367Semaste * Return the number of interfaces the chip has. Each interface 134263367Semaste * may have multiple ports. Most chips support two interfaces, 135263367Semaste * but the CNX0XX and CNX1XX are exceptions. These only support 136263367Semaste * one interface. 137263367Semaste * 138254721Semaste * @return Number of interfaces on chip 139254721Semaste */ 140254721Semasteint cvmx_helper_get_number_of_interfaces(void) 141254721Semaste{ 142263367Semaste switch (cvmx_sysinfo_get()->board_type) { 143263367Semaste#if defined(OCTEON_VENDOR_LANNER) 144263367Semaste case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 145254721Semaste return 2; 146254721Semaste case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 147254721Semaste return 1; 148254721Semaste#endif 149254721Semaste#if defined(OCTEON_VENDOR_RADISYS) 150254721Semaste case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE: 151254721Semaste return 2; 152263367Semaste#endif 153263367Semaste default: 154263367Semaste break; 155263367Semaste } 156263367Semaste 157254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 158254721Semaste return 9; 159254721Semaste else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 160254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 161254721Semaste return 7; 162254721Semaste else 163254721Semaste return 8; 164254721Semaste else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 165254721Semaste return 6; 166254721Semaste else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN61XX)) 167254721Semaste return 4; 168254721Semaste else 169254721Semaste return 3; 170254721Semaste} 171254721Semaste#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 172254721SemasteEXPORT_SYMBOL(cvmx_helper_get_number_of_interfaces); 173254721Semaste#endif 174254721Semaste 175254721Semaste 176254721Semaste/** 177254721Semaste * Return the number of ports on an interface. Depending on the 178254721Semaste * chip and configuration, this can be 1-16. A value of 0 179254721Semaste * specifies that the interface doesn't exist or isn't usable. 180254721Semaste * 181254721Semaste * @param interface Interface to get the port count for 182254721Semaste * 183254721Semaste * @return Number of ports on interface. Can be Zero. 184254721Semaste */ 185254721Semasteint cvmx_helper_ports_on_interface(int interface) 186254721Semaste{ 187254721Semaste if (octeon_has_feature(OCTEON_FEATURE_PKND)) 188254721Semaste return cvmx_helper_interface_enumerate(interface); 189254721Semaste else 190254721Semaste return __cvmx_helper_get_num_ipd_ports(interface); 191254721Semaste} 192254721Semaste#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 193254721SemasteEXPORT_SYMBOL(cvmx_helper_ports_on_interface); 194254721Semaste#endif 195254721Semaste 196254721Semaste 197254721Semaste/** 198254721Semaste * Get the operating mode of an interface. Depending on the Octeon 199254721Semaste * chip and configuration, this function returns an enumeration 200254721Semaste * of the type of packet I/O supported by an interface. 201254721Semaste * 202254721Semaste * @param interface Interface to probe 203254721Semaste * 204254721Semaste * @return Mode of the interface. Unknown or unsupported interfaces return 205254721Semaste * DISABLED. 206254721Semaste */ 207254721Semastecvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) 208254721Semaste{ 209254721Semaste cvmx_gmxx_inf_mode_t mode; 210254721Semaste 211254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 212254721Semaste { 213254721Semaste cvmx_mio_qlmx_cfg_t qlm_cfg; 214254721Semaste switch(interface) 215254721Semaste { 216254721Semaste case 0: 217254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 218254721Semaste /* QLM is disabled when QLM SPD is 15. */ 219254721Semaste if (qlm_cfg.s.qlm_spd == 15) 220254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 221254721Semaste 222254721Semaste if (qlm_cfg.s.qlm_cfg == 7) 223254721Semaste return CVMX_HELPER_INTERFACE_MODE_RXAUI; 224254721Semaste else if (qlm_cfg.s.qlm_cfg == 2) 225254721Semaste return CVMX_HELPER_INTERFACE_MODE_SGMII; 226254721Semaste else if (qlm_cfg.s.qlm_cfg == 3) 227263365Semaste return CVMX_HELPER_INTERFACE_MODE_XAUI; 228263365Semaste else 229263365Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 230263365Semaste break; 231263365Semaste case 1: 232254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 233254721Semaste /* QLM is disabled when QLM SPD is 15. */ 234254721Semaste if (qlm_cfg.s.qlm_spd == 15) 235254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 236254721Semaste 237254721Semaste if (qlm_cfg.s.qlm_cfg == 7) 238254721Semaste return CVMX_HELPER_INTERFACE_MODE_RXAUI; 239254721Semaste else 240254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 241254721Semaste break; 242254721Semaste case 2: 243254721Semaste case 3: 244254721Semaste case 4: 245254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface)); 246254721Semaste /* QLM is disabled when QLM SPD is 15. */ 247254721Semaste if (qlm_cfg.s.qlm_spd == 15) 248254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 249254721Semaste 250254721Semaste if (qlm_cfg.s.qlm_cfg == 2) 251254721Semaste return CVMX_HELPER_INTERFACE_MODE_SGMII; 252254721Semaste else if (qlm_cfg.s.qlm_cfg == 3) 253254721Semaste return CVMX_HELPER_INTERFACE_MODE_XAUI; 254254721Semaste else 255254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 256254721Semaste break; 257254721Semaste case 5: 258254721Semaste case 6: 259254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface - 4)); 260254721Semaste /* QLM is disabled when QLM SPD is 15. */ 261254721Semaste if (qlm_cfg.s.qlm_spd == 15) 262254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 263254721Semaste 264254721Semaste if (qlm_cfg.s.qlm_cfg == 1) 265254721Semaste { 266254721Semaste return CVMX_HELPER_INTERFACE_MODE_ILK; 267254721Semaste } 268254721Semaste else 269254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 270254721Semaste break; 271254721Semaste case 7: 272254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3)); 273254721Semaste /* QLM is disabled when QLM SPD is 15. */ 274254721Semaste if (qlm_cfg.s.qlm_spd == 15) 275254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 276254721Semaste else if (qlm_cfg.s.qlm_cfg != 0) 277254721Semaste { 278254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 279254721Semaste if (qlm_cfg.s.qlm_cfg != 0) 280254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 281254721Semaste } 282254721Semaste return CVMX_HELPER_INTERFACE_MODE_NPI; 283254721Semaste break; 284254721Semaste case 8: 285254721Semaste return CVMX_HELPER_INTERFACE_MODE_LOOP; 286254721Semaste break; 287254721Semaste default: 288254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 289254721Semaste break; 290254721Semaste } 291254721Semaste } 292254721Semaste 293254721Semaste if (interface == 2) 294254721Semaste return CVMX_HELPER_INTERFACE_MODE_NPI; 295254721Semaste 296254721Semaste if (interface == 3) 297254721Semaste { 298254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN56XX) 299254721Semaste || OCTEON_IS_MODEL(OCTEON_CN52XX) 300254721Semaste || OCTEON_IS_MODEL(OCTEON_CN6XXX) 301254721Semaste || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 302254721Semaste return CVMX_HELPER_INTERFACE_MODE_LOOP; 303254721Semaste else 304254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 305254721Semaste } 306254721Semaste 307254721Semaste /* Only present in CN63XX & CN66XX Octeon model */ 308254721Semaste if ((OCTEON_IS_MODEL(OCTEON_CN63XX) && (interface == 4 || interface == 5)) 309254721Semaste || (OCTEON_IS_MODEL(OCTEON_CN66XX) && interface >= 4 && interface <= 7)) 310254721Semaste { 311254721Semaste cvmx_sriox_status_reg_t sriox_status_reg; 312254721Semaste 313254721Semaste /* cn66xx pass1.0 has only 2 SRIO interfaces. */ 314254721Semaste if ((interface == 5 || interface == 7) && OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 315254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 316254721Semaste 317254721Semaste sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(interface-4)); 318254721Semaste if (sriox_status_reg.s.srio) 319254721Semaste return CVMX_HELPER_INTERFACE_MODE_SRIO; 320254721Semaste else 321254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 322254721Semaste } 323254721Semaste 324254721Semaste /* Interface 5 always disabled in CN66XX */ 325254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 326254721Semaste { 327254721Semaste cvmx_mio_qlmx_cfg_t mio_qlm_cfg; 328254721Semaste 329254721Semaste /* QLM2 is SGMII0 and QLM1 is SGMII1 */ 330254721Semaste if (interface == 0) 331254721Semaste mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); 332254721Semaste else if (interface == 1) 333254721Semaste mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 334254721Semaste else 335254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 336254721Semaste 337254721Semaste if (mio_qlm_cfg.s.qlm_spd == 15) 338254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 339254721Semaste 340254721Semaste if (mio_qlm_cfg.s.qlm_cfg == 9) 341254721Semaste return CVMX_HELPER_INTERFACE_MODE_SGMII; 342254721Semaste else if (mio_qlm_cfg.s.qlm_cfg == 11) 343254721Semaste return CVMX_HELPER_INTERFACE_MODE_XAUI; 344254721Semaste else 345254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 346254721Semaste } 347254721Semaste else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 348254721Semaste { 349254721Semaste cvmx_mio_qlmx_cfg_t qlm_cfg; 350254721Semaste 351254721Semaste if (interface == 0) 352254721Semaste { 353254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); 354254721Semaste if (qlm_cfg.s.qlm_cfg == 2) 355254721Semaste return CVMX_HELPER_INTERFACE_MODE_SGMII; 356254721Semaste else if (qlm_cfg.s.qlm_cfg == 3) 357254721Semaste return CVMX_HELPER_INTERFACE_MODE_XAUI; 358254721Semaste else 359254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 360254721Semaste } 361254721Semaste else if (interface == 1) 362254721Semaste { 363254721Semaste /* If QLM 1 is PEV0/PEM1 mode, them QLM0 cannot be SGMII/XAUI */ 364254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 365254721Semaste if (qlm_cfg.s.qlm_cfg == 1) 366254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 367254721Semaste 368254721Semaste qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 369254721Semaste if (qlm_cfg.s.qlm_cfg == 2) 370254721Semaste return CVMX_HELPER_INTERFACE_MODE_SGMII; 371254721Semaste else if (qlm_cfg.s.qlm_cfg == 3) 372254721Semaste return CVMX_HELPER_INTERFACE_MODE_XAUI; 373254721Semaste else 374254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 375254721Semaste } 376254721Semaste } 377254721Semaste 378254721Semaste if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1) 379254721Semaste { 380254721Semaste /* Lie about interface type of CN3005 board. This board has a switch on port 1 like 381254721Semaste ** the other evaluation boards, but it is connected over RGMII instead of GMII. Report 382254721Semaste ** GMII mode so that the speed is forced to 1 Gbit full duplex. Other than some initial configuration 383254721Semaste ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes. 384254721Semaste */ 385254721Semaste return CVMX_HELPER_INTERFACE_MODE_GMII; 386254721Semaste } 387254721Semaste 388254721Semaste /* Interface 1 is always disabled on CN31XX and CN30XX */ 389254721Semaste if ((interface == 1) 390254721Semaste && (OCTEON_IS_MODEL(OCTEON_CN31XX) 391254721Semaste || OCTEON_IS_MODEL(OCTEON_CN30XX) 392254721Semaste || OCTEON_IS_MODEL(OCTEON_CN50XX) 393254721Semaste || OCTEON_IS_MODEL(OCTEON_CN52XX) 394254721Semaste || OCTEON_IS_MODEL(OCTEON_CN63XX) 395254721Semaste || OCTEON_IS_MODEL(OCTEON_CNF71XX))) 396254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 397254721Semaste 398254721Semaste mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 399254721Semaste 400254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 401254721Semaste { 402254721Semaste switch(mode.cn56xx.mode) 403254721Semaste { 404254721Semaste case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 405254721Semaste case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 406254721Semaste case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII; 407254721Semaste case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG; 408254721Semaste default:return CVMX_HELPER_INTERFACE_MODE_DISABLED; 409254721Semaste } 410254721Semaste } 411254721Semaste else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 412254721Semaste { 413254721Semaste switch(mode.cn63xx.mode) 414254721Semaste { 415254721Semaste case 0: return CVMX_HELPER_INTERFACE_MODE_SGMII; 416254721Semaste case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 417254721Semaste default: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 418254721Semaste } 419254721Semaste } 420254721Semaste else 421254721Semaste { 422254721Semaste if (!mode.s.en) 423254721Semaste return CVMX_HELPER_INTERFACE_MODE_DISABLED; 424254721Semaste 425254721Semaste if (mode.s.type) 426254721Semaste { 427254721Semaste if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) 428254721Semaste return CVMX_HELPER_INTERFACE_MODE_SPI; 429254721Semaste else 430254721Semaste return CVMX_HELPER_INTERFACE_MODE_GMII; 431254721Semaste } 432254721Semaste else 433254721Semaste return CVMX_HELPER_INTERFACE_MODE_RGMII; 434254721Semaste } 435254721Semaste} 436254721Semaste#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 437254721SemasteEXPORT_SYMBOL(cvmx_helper_interface_get_mode); 438254721Semaste#endif 439254721Semaste 440254721Semaste/** 441254721Semaste * @INTERNAL 442254721Semaste * Configure the IPD/PIP tagging and QoS options for a specific 443254721Semaste * port. This function determines the POW work queue entry 444254721Semaste * contents for a port. The setup performed here is controlled by 445254721Semaste * the defines in executive-config.h. 446254721Semaste * 447254721Semaste * @param ipd_port Port/Port kind to configure. This follows the IPD numbering, 448254721Semaste * not the per interface numbering 449254721Semaste * 450254721Semaste * @return Zero on success, negative on failure 451254721Semaste */ 452254721Semastestatic int __cvmx_helper_port_setup_ipd(int ipd_port) 453254721Semaste{ 454254721Semaste cvmx_pip_prt_cfgx_t port_config; 455254721Semaste cvmx_pip_prt_tagx_t tag_config; 456254721Semaste 457254721Semaste if (octeon_has_feature(OCTEON_FEATURE_PKND)) 458254721Semaste { 459254721Semaste int interface, index, pknd; 460254721Semaste cvmx_pip_prt_cfgbx_t prt_cfgbx; 461254721Semaste 462254721Semaste interface = cvmx_helper_get_interface_num(ipd_port); 463254721Semaste index = cvmx_helper_get_interface_index_num(ipd_port); 464254721Semaste pknd = cvmx_helper_get_pknd(interface, index); 465254721Semaste 466254721Semaste port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd)); 467254721Semaste tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(pknd)); 468254721Semaste 469254721Semaste port_config.s.qos = pknd & 0x7; 470254721Semaste 471254721Semaste /* Default BPID to use for packets on this port-kind */ 472254721Semaste prt_cfgbx.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGBX(pknd)); 473254721Semaste prt_cfgbx.s.bpid = pknd; 474254721Semaste cvmx_write_csr(CVMX_PIP_PRT_CFGBX(pknd), prt_cfgbx.u64); 475254721Semaste } 476254721Semaste else 477254721Semaste { 478254721Semaste port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 479254721Semaste tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); 480254721Semaste 481254721Semaste /* Have each port go to a different POW queue */ 482254721Semaste port_config.s.qos = ipd_port & 0x7; 483254721Semaste } 484254721Semaste 485254721Semaste /* Process the headers and place the IP header in the work queue */ 486254721Semaste port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; 487254721Semaste 488254721Semaste tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; 489254721Semaste tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; 490254721Semaste tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; 491254721Semaste tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; 492263367Semaste tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; 493254721Semaste tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; 494254721Semaste tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; 495254721Semaste tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; 496254721Semaste tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; 497254721Semaste tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; 498263367Semaste tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; 499263367Semaste tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 500254721Semaste tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 501263367Semaste tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 502254721Semaste tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 503263367Semaste tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 504263367Semaste /* Put all packets in group 0. Other groups can be used by the app */ 505254721Semaste tag_config.s.grp = 0; 506263367Semaste 507254721Semaste cvmx_pip_config_port(ipd_port, port_config, tag_config); 508254721Semaste 509254721Semaste /* Give the user a chance to override our setting for each port */ 510254721Semaste if (cvmx_override_ipd_port_setup) 511254721Semaste cvmx_override_ipd_port_setup(ipd_port); 512254721Semaste 513263367Semaste return 0; 514263367Semaste} 515263367Semaste 516263367Semaste/** 517263367Semaste * Enable or disable FCS stripping for all the ports on an interface. 518263367Semaste * 519263367Semaste * @param interface 520254721Semaste * @param nports number of ports 521254721Semaste * @param has_fcs 0 for disable and !0 for enable 522254721Semaste */ 523254721Semastestatic int cvmx_helper_fcs_op(int interface, int nports, int has_fcs) 524254721Semaste{ 525254721Semaste uint64_t port_bit; 526254721Semaste int index; 527263367Semaste int pknd; 528254721Semaste cvmx_pip_sub_pkind_fcsx_t pkind_fcsx; 529263367Semaste cvmx_pip_prt_cfgx_t port_cfg; 530263367Semaste 531263367Semaste if (!octeon_has_feature(OCTEON_FEATURE_PKND)) 532263367Semaste return 0; 533263367Semaste 534263367Semaste port_bit = 0; 535263367Semaste for (index = 0; index < nports; index++) 536263367Semaste port_bit |= ((uint64_t)1 << cvmx_helper_get_pknd(interface, index)); 537263367Semaste 538263367Semaste pkind_fcsx.u64 = cvmx_read_csr(CVMX_PIP_SUB_PKIND_FCSX(0)); 539263367Semaste if (has_fcs) 540263367Semaste pkind_fcsx.s.port_bit |= port_bit; 541263367Semaste else 542263367Semaste pkind_fcsx.s.port_bit &= ~port_bit; 543263367Semaste cvmx_write_csr(CVMX_PIP_SUB_PKIND_FCSX(0), pkind_fcsx.u64); 544263367Semaste 545254721Semaste for (pknd = 0; pknd < 64; pknd++) 546254721Semaste { 547254721Semaste if ((1ull << pknd) & port_bit) 548254721Semaste { 549254721Semaste port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd)); 550254721Semaste port_cfg.s.crc_en = (has_fcs) ? 1 : 0; 551254721Semaste cvmx_write_csr(CVMX_PIP_PRT_CFGX(pknd), port_cfg.u64); 552254721Semaste } 553254721Semaste } 554254721Semaste 555254721Semaste return 0; 556} 557 558/** 559 * Determine the actual number of hardware ports connected to an 560 * interface. It doesn't setup the ports or enable them. 561 * 562 * @param interface Interface to enumerate 563 * 564 * @return The number of ports on the interface, negative on failure 565 */ 566int cvmx_helper_interface_enumerate(int interface) 567{ 568 switch (cvmx_helper_interface_get_mode(interface)) { 569 /* XAUI is a single high speed port */ 570 case CVMX_HELPER_INTERFACE_MODE_XAUI: 571 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 572 return __cvmx_helper_xaui_enumerate(interface); 573 /* RGMII/GMII/MII are all treated about the same. Most functions 574 refer to these ports as RGMII */ 575 case CVMX_HELPER_INTERFACE_MODE_RGMII: 576 case CVMX_HELPER_INTERFACE_MODE_GMII: 577 return __cvmx_helper_rgmii_enumerate(interface); 578 /* SPI4 can have 1-16 ports depending on the device at the other end */ 579 case CVMX_HELPER_INTERFACE_MODE_SPI: 580 return __cvmx_helper_spi_enumerate(interface); 581 /* SGMII can have 1-4 ports depending on how many are hooked up */ 582 case CVMX_HELPER_INTERFACE_MODE_SGMII: 583 case CVMX_HELPER_INTERFACE_MODE_PICMG: 584 return __cvmx_helper_sgmii_enumerate(interface); 585 /* PCI target Network Packet Interface */ 586 case CVMX_HELPER_INTERFACE_MODE_NPI: 587 return __cvmx_helper_npi_enumerate(interface); 588 /* Special loopback only ports. These are not the same 589 * as other ports in loopback mode */ 590 case CVMX_HELPER_INTERFACE_MODE_LOOP: 591 return __cvmx_helper_loop_enumerate(interface); 592 /* SRIO has 2^N ports, where N is number of interfaces */ 593 case CVMX_HELPER_INTERFACE_MODE_SRIO: 594 return __cvmx_helper_srio_enumerate(interface); 595 596 case CVMX_HELPER_INTERFACE_MODE_ILK: 597 return __cvmx_helper_ilk_enumerate(interface); 598 /* These types don't support ports to IPD/PKO */ 599 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 600 case CVMX_HELPER_INTERFACE_MODE_PCIE: 601 default: 602 return 0; 603 } 604} 605 606/** 607 * This function probes an interface to determine the actual number of 608 * hardware ports connected to it. It does some setup the ports but 609 * doesn't enable them. The main goal here is to set the global 610 * interface_port_count[interface] correctly. Final hardware setup of 611 * the ports will be performed later. 612 * 613 * @param interface Interface to probe 614 * 615 * @return Zero on success, negative on failure 616 */ 617int cvmx_helper_interface_probe(int interface) 618{ 619 /* At this stage in the game we don't want packets to be moving yet. 620 The following probe calls should perform hardware setup 621 needed to determine port counts. Receive must still be disabled */ 622 int nports; 623 int has_fcs; 624 enum cvmx_pko_padding padding = CVMX_PKO_PADDING_NONE; 625 626 nports = -1; 627 has_fcs = 0; 628 switch (cvmx_helper_interface_get_mode(interface)) 629 { 630 /* These types don't support ports to IPD/PKO */ 631 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 632 case CVMX_HELPER_INTERFACE_MODE_PCIE: 633 nports = 0; 634 break; 635 /* XAUI is a single high speed port */ 636 case CVMX_HELPER_INTERFACE_MODE_XAUI: 637 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 638 nports = __cvmx_helper_xaui_probe(interface); 639 has_fcs = 1; 640 padding = CVMX_PKO_PADDING_60; 641 break; 642 /* RGMII/GMII/MII are all treated about the same. Most functions 643 refer to these ports as RGMII */ 644 case CVMX_HELPER_INTERFACE_MODE_RGMII: 645 case CVMX_HELPER_INTERFACE_MODE_GMII: 646 nports = __cvmx_helper_rgmii_probe(interface); 647 padding = CVMX_PKO_PADDING_60; 648 break; 649 /* SPI4 can have 1-16 ports depending on the device at the other end */ 650 case CVMX_HELPER_INTERFACE_MODE_SPI: 651 nports = __cvmx_helper_spi_probe(interface); 652 padding = CVMX_PKO_PADDING_60; 653 break; 654 /* SGMII can have 1-4 ports depending on how many are hooked up */ 655 case CVMX_HELPER_INTERFACE_MODE_SGMII: 656 padding = CVMX_PKO_PADDING_60; 657 case CVMX_HELPER_INTERFACE_MODE_PICMG: 658 nports = __cvmx_helper_sgmii_probe(interface); 659 has_fcs = 1; 660 break; 661 /* PCI target Network Packet Interface */ 662 case CVMX_HELPER_INTERFACE_MODE_NPI: 663 nports = __cvmx_helper_npi_probe(interface); 664 break; 665 /* Special loopback only ports. These are not the same as other ports 666 in loopback mode */ 667 case CVMX_HELPER_INTERFACE_MODE_LOOP: 668 nports = __cvmx_helper_loop_probe(interface); 669 break; 670 /* SRIO has 2^N ports, where N is number of interfaces */ 671 case CVMX_HELPER_INTERFACE_MODE_SRIO: 672 nports = __cvmx_helper_srio_probe(interface); 673 break; 674 case CVMX_HELPER_INTERFACE_MODE_ILK: 675 nports = __cvmx_helper_ilk_probe(interface); 676 has_fcs = 1; 677 padding = CVMX_PKO_PADDING_60; 678 break; 679 } 680 681 if (nports == -1) 682 return -1; 683 684 if (!octeon_has_feature(OCTEON_FEATURE_PKND)) 685 has_fcs = 0; 686 687 nports = __cvmx_helper_board_interface_probe(interface, nports); 688 __cvmx_helper_init_interface(interface, nports, has_fcs, padding); 689 cvmx_helper_fcs_op(interface, nports, has_fcs); 690 691 /* Make sure all global variables propagate to other cores */ 692 CVMX_SYNCWS; 693 694 return 0; 695} 696 697 698/** 699 * @INTERNAL 700 * Setup the IPD/PIP for the ports on an interface. Packet 701 * classification and tagging are set for every port on the 702 * interface. The number of ports on the interface must already 703 * have been probed. 704 * 705 * @param interface Interface to setup IPD/PIP for 706 * 707 * @return Zero on success, negative on failure 708 */ 709static int __cvmx_helper_interface_setup_ipd(int interface) 710{ 711 712 cvmx_helper_interface_mode_t mode; 713 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 714 int num_ports = cvmx_helper_ports_on_interface(interface); 715 int delta; 716 717 if (num_ports == CVMX_HELPER_CFG_INVALID_VALUE) 718 return 0; 719 720 mode = cvmx_helper_interface_get_mode(interface); 721 722 if (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) 723 __cvmx_helper_loop_enable(interface); 724 725 delta = 1; 726 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 727 { 728 if (mode == CVMX_HELPER_INTERFACE_MODE_SGMII) 729 delta = 16; 730 } 731 732 while (num_ports--) 733 { 734 __cvmx_helper_port_setup_ipd(ipd_port); 735 ipd_port += delta; 736 } 737 738 return 0; 739} 740 741 742/** 743 * @INTERNAL 744 * Setup global setting for IPD/PIP not related to a specific 745 * interface or port. This must be called before IPD is enabled. 746 * 747 * @return Zero on success, negative on failure. 748 */ 749static int __cvmx_helper_global_setup_ipd(void) 750{ 751#ifndef CVMX_HELPER_IPD_DRAM_MODE 752#define CVMX_HELPER_IPD_DRAM_MODE CVMX_IPD_OPC_MODE_STT 753#endif 754 /* Setup the global packet input options */ 755 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8, 756 CVMX_HELPER_FIRST_MBUFF_SKIP/8, 757 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8, 758 (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 759 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 760 CVMX_FPA_WQE_POOL, 761 CVMX_HELPER_IPD_DRAM_MODE, 762 1); 763 return 0; 764} 765 766 767/** 768 * @INTERNAL 769 * Setup the PKO for the ports on an interface. The number of 770 * queues per port and the priority of each PKO output queue 771 * is set here. PKO must be disabled when this function is called. 772 * 773 * @param interface Interface to setup PKO for 774 * 775 * @return Zero on success, negative on failure 776 */ 777static int __cvmx_helper_interface_setup_pko(int interface) 778{ 779 /* Each packet output queue has an associated priority. The higher the 780 priority, the more often it can send a packet. A priority of 8 means 781 it can send in all 8 rounds of contention. We're going to make each 782 queue one less than the last. 783 The vector of priorities has been extended to support CN5xxx CPUs, 784 where up to 16 queues can be associated to a port. 785 To keep backward compatibility we don't change the initial 8 786 priorities and replicate them in the second half. 787 With per-core PKO queues (PKO lockless operation) all queues have 788 the same priority. */ 789 /* uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; */ 790 uint64_t priorities[16] = {[0 ... 15] = 8}; 791 792 /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet 793 classification, tagging and output priorities are set */ 794 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 795 int num_ports = cvmx_helper_ports_on_interface(interface); 796 while (num_ports--) 797 { 798 /* Give the user a chance to override the per queue priorities */ 799 if (cvmx_override_pko_queue_priority) 800 cvmx_override_pko_queue_priority(ipd_port, priorities); 801 802 cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0), 803 cvmx_pko_get_num_queues(ipd_port), priorities); 804 ipd_port++; 805 } 806 return 0; 807} 808 809 810/** 811 * @INTERNAL 812 * Setup global setting for PKO not related to a specific 813 * interface or port. This must be called before PKO is enabled. 814 * 815 * @return Zero on success, negative on failure. 816 */ 817static int __cvmx_helper_global_setup_pko(void) 818{ 819 /* Disable tagwait FAU timeout. This needs to be done before anyone might 820 start packet output using tags */ 821 cvmx_iob_fau_timeout_t fau_to; 822 fau_to.u64 = 0; 823 fau_to.s.tout_val = 0xfff; 824 fau_to.s.tout_enb = 0; 825 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 826 827 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { 828 cvmx_pko_reg_min_pkt_t min_pkt; 829 830 min_pkt.u64 = 0; 831 min_pkt.s.size1 = 59; 832 min_pkt.s.size2 = 59; 833 min_pkt.s.size3 = 59; 834 min_pkt.s.size4 = 59; 835 min_pkt.s.size5 = 59; 836 min_pkt.s.size6 = 59; 837 min_pkt.s.size7 = 59; 838 cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64); 839 } 840 841 return 0; 842} 843 844 845/** 846 * @INTERNAL 847 * Setup global backpressure setting. 848 * 849 * @return Zero on success, negative on failure 850 */ 851static int __cvmx_helper_global_setup_backpressure(void) 852{ 853#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 854 /* Disable backpressure if configured to do so */ 855 /* Disable backpressure (pause frame) generation */ 856 int num_interfaces = cvmx_helper_get_number_of_interfaces(); 857 int interface; 858 for (interface=0; interface<num_interfaces; interface++) 859 { 860 switch (cvmx_helper_interface_get_mode(interface)) 861 { 862 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 863 case CVMX_HELPER_INTERFACE_MODE_PCIE: 864 case CVMX_HELPER_INTERFACE_MODE_SRIO: 865 case CVMX_HELPER_INTERFACE_MODE_ILK: 866 case CVMX_HELPER_INTERFACE_MODE_NPI: 867 case CVMX_HELPER_INTERFACE_MODE_LOOP: 868 case CVMX_HELPER_INTERFACE_MODE_XAUI: 869 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 870 break; 871 case CVMX_HELPER_INTERFACE_MODE_RGMII: 872 case CVMX_HELPER_INTERFACE_MODE_GMII: 873 case CVMX_HELPER_INTERFACE_MODE_SPI: 874 case CVMX_HELPER_INTERFACE_MODE_SGMII: 875 case CVMX_HELPER_INTERFACE_MODE_PICMG: 876 cvmx_gmx_set_backpressure_override(interface, 0xf); 877 break; 878 } 879 } 880 //cvmx_dprintf("Disabling backpressure\n"); 881#endif 882 883 return 0; 884} 885 886/** 887 * @INTERNAL 888 * Verify the per port IPD backpressure is aligned properly. 889 * @return Zero if working, non zero if misaligned 890 */ 891static int __cvmx_helper_backpressure_is_misaligned(void) 892{ 893 uint64_t ipd_int_enb; 894 cvmx_ipd_ctl_status_t ipd_reg; 895 uint64_t bp_status0; 896 uint64_t bp_status1; 897 const int port0 = 0; 898 const int port1 = 16; 899 cvmx_helper_interface_mode_t mode0 = cvmx_helper_interface_get_mode(0); 900 cvmx_helper_interface_mode_t mode1 = cvmx_helper_interface_get_mode(1); 901 902 /* Disable error interrupts while we check backpressure */ 903 ipd_int_enb = cvmx_read_csr(CVMX_IPD_INT_ENB); 904 cvmx_write_csr(CVMX_IPD_INT_ENB, 0); 905 906 /* Enable per port backpressure */ 907 ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 908 ipd_reg.s.pbp_en = 1; 909 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); 910 911 if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 912 { 913 /* Enable backpressure for port with a zero threshold */ 914 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 1<<17); 915 /* Add 1000 to the page count to simulate packets coming in */ 916 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | 1000); 917 } 918 919 if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 920 { 921 /* Enable backpressure for port with a zero threshold */ 922 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 1<<17); 923 /* Add 1000 to the page count to simulate packets coming in */ 924 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | 1000); 925 } 926 927 /* Wait 500 cycles for the BP to update */ 928 cvmx_wait(500); 929 930 /* Read the BP state from the debug select register */ 931 switch (mode0) 932 { 933 case CVMX_HELPER_INTERFACE_MODE_SPI: 934 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9004); 935 bp_status0 = cvmx_read_csr(CVMX_DBG_DATA); 936 bp_status0 = 0xffff & ~bp_status0; 937 break; 938 case CVMX_HELPER_INTERFACE_MODE_RGMII: 939 case CVMX_HELPER_INTERFACE_MODE_GMII: 940 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x0e00); 941 bp_status0 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 942 break; 943 case CVMX_HELPER_INTERFACE_MODE_XAUI: 944 case CVMX_HELPER_INTERFACE_MODE_SGMII: 945 case CVMX_HELPER_INTERFACE_MODE_PICMG: 946 cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x0e00); 947 bp_status0 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 948 break; 949 default: 950 bp_status0 = 1<<port0; 951 break; 952 } 953 954 /* Read the BP state from the debug select register */ 955 switch (mode1) 956 { 957 case CVMX_HELPER_INTERFACE_MODE_SPI: 958 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9804); 959 bp_status1 = cvmx_read_csr(CVMX_DBG_DATA); 960 bp_status1 = 0xffff & ~bp_status1; 961 break; 962 case CVMX_HELPER_INTERFACE_MODE_RGMII: 963 case CVMX_HELPER_INTERFACE_MODE_GMII: 964 cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x1600); 965 bp_status1 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 966 break; 967 case CVMX_HELPER_INTERFACE_MODE_XAUI: 968 case CVMX_HELPER_INTERFACE_MODE_SGMII: 969 case CVMX_HELPER_INTERFACE_MODE_PICMG: 970 cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x1600); 971 bp_status1 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 972 break; 973 default: 974 bp_status1 = 1<<(port1-16); 975 break; 976 } 977 978 if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 979 { 980 /* Shutdown BP */ 981 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | (0x1ffffff & -1000)); 982 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 0); 983 } 984 985 if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 986 { 987 /* Shutdown BP */ 988 cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | (0x1ffffff & -1000)); 989 cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 0); 990 } 991 992 /* Clear any error interrupts that might have been set */ 993 cvmx_write_csr(CVMX_IPD_INT_SUM, 0x1f); 994 cvmx_write_csr(CVMX_IPD_INT_ENB, ipd_int_enb); 995 996 return ((bp_status0 != 1ull<<port0) || (bp_status1 != 1ull<<(port1-16))); 997} 998 999 1000/** 1001 * @INTERNAL 1002 * Enable packet input/output from the hardware. This function is 1003 * called after all internal setup is complete and IPD is enabled. 1004 * After this function completes, packets will be accepted from the 1005 * hardware ports. PKO should still be disabled to make sure packets 1006 * aren't sent out partially setup hardware. 1007 * 1008 * @param interface Interface to enable 1009 * 1010 * @return Zero on success, negative on failure 1011 */ 1012static int __cvmx_helper_packet_hardware_enable(int interface) 1013{ 1014 int result = 0; 1015 switch (cvmx_helper_interface_get_mode(interface)) 1016 { 1017 /* These types don't support ports to IPD/PKO */ 1018 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1019 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1020 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1021 /* Nothing to do */ 1022 break; 1023 /* XAUI is a single high speed port */ 1024 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1025 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1026 result = __cvmx_helper_xaui_enable(interface); 1027 break; 1028 /* RGMII/GMII/MII are all treated about the same. Most functions 1029 refer to these ports as RGMII */ 1030 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1031 case CVMX_HELPER_INTERFACE_MODE_GMII: 1032 result = __cvmx_helper_rgmii_enable(interface); 1033 break; 1034 /* SPI4 can have 1-16 ports depending on the device at the other end */ 1035 case CVMX_HELPER_INTERFACE_MODE_SPI: 1036 result = __cvmx_helper_spi_enable(interface); 1037 break; 1038 /* SGMII can have 1-4 ports depending on how many are hooked up */ 1039 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1040 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1041 result = __cvmx_helper_sgmii_enable(interface); 1042 break; 1043 /* PCI target Network Packet Interface */ 1044 case CVMX_HELPER_INTERFACE_MODE_NPI: 1045 result = __cvmx_helper_npi_enable(interface); 1046 break; 1047 /* SRIO has 2^N ports, where N is number of interfaces */ 1048 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1049 result = __cvmx_helper_srio_enable(interface); 1050 break; 1051 case CVMX_HELPER_INTERFACE_MODE_ILK: 1052 result = __cvmx_helper_ilk_enable(interface); 1053 break; 1054 } 1055 result |= __cvmx_helper_board_hardware_enable(interface); 1056 return result; 1057} 1058 1059 1060/** 1061 * Called after all internal packet IO paths are setup. This 1062 * function enables IPD/PIP and begins packet input and output. 1063 * 1064 * @return Zero on success, negative on failure 1065 */ 1066int cvmx_helper_ipd_and_packet_input_enable(void) 1067{ 1068 int num_interfaces; 1069 int interface; 1070 1071 /* Enable IPD */ 1072 cvmx_ipd_enable(); 1073 1074 /* Time to enable hardware ports packet input and output. Note that at this 1075 point IPD/PIP must be fully functional and PKO must be disabled */ 1076 num_interfaces = cvmx_helper_get_number_of_interfaces(); 1077 for (interface=0; interface<num_interfaces; interface++) 1078 { 1079 if (cvmx_helper_ports_on_interface(interface) > 0) 1080 { 1081 //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface); 1082 __cvmx_helper_packet_hardware_enable(interface); 1083 } 1084 } 1085 1086 /* Finally enable PKO now that the entire path is up and running */ 1087 cvmx_pko_enable(); 1088 1089 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) && 1090 (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) 1091 __cvmx_helper_errata_fix_ipd_ptr_alignment(); 1092 return 0; 1093} 1094#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1095EXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable); 1096#endif 1097 1098#define __CVMX_SSO_RWQ_SIZE 256 1099 1100int cvmx_helper_initialize_sso(int wqe_entries) 1101{ 1102 int cvm_oct_sso_number_rwq_bufs; 1103 char *mem; 1104 int i; 1105 cvmx_sso_cfg_t sso_cfg; 1106 cvmx_fpa_fpfx_marks_t fpa_marks; 1107 1108 if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1109 return 0; 1110 1111 /* 1112 * CN68XX-P1 may reset with the wrong values, put in 1113 * the correct values. 1114 */ 1115 fpa_marks.u64 = 0; 1116 fpa_marks.s.fpf_wr = 0xa4; 1117 fpa_marks.s.fpf_rd = 0x40; 1118 cvmx_write_csr(CVMX_FPA_FPF8_MARKS, fpa_marks.u64); 1119 1120 cvm_oct_sso_number_rwq_bufs = ((wqe_entries - 1) / 26) + 1 + 48 + 8; 1121 1122 mem = cvmx_bootmem_alloc(__CVMX_SSO_RWQ_SIZE * cvm_oct_sso_number_rwq_bufs, CVMX_CACHE_LINE_SIZE); 1123 if (mem == NULL) { 1124 cvmx_dprintf("Out of memory initializing sso pool\n"); 1125 return -1; 1126 } 1127 /* Make sure RWI/RWO is disabled. */ 1128 sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1129 sso_cfg.s.rwen = 0; 1130 cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1131 1132 for (i = cvm_oct_sso_number_rwq_bufs - 8; i > 0; i--) { 1133 cvmx_sso_rwq_psh_fptr_t fptr; 1134 1135 for (;;) { 1136 fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR); 1137 if (!fptr.s.full) 1138 break; 1139 cvmx_wait(1000); 1140 } 1141 fptr.s.fptr = cvmx_ptr_to_phys(mem) >> 7; 1142 cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64); 1143 mem = mem + __CVMX_SSO_RWQ_SIZE; 1144 } 1145 1146 for (i = 0; i < 8; i++) { 1147 cvmx_sso_rwq_head_ptrx_t head_ptr; 1148 cvmx_sso_rwq_tail_ptrx_t tail_ptr; 1149 1150 head_ptr.u64 = 0; 1151 tail_ptr.u64 = 0; 1152 head_ptr.s.ptr = cvmx_ptr_to_phys(mem) >> 7; 1153 tail_ptr.s.ptr = head_ptr.s.ptr; 1154 cvmx_write_csr(CVMX_SSO_RWQ_HEAD_PTRX(i), head_ptr.u64); 1155 cvmx_write_csr(CVMX_SSO_RWQ_TAIL_PTRX(i), tail_ptr.u64); 1156 mem = mem + __CVMX_SSO_RWQ_SIZE; 1157 } 1158 1159 sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1160 sso_cfg.s.rwen = 1; 1161 sso_cfg.s.dwb = cvmx_helper_cfg_opt_get(CVMX_HELPER_CFG_OPT_USE_DWB); 1162 sso_cfg.s.rwq_byp_dis = 0; 1163 sso_cfg.s.rwio_byp_dis = 0; 1164 cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1165 1166 return 0; 1167} 1168 1169int cvmx_helper_uninitialize_sso(void) 1170{ 1171 cvmx_fpa_quex_available_t queue_available; 1172 cvmx_sso_cfg_t sso_cfg; 1173 cvmx_sso_rwq_pop_fptr_t pop_fptr; 1174 cvmx_sso_rwq_psh_fptr_t fptr; 1175 cvmx_sso_fpage_cnt_t fpage_cnt; 1176 int num_to_transfer, i; 1177 char *mem; 1178 1179 if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1180 return 0; 1181 1182 sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1183 sso_cfg.s.rwen = 0; 1184 sso_cfg.s.rwq_byp_dis = 1; 1185 cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1186 cvmx_read_csr(CVMX_SSO_CFG); 1187 queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8)); 1188 1189 /* Make CVMX_FPA_QUEX_AVAILABLE(8) % 16 == 0*/ 1190 for (num_to_transfer = (16 - queue_available.s.que_siz) % 16; 1191 num_to_transfer > 0; num_to_transfer--) { 1192 do { 1193 pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR); 1194 } while (!pop_fptr.s.val); 1195 for (;;) { 1196 fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR); 1197 if (!fptr.s.full) 1198 break; 1199 cvmx_wait(1000); 1200 } 1201 fptr.s.fptr = pop_fptr.s.fptr; 1202 cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64); 1203 } 1204 cvmx_read_csr(CVMX_SSO_CFG); 1205 1206 do { 1207 queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8)); 1208 } while (queue_available.s.que_siz % 16); 1209 1210 sso_cfg.s.rwen = 1; 1211 sso_cfg.s.rwq_byp_dis = 0; 1212 cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1213 1214 for (i = 0; i < 8; i++) { 1215 cvmx_sso_rwq_head_ptrx_t head_ptr; 1216 cvmx_sso_rwq_tail_ptrx_t tail_ptr; 1217 1218 head_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_HEAD_PTRX(i)); 1219 tail_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_TAIL_PTRX(i)); 1220 if (head_ptr.s.ptr != tail_ptr.s.ptr) { 1221 cvmx_dprintf("head_ptr.s.ptr != tail_ptr.s.ptr, idx: %d\n", i); 1222 } 1223 1224 mem = cvmx_phys_to_ptr(((uint64_t)head_ptr.s.ptr) << 7); 1225 /* Leak the memory */ 1226 } 1227 1228 do { 1229 do { 1230 pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR); 1231 if (pop_fptr.s.val) { 1232 mem = cvmx_phys_to_ptr(((uint64_t)pop_fptr.s.fptr) << 7); 1233 /* Leak the memory */ 1234 } 1235 } while (pop_fptr.s.val); 1236 fpage_cnt.u64 = cvmx_read_csr(CVMX_SSO_FPAGE_CNT); 1237 } while (fpage_cnt.s.fpage_cnt); 1238 1239 sso_cfg.s.rwen = 0; 1240 sso_cfg.s.rwq_byp_dis = 0; 1241 cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1242 1243 return 0; 1244} 1245 1246/** 1247 * Initialize the PIP, IPD, and PKO hardware to support 1248 * simple priority based queues for the ethernet ports. Each 1249 * port is configured with a number of priority queues based 1250 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower 1251 * priority than the previous. 1252 * 1253 * @return Zero on success, non-zero on failure 1254 */ 1255int cvmx_helper_initialize_packet_io_global(void) 1256{ 1257 int result = 0; 1258 int interface; 1259 cvmx_l2c_cfg_t l2c_cfg; 1260 cvmx_smix_en_t smix_en; 1261 const int num_interfaces = cvmx_helper_get_number_of_interfaces(); 1262 1263 /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */ 1264 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 1265 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); 1266 1267 /* Tell L2 to give the IOB statically higher priority compared to the 1268 cores. This avoids conditions where IO blocks might be starved under 1269 very high L2 loads */ 1270 if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 1271 { 1272 cvmx_l2c_ctl_t l2c_ctl; 1273 l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL); 1274 l2c_ctl.s.rsp_arb_mode = 1; 1275 l2c_ctl.s.xmc_arb_mode = 0; 1276 cvmx_write_csr(CVMX_L2C_CTL, l2c_ctl.u64); 1277 } 1278 else 1279 { 1280 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 1281 l2c_cfg.s.lrf_arb_mode = 0; 1282 l2c_cfg.s.rfb_arb_mode = 0; 1283 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); 1284 } 1285 1286 if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 1287 { 1288 int smi_inf = 1; 1289 int i; 1290 1291 /* Newer chips have more than one SMI/MDIO interface */ 1292 if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 1293 smi_inf = 4; 1294 else if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) 1295 && !OCTEON_IS_MODEL(OCTEON_CN58XX) 1296 && !OCTEON_IS_MODEL(OCTEON_CN50XX)) 1297 smi_inf = 2; 1298 1299 for (i = 0; i < smi_inf; i++) 1300 { 1301 /* Make sure SMI/MDIO is enabled so we can query PHYs */ 1302 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(i)); 1303 if (!smix_en.s.en) 1304 { 1305 smix_en.s.en = 1; 1306 cvmx_write_csr(CVMX_SMIX_EN(i), smix_en.u64); 1307 } 1308 } 1309 } 1310 1311 __cvmx_helper_cfg_init(); 1312 1313 for (interface=0; interface<num_interfaces; interface++) 1314 result |= cvmx_helper_interface_probe(interface); 1315 1316 cvmx_pko_initialize_global(); 1317 for (interface=0; interface<num_interfaces; interface++) 1318 { 1319 if (cvmx_helper_ports_on_interface(interface) > 0) 1320 cvmx_dprintf("Interface %d has %d ports (%s)\n", 1321 interface, cvmx_helper_ports_on_interface(interface), 1322 cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface))); 1323 result |= __cvmx_helper_interface_setup_ipd(interface); 1324 if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1325 result |= __cvmx_helper_interface_setup_pko(interface); 1326 } 1327 1328 result |= __cvmx_helper_global_setup_ipd(); 1329 result |= __cvmx_helper_global_setup_pko(); 1330 1331 /* Enable any flow control and backpressure */ 1332 result |= __cvmx_helper_global_setup_backpressure(); 1333 1334#if CVMX_HELPER_ENABLE_IPD 1335 result |= cvmx_helper_ipd_and_packet_input_enable(); 1336#endif 1337 return result; 1338} 1339#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1340EXPORT_SYMBOL(cvmx_helper_initialize_packet_io_global); 1341#endif 1342 1343 1344/** 1345 * Does core local initialization for packet io 1346 * 1347 * @return Zero on success, non-zero on failure 1348 */ 1349int cvmx_helper_initialize_packet_io_local(void) 1350{ 1351 return cvmx_pko_initialize_local(); 1352} 1353 1354/** 1355 * wait for the pko queue to drain 1356 * 1357 * @param queue a valid pko queue 1358 * @return count is the length of the queue after calling this 1359 * function 1360 */ 1361static int cvmx_helper_wait_pko_queue_drain(int queue) 1362{ 1363 const int timeout = 5; /* Wait up to 5 seconds for timeouts */ 1364 int count; 1365 uint64_t start_cycle, stop_cycle; 1366 1367 count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 1368 start_cycle = cvmx_get_cycle(); 1369 stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 1370 while (count && (cvmx_get_cycle() < stop_cycle)) 1371 { 1372 cvmx_wait(10000); 1373 count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 1374 } 1375 1376 return count; 1377} 1378 1379struct cvmx_buffer_list { 1380 struct cvmx_buffer_list *next; 1381}; 1382 1383/** 1384 * Undo the initialization performed in 1385 * cvmx_helper_initialize_packet_io_global(). After calling this routine and the 1386 * local version on each core, packet IO for Octeon will be disabled and placed 1387 * in the initial reset state. It will then be safe to call the initialize 1388 * later on. Note that this routine does not empty the FPA pools. It frees all 1389 * buffers used by the packet IO hardware to the FPA so a function emptying the 1390 * FPA after shutdown should find all packet buffers in the FPA. 1391 * 1392 * @return Zero on success, negative on failure. 1393 */ 1394int cvmx_helper_shutdown_packet_io_global(void) 1395{ 1396 const int timeout = 5; /* Wait up to 5 seconds for timeouts */ 1397 int result = 0; 1398 int num_interfaces; 1399 int interface; 1400 int num_ports; 1401 int index; 1402 struct cvmx_buffer_list *pool0_buffers; 1403 struct cvmx_buffer_list *pool0_buffers_tail; 1404 cvmx_wqe_t *work; 1405 1406 /* Step 1: Disable all backpressure */ 1407 for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1408 if (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_DISABLED) 1409 cvmx_gmx_set_backpressure_override(interface, 0xf); 1410 1411step2: 1412 /* Step 2: Wait for the PKO queues to drain */ 1413 if (octeon_has_feature(OCTEON_FEATURE_PKND)) 1414 { 1415 int queue, max_queue; 1416 1417 max_queue = __cvmx_helper_cfg_pko_max_queue(); 1418 for (queue = 0; queue < max_queue; queue++) 1419 { 1420 if (cvmx_helper_wait_pko_queue_drain(queue)) 1421 { 1422 result = -1; 1423 goto step3; 1424 } 1425 } 1426 } 1427 else 1428 { 1429 num_interfaces = cvmx_helper_get_number_of_interfaces(); 1430 for (interface=0; interface<num_interfaces; interface++) 1431 { 1432 num_ports = cvmx_helper_ports_on_interface(interface); 1433 for (index=0; index<num_ports; index++) 1434 { 1435 int pko_port = cvmx_helper_get_ipd_port(interface, index); 1436 int queue = cvmx_pko_get_base_queue(pko_port); 1437 int max_queue = queue + cvmx_pko_get_num_queues(pko_port); 1438 while (queue < max_queue) 1439 { 1440 if (cvmx_helper_wait_pko_queue_drain(queue)) 1441 { 1442 result = -1; 1443 goto step3; 1444 } 1445 queue++; 1446 } 1447 } 1448 } 1449 } 1450 1451step3: 1452 /* Step 3: Disable TX and RX on all ports */ 1453 for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1454 { 1455 switch (cvmx_helper_interface_get_mode(interface)) 1456 { 1457 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1458 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1459 /* Not a packet interface */ 1460 break; 1461 case CVMX_HELPER_INTERFACE_MODE_NPI: 1462 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1463 case CVMX_HELPER_INTERFACE_MODE_ILK: 1464 /* We don't handle the NPI/NPEI/SRIO packet engines. The caller 1465 must know these are idle */ 1466 break; 1467 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1468 /* Nothing needed. Once PKO is idle, the loopback devices 1469 must be idle */ 1470 break; 1471 case CVMX_HELPER_INTERFACE_MODE_SPI: 1472 /* SPI cannot be disabled from Octeon. It is the responsibility 1473 of the caller to make sure SPI is idle before doing 1474 shutdown */ 1475 /* Fall through and do the same processing as RGMII/GMII */ 1476 case CVMX_HELPER_INTERFACE_MODE_GMII: 1477 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1478 /* Disable outermost RX at the ASX block */ 1479 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), 0); 1480 num_ports = cvmx_helper_ports_on_interface(interface); 1481 if (num_ports > 4) 1482 num_ports = 4; 1483 for (index=0; index<num_ports; index++) 1484 { 1485 cvmx_gmxx_prtx_cfg_t gmx_cfg; 1486 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 1487 gmx_cfg.s.en = 0; 1488 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 1489 /* Poll the GMX state machine waiting for it to become idle */ 1490 cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880); 1491 if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, timeout*1000000)) 1492 { 1493 cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 1494 result = -1; 1495 } 1496 if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, timeout*1000000)) 1497 { 1498 cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 1499 result = -1; 1500 } 1501 } 1502 /* Disable outermost TX at the ASX block */ 1503 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), 0); 1504 /* Disable interrupts for interface */ 1505 cvmx_write_csr(CVMX_ASXX_INT_EN(interface), 0); 1506 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0); 1507 break; 1508 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1509 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1510 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1511 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1512 num_ports = cvmx_helper_ports_on_interface(interface); 1513 if (num_ports > 4) 1514 num_ports = 4; 1515 for (index=0; index<num_ports; index++) 1516 { 1517 cvmx_gmxx_prtx_cfg_t gmx_cfg; 1518 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 1519 gmx_cfg.s.en = 0; 1520 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 1521 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, timeout*1000000)) 1522 { 1523 cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 1524 result = -1; 1525 } 1526 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, timeout*1000000)) 1527 { 1528 cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 1529 result = -1; 1530 } 1531 } 1532 break; 1533 } 1534 } 1535 1536 /* Step 4: Retrieve all packets from the POW and free them */ 1537 while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT))) 1538 { 1539 cvmx_helper_free_packet_data(work); 1540 cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 0); 1541 } 1542 1543 /* Step 4b: Special workaround for pass 2 errata */ 1544 if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1545 { 1546 cvmx_ipd_ptr_count_t ipd_cnt; 1547 int to_add; 1548 ipd_cnt.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 1549 to_add = (ipd_cnt.s.wqev_cnt + ipd_cnt.s.wqe_pcnt) & 0x7; 1550 if (to_add) 1551 { 1552 int port = -1; 1553 cvmx_dprintf("Aligning CN38XX pass 2 IPD counters\n"); 1554 if (cvmx_helper_interface_get_mode(0) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1555 port = 0; 1556 else if (cvmx_helper_interface_get_mode(1) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1557 port = 16; 1558 1559 if (port != -1) 1560 { 1561 char *buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); 1562 if (buffer) 1563 { 1564 int queue = cvmx_pko_get_base_queue(port); 1565 cvmx_pko_command_word0_t pko_command; 1566 cvmx_buf_ptr_t packet; 1567 uint64_t start_cycle; 1568 uint64_t stop_cycle; 1569 1570 /* Populate a minimal packet */ 1571 memset(buffer, 0xff, 6); 1572 memset(buffer+6, 0, 54); 1573 pko_command.u64 = 0; 1574 pko_command.s.dontfree = 1; 1575 pko_command.s.total_bytes = 60; 1576 pko_command.s.segs = 1; 1577 packet.u64 = 0; 1578 packet.s.addr = cvmx_ptr_to_phys(buffer); 1579 packet.s.size = CVMX_FPA_PACKET_POOL_SIZE; 1580 __cvmx_helper_rgmii_configure_loopback(port, 1, 0); 1581 while (to_add--) 1582 { 1583 cvmx_pko_send_packet_prepare(port, queue, CVMX_PKO_LOCK_CMD_QUEUE); 1584 if (cvmx_pko_send_packet_finish(port, queue, pko_command, packet, CVMX_PKO_LOCK_CMD_QUEUE)) 1585 { 1586 cvmx_dprintf("ERROR: Unable to align IPD counters (PKO failed)\n"); 1587 break; 1588 } 1589 } 1590 cvmx_fpa_free(buffer, CVMX_FPA_PACKET_POOL, 0); 1591 1592 /* Wait for the packets to loop back */ 1593 start_cycle = cvmx_get_cycle(); 1594 stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 1595 while (cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)) && 1596 (cvmx_get_cycle() < stop_cycle)) 1597 { 1598 cvmx_wait(1000); 1599 } 1600 cvmx_wait(1000); 1601 __cvmx_helper_rgmii_configure_loopback(port, 0, 0); 1602 if (to_add == -1) 1603 goto step2; 1604 } 1605 else 1606 cvmx_dprintf("ERROR: Unable to align IPD counters (Packet pool empty)\n"); 1607 } 1608 else 1609 cvmx_dprintf("ERROR: Unable to align IPD counters\n"); 1610 } 1611 } 1612 1613 /* Step 5 */ 1614 cvmx_ipd_disable(); 1615 1616 /* Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP 1617 have not been reset yet */ 1618 __cvmx_ipd_free_ptr(); 1619 1620 /* Step 7: Free the PKO command buffers and put PKO in reset */ 1621 cvmx_pko_shutdown(); 1622 1623 /* Step 8: Disable MAC address filtering */ 1624 for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1625 { 1626 switch (cvmx_helper_interface_get_mode(interface)) 1627 { 1628 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1629 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1630 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1631 case CVMX_HELPER_INTERFACE_MODE_ILK: 1632 case CVMX_HELPER_INTERFACE_MODE_NPI: 1633 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1634 break; 1635 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1636 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1637 case CVMX_HELPER_INTERFACE_MODE_GMII: 1638 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1639 case CVMX_HELPER_INTERFACE_MODE_SPI: 1640 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1641 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1642 num_ports = cvmx_helper_ports_on_interface(interface); 1643 if (num_ports > 4) 1644 num_ports = 4; 1645 for (index=0; index<num_ports; index++) 1646 { 1647 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1); 1648 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0); 1649 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0); 1650 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0); 1651 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0); 1652 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0); 1653 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0); 1654 cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0); 1655 } 1656 break; 1657 } 1658 } 1659 1660 /* Step 9: Drain all FPA buffers out of pool 0 before we reset 1661 * IPD/PIP. This is needed to keep IPD_QUE0_FREE_PAGE_CNT in 1662 * sync. We temporarily keep the buffers in the pool0_buffers 1663 * list. 1664 */ 1665 pool0_buffers = NULL; 1666 pool0_buffers_tail = NULL; 1667 while (1) 1668 { 1669 struct cvmx_buffer_list *buffer = cvmx_fpa_alloc(0); 1670 if (buffer) { 1671 buffer->next = NULL; 1672 1673 if (pool0_buffers == NULL) 1674 pool0_buffers = buffer; 1675 else 1676 pool0_buffers_tail->next = buffer; 1677 1678 pool0_buffers_tail = buffer; 1679 } 1680 else 1681 break; 1682 } 1683 1684 /* Step 10: Reset IPD and PIP */ 1685 { 1686 cvmx_ipd_ctl_status_t ipd_ctl_status; 1687 ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 1688 ipd_ctl_status.s.reset = 1; 1689 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1690 1691 if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && 1692 (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))) 1693 { 1694 /* only try 1000 times. Normally if this works it will happen in 1695 ** the first 50 loops. */ 1696 int max_loops = 1000; 1697 int loop = 0; 1698 /* Per port backpressure counters can get misaligned after an 1699 IPD reset. This code realigns them by performing repeated 1700 resets. See IPD-13473 */ 1701 cvmx_wait(100); 1702 if (__cvmx_helper_backpressure_is_misaligned()) 1703 { 1704 cvmx_dprintf("Starting to align per port backpressure counters.\n"); 1705 while (__cvmx_helper_backpressure_is_misaligned() && (loop++ < max_loops)) 1706 { 1707 cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1708 cvmx_wait(123); 1709 } 1710 if (loop < max_loops) 1711 cvmx_dprintf("Completed aligning per port backpressure counters (%d loops).\n", loop); 1712 else 1713 { 1714 cvmx_dprintf("ERROR: unable to align per port backpressure counters.\n"); 1715 /* For now, don't hang.... */ 1716 } 1717 } 1718 } 1719 1720 /* PIP_SFT_RST not present in CN38XXp{1,2} */ 1721 if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1722 { 1723 cvmx_pip_sft_rst_t pip_sft_rst; 1724 pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST); 1725 pip_sft_rst.s.rst = 1; 1726 cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64); 1727 } 1728 1729 /* Make sure IPD has finished reset. */ 1730 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 1731 { 1732 if (CVMX_WAIT_FOR_FIELD64(CVMX_IPD_CTL_STATUS, cvmx_ipd_ctl_status_t, rst_done, ==, 0, 1000)) 1733 { 1734 cvmx_dprintf("IPD reset timeout waiting for idle\n"); 1735 result = -1; 1736 } 1737 } 1738 } 1739 1740 /* Step 11: Restore the FPA buffers into pool 0 */ 1741 while (pool0_buffers) { 1742 struct cvmx_buffer_list *n = pool0_buffers->next; 1743 cvmx_fpa_free(pool0_buffers, 0, 0); 1744 pool0_buffers = n; 1745 } 1746 1747 /* Step 12: Release interface structures */ 1748 __cvmx_helper_shutdown_interfaces(); 1749 1750 return result; 1751} 1752#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1753EXPORT_SYMBOL(cvmx_helper_shutdown_packet_io_global); 1754#endif 1755 1756 1757/** 1758 * Does core local shutdown of packet io 1759 * 1760 * @return Zero on success, non-zero on failure 1761 */ 1762int cvmx_helper_shutdown_packet_io_local(void) 1763{ 1764 /* Currently there is nothing to do per core. This may change in 1765 the future */ 1766 return 0; 1767} 1768 1769 1770 1771/** 1772 * Auto configure an IPD/PKO port link state and speed. This 1773 * function basically does the equivalent of: 1774 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); 1775 * 1776 * @param ipd_port IPD/PKO port to auto configure 1777 * 1778 * @return Link state after configure 1779 */ 1780cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) 1781{ 1782 cvmx_helper_link_info_t link_info; 1783 int interface = cvmx_helper_get_interface_num(ipd_port); 1784 int index = cvmx_helper_get_interface_index_num(ipd_port); 1785 1786 if (index >= cvmx_helper_ports_on_interface(interface)) 1787 { 1788 link_info.u64 = 0; 1789 return link_info; 1790 } 1791 1792 link_info = cvmx_helper_link_get(ipd_port); 1793 if (link_info.u64 == (__cvmx_helper_get_link_info(interface, index)).u64) 1794 return link_info; 1795 1796#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1797 if (!link_info.s.link_up) 1798 cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1799#endif 1800 1801 /* If we fail to set the link speed, port_link_info will not change */ 1802 cvmx_helper_link_set(ipd_port, link_info); 1803 1804#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1805 if (link_info.s.link_up) 1806 cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1807#endif 1808 1809 return link_info; 1810} 1811#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1812EXPORT_SYMBOL(cvmx_helper_link_autoconf); 1813#endif 1814 1815/** 1816 * Return the link state of an IPD/PKO port as returned by 1817 * auto negotiation. The result of this function may not match 1818 * Octeon's link config if auto negotiation has changed since 1819 * the last call to cvmx_helper_link_set(). 1820 * 1821 * @param ipd_port IPD/PKO port to query 1822 * 1823 * @return Link state 1824 */ 1825cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) 1826{ 1827 cvmx_helper_link_info_t result; 1828 int interface = cvmx_helper_get_interface_num(ipd_port); 1829 int index = cvmx_helper_get_interface_index_num(ipd_port); 1830 1831 /* The default result will be a down link unless the code below 1832 changes it */ 1833 result.u64 = 0; 1834 1835 if (index >= cvmx_helper_ports_on_interface(interface)) 1836 return result; 1837 1838 switch (cvmx_helper_interface_get_mode(interface)) 1839 { 1840 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1841 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1842 /* Network links are not supported */ 1843 break; 1844 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1845 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1846 result = __cvmx_helper_xaui_link_get(ipd_port); 1847 break; 1848 case CVMX_HELPER_INTERFACE_MODE_GMII: 1849 if (index == 0) 1850 result = __cvmx_helper_rgmii_link_get(ipd_port); 1851 else 1852 { 1853 result.s.full_duplex = 1; 1854 result.s.link_up = 1; 1855 result.s.speed = 1000; 1856 } 1857 break; 1858 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1859 result = __cvmx_helper_rgmii_link_get(ipd_port); 1860 break; 1861 case CVMX_HELPER_INTERFACE_MODE_SPI: 1862 result = __cvmx_helper_spi_link_get(ipd_port); 1863 break; 1864 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1865 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1866 result = __cvmx_helper_sgmii_link_get(ipd_port); 1867 break; 1868 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1869 result = __cvmx_helper_srio_link_get(ipd_port); 1870 break; 1871 case CVMX_HELPER_INTERFACE_MODE_ILK: 1872 result = __cvmx_helper_ilk_link_get(ipd_port); 1873 break; 1874 case CVMX_HELPER_INTERFACE_MODE_NPI: 1875 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1876 /* Network links are not supported */ 1877 break; 1878 } 1879 return result; 1880} 1881#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1882EXPORT_SYMBOL(cvmx_helper_link_get); 1883#endif 1884 1885 1886/** 1887 * Configure an IPD/PKO port for the specified link state. This 1888 * function does not influence auto negotiation at the PHY level. 1889 * The passed link state must always match the link state returned 1890 * by cvmx_helper_link_get(). It is normally best to use 1891 * cvmx_helper_link_autoconf() instead. 1892 * 1893 * @param ipd_port IPD/PKO port to configure 1894 * @param link_info The new link state 1895 * 1896 * @return Zero on success, negative on failure 1897 */ 1898int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 1899{ 1900 int result = -1; 1901 int interface = cvmx_helper_get_interface_num(ipd_port); 1902 int index = cvmx_helper_get_interface_index_num(ipd_port); 1903 1904 if (index >= cvmx_helper_ports_on_interface(interface)) 1905 return -1; 1906 1907 switch (cvmx_helper_interface_get_mode(interface)) 1908 { 1909 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1910 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1911 break; 1912 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1913 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1914 result = __cvmx_helper_xaui_link_set(ipd_port, link_info); 1915 break; 1916 /* RGMII/GMII/MII are all treated about the same. Most functions 1917 refer to these ports as RGMII */ 1918 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1919 case CVMX_HELPER_INTERFACE_MODE_GMII: 1920 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); 1921 break; 1922 case CVMX_HELPER_INTERFACE_MODE_SPI: 1923 result = __cvmx_helper_spi_link_set(ipd_port, link_info); 1924 break; 1925 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1926 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1927 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); 1928 break; 1929 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1930 result = __cvmx_helper_srio_link_set(ipd_port, link_info); 1931 break; 1932 case CVMX_HELPER_INTERFACE_MODE_ILK: 1933 result = __cvmx_helper_ilk_link_set(ipd_port, link_info); 1934 break; 1935 case CVMX_HELPER_INTERFACE_MODE_NPI: 1936 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1937 break; 1938 } 1939 /* Set the port_link_info here so that the link status is updated 1940 no matter how cvmx_helper_link_set is called. We don't change 1941 the value if link_set failed */ 1942 if (result == 0) 1943 __cvmx_helper_set_link_info(interface, index, link_info); 1944 return result; 1945} 1946#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1947EXPORT_SYMBOL(cvmx_helper_link_set); 1948#endif 1949 1950 1951/** 1952 * Configure a port for internal and/or external loopback. Internal loopback 1953 * causes packets sent by the port to be received by Octeon. External loopback 1954 * causes packets received from the wire to sent out again. 1955 * 1956 * @param ipd_port IPD/PKO port to loopback. 1957 * @param enable_internal 1958 * Non zero if you want internal loopback 1959 * @param enable_external 1960 * Non zero if you want external loopback 1961 * 1962 * @return Zero on success, negative on failure. 1963 */ 1964int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external) 1965{ 1966 int result = -1; 1967 int interface = cvmx_helper_get_interface_num(ipd_port); 1968 int index = cvmx_helper_get_interface_index_num(ipd_port); 1969 1970 if (index >= cvmx_helper_ports_on_interface(interface)) 1971 return -1; 1972 1973 switch (cvmx_helper_interface_get_mode(interface)) 1974 { 1975 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1976 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1977 case CVMX_HELPER_INTERFACE_MODE_SRIO: 1978 case CVMX_HELPER_INTERFACE_MODE_ILK: 1979 case CVMX_HELPER_INTERFACE_MODE_SPI: 1980 case CVMX_HELPER_INTERFACE_MODE_NPI: 1981 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1982 break; 1983 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1984 case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1985 result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external); 1986 break; 1987 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1988 case CVMX_HELPER_INTERFACE_MODE_GMII: 1989 result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1990 break; 1991 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1992 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1993 result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1994 break; 1995 } 1996 return result; 1997} 1998 1999#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 2000