1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Helper functions for common, but complicated tasks. 50210284Sjmallett * 51232812Sjmallett * <hr>$Revision: 70030 $<hr> 52210284Sjmallett */ 53215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54215990Sjmallett#include <linux/module.h> 55215990Sjmallett#include <asm/octeon/cvmx.h> 56215990Sjmallett#include <asm/octeon/cvmx-config.h> 57215990Sjmallett#include <asm/octeon/cvmx-bootmem.h> 58215990Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 59215990Sjmallett#include <asm/octeon/cvmx-npi-defs.h> 60232812Sjmallett#include <asm/octeon/cvmx-mio-defs.h> 61215990Sjmallett#include <asm/octeon/cvmx-pexp-defs.h> 62215990Sjmallett#include <asm/octeon/cvmx-pip-defs.h> 63215990Sjmallett#include <asm/octeon/cvmx-asxx-defs.h> 64215990Sjmallett#include <asm/octeon/cvmx-gmxx-defs.h> 65215990Sjmallett#include <asm/octeon/cvmx-smix-defs.h> 66215990Sjmallett#include <asm/octeon/cvmx-dbg-defs.h> 67232812Sjmallett#include <asm/octeon/cvmx-sso-defs.h> 68215990Sjmallett 69215990Sjmallett#include <asm/octeon/cvmx-gmx.h> 70215990Sjmallett#include <asm/octeon/cvmx-fpa.h> 71215990Sjmallett#include <asm/octeon/cvmx-pip.h> 72215990Sjmallett#include <asm/octeon/cvmx-pko.h> 73215990Sjmallett#include <asm/octeon/cvmx-ipd.h> 74215990Sjmallett#include <asm/octeon/cvmx-spi.h> 75215990Sjmallett#include <asm/octeon/cvmx-clock.h> 76215990Sjmallett#include <asm/octeon/cvmx-helper.h> 77215990Sjmallett#include <asm/octeon/cvmx-helper-board.h> 78215990Sjmallett#include <asm/octeon/cvmx-helper-errata.h> 79232812Sjmallett#include <asm/octeon/cvmx-helper-cfg.h> 80215990Sjmallett#else 81215990Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 82215990Sjmallett#include "executive-config.h" 83215990Sjmallett#endif 84210284Sjmallett#include "cvmx.h" 85215990Sjmallett#include "cvmx-sysinfo.h" 86210284Sjmallett#include "cvmx-bootmem.h" 87215990Sjmallett#include "cvmx-version.h" 88215990Sjmallett#include "cvmx-helper-check-defines.h" 89215990Sjmallett#include "cvmx-gmx.h" 90232816Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 91215990Sjmallett#include "cvmx-error.h" 92215990Sjmallett#include "cvmx-config.h" 93215990Sjmallett#endif 94215990Sjmallett 95210284Sjmallett#include "cvmx-fpa.h" 96210284Sjmallett#include "cvmx-pip.h" 97210284Sjmallett#include "cvmx-pko.h" 98210284Sjmallett#include "cvmx-ipd.h" 99210284Sjmallett#include "cvmx-spi.h" 100210284Sjmallett#include "cvmx-helper.h" 101210284Sjmallett#include "cvmx-helper-board.h" 102210284Sjmallett#include "cvmx-helper-errata.h" 103232812Sjmallett#include "cvmx-helper-cfg.h" 104215990Sjmallett#endif 105210284Sjmallett 106215990Sjmallett 107210284Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 108210284Sjmallett 109210284Sjmallett/** 110232812Sjmallett * cvmx_override_pko_queue_priority(int pko_port, uint64_t 111210284Sjmallett * priorities[16]) is a function pointer. It is meant to allow 112210284Sjmallett * customization of the PKO queue priorities based on the port 113210284Sjmallett * number. Users should set this pointer to a function before 114210284Sjmallett * calling any cvmx-helper operations. 115210284Sjmallett */ 116232812SjmallettCVMX_SHARED void (*cvmx_override_pko_queue_priority)(int ipd_port, 117232812Sjmallett uint64_t *priorities) = NULL; 118215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 119215990SjmallettEXPORT_SYMBOL(cvmx_override_pko_queue_priority); 120215990Sjmallett#endif 121210284Sjmallett 122210284Sjmallett/** 123210284Sjmallett * cvmx_override_ipd_port_setup(int ipd_port) is a function 124232812Sjmallett * pointer. It is meant to allow customization of the IPD 125232812Sjmallett * port/port kind setup before packet input/output comes online. 126232812Sjmallett * It is called after cvmx-helper does the default IPD configuration, 127232812Sjmallett * but before IPD is enabled. Users should set this pointer to a 128210284Sjmallett * function before calling any cvmx-helper operations. 129210284Sjmallett */ 130210284SjmallettCVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL; 131210284Sjmallett 132210284Sjmallett/** 133210284Sjmallett * Return the number of interfaces the chip has. Each interface 134210284Sjmallett * may have multiple ports. Most chips support two interfaces, 135210284Sjmallett * but the CNX0XX and CNX1XX are exceptions. These only support 136210284Sjmallett * one interface. 137210284Sjmallett * 138210284Sjmallett * @return Number of interfaces on chip 139210284Sjmallett */ 140210284Sjmallettint cvmx_helper_get_number_of_interfaces(void) 141210284Sjmallett{ 142212844Sjmallett switch (cvmx_sysinfo_get()->board_type) { 143212844Sjmallett#if defined(OCTEON_VENDOR_LANNER) 144212844Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 145212844Sjmallett return 2; 146215014Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 147215014Sjmallett return 1; 148212844Sjmallett#endif 149242104Sjmallett#if defined(OCTEON_VENDOR_RADISYS) 150242104Sjmallett case CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE: 151242104Sjmallett return 2; 152242104Sjmallett#endif 153212844Sjmallett default: 154212844Sjmallett break; 155212844Sjmallett } 156212844Sjmallett 157232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 158232812Sjmallett return 9; 159232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 160232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 161232812Sjmallett return 7; 162232812Sjmallett else 163232812Sjmallett return 8; 164232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 165232812Sjmallett return 6; 166232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN61XX)) 167210284Sjmallett return 4; 168210284Sjmallett else 169210284Sjmallett return 3; 170210284Sjmallett} 171215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 172215990SjmallettEXPORT_SYMBOL(cvmx_helper_get_number_of_interfaces); 173215990Sjmallett#endif 174210284Sjmallett 175210284Sjmallett 176210284Sjmallett/** 177210284Sjmallett * Return the number of ports on an interface. Depending on the 178210284Sjmallett * chip and configuration, this can be 1-16. A value of 0 179210284Sjmallett * specifies that the interface doesn't exist or isn't usable. 180210284Sjmallett * 181210284Sjmallett * @param interface Interface to get the port count for 182210284Sjmallett * 183210284Sjmallett * @return Number of ports on interface. Can be Zero. 184210284Sjmallett */ 185210284Sjmallettint cvmx_helper_ports_on_interface(int interface) 186210284Sjmallett{ 187232812Sjmallett if (octeon_has_feature(OCTEON_FEATURE_PKND)) 188232812Sjmallett return cvmx_helper_interface_enumerate(interface); 189232812Sjmallett else 190232812Sjmallett return __cvmx_helper_get_num_ipd_ports(interface); 191210284Sjmallett} 192215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 193215990SjmallettEXPORT_SYMBOL(cvmx_helper_ports_on_interface); 194215990Sjmallett#endif 195210284Sjmallett 196210284Sjmallett 197210284Sjmallett/** 198210284Sjmallett * Get the operating mode of an interface. Depending on the Octeon 199210284Sjmallett * chip and configuration, this function returns an enumeration 200210284Sjmallett * of the type of packet I/O supported by an interface. 201210284Sjmallett * 202210284Sjmallett * @param interface Interface to probe 203210284Sjmallett * 204210284Sjmallett * @return Mode of the interface. Unknown or unsupported interfaces return 205210284Sjmallett * DISABLED. 206210284Sjmallett */ 207210284Sjmallettcvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) 208210284Sjmallett{ 209210284Sjmallett cvmx_gmxx_inf_mode_t mode; 210232812Sjmallett 211232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 212232812Sjmallett { 213232812Sjmallett cvmx_mio_qlmx_cfg_t qlm_cfg; 214232812Sjmallett switch(interface) 215232812Sjmallett { 216232812Sjmallett case 0: 217232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 218232812Sjmallett /* QLM is disabled when QLM SPD is 15. */ 219232812Sjmallett if (qlm_cfg.s.qlm_spd == 15) 220232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 221232812Sjmallett 222232812Sjmallett if (qlm_cfg.s.qlm_cfg == 7) 223232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_RXAUI; 224232812Sjmallett else if (qlm_cfg.s.qlm_cfg == 2) 225232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_SGMII; 226232812Sjmallett else if (qlm_cfg.s.qlm_cfg == 3) 227232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_XAUI; 228232812Sjmallett else 229232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 230232812Sjmallett break; 231232812Sjmallett case 1: 232232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 233232812Sjmallett /* QLM is disabled when QLM SPD is 15. */ 234232812Sjmallett if (qlm_cfg.s.qlm_spd == 15) 235232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 236232812Sjmallett 237232812Sjmallett if (qlm_cfg.s.qlm_cfg == 7) 238232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_RXAUI; 239232812Sjmallett else 240232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 241232812Sjmallett break; 242232812Sjmallett case 2: 243232812Sjmallett case 3: 244232812Sjmallett case 4: 245232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface)); 246232812Sjmallett /* QLM is disabled when QLM SPD is 15. */ 247232812Sjmallett if (qlm_cfg.s.qlm_spd == 15) 248232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 249232812Sjmallett 250232812Sjmallett if (qlm_cfg.s.qlm_cfg == 2) 251232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_SGMII; 252232812Sjmallett else if (qlm_cfg.s.qlm_cfg == 3) 253232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_XAUI; 254232812Sjmallett else 255232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 256232812Sjmallett break; 257232812Sjmallett case 5: 258232812Sjmallett case 6: 259232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(interface - 4)); 260232812Sjmallett /* QLM is disabled when QLM SPD is 15. */ 261232812Sjmallett if (qlm_cfg.s.qlm_spd == 15) 262232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 263232812Sjmallett 264232812Sjmallett if (qlm_cfg.s.qlm_cfg == 1) 265232812Sjmallett { 266232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_ILK; 267232812Sjmallett } 268232812Sjmallett else 269232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 270232812Sjmallett break; 271232812Sjmallett case 7: 272232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(3)); 273232812Sjmallett /* QLM is disabled when QLM SPD is 15. */ 274232812Sjmallett if (qlm_cfg.s.qlm_spd == 15) 275232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 276232812Sjmallett else if (qlm_cfg.s.qlm_cfg != 0) 277232812Sjmallett { 278232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 279232812Sjmallett if (qlm_cfg.s.qlm_cfg != 0) 280232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 281232812Sjmallett } 282232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_NPI; 283232812Sjmallett break; 284232812Sjmallett case 8: 285232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_LOOP; 286232812Sjmallett break; 287232812Sjmallett default: 288232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 289232812Sjmallett break; 290232812Sjmallett } 291232812Sjmallett } 292232812Sjmallett 293210284Sjmallett if (interface == 2) 294210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_NPI; 295210284Sjmallett 296210284Sjmallett if (interface == 3) 297210284Sjmallett { 298232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN56XX) 299232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN52XX) 300232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN6XXX) 301232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 302210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_LOOP; 303210284Sjmallett else 304210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 305210284Sjmallett } 306210284Sjmallett 307232812Sjmallett /* Only present in CN63XX & CN66XX Octeon model */ 308232812Sjmallett if ((OCTEON_IS_MODEL(OCTEON_CN63XX) && (interface == 4 || interface == 5)) 309232812Sjmallett || (OCTEON_IS_MODEL(OCTEON_CN66XX) && interface >= 4 && interface <= 7)) 310215990Sjmallett { 311215990Sjmallett cvmx_sriox_status_reg_t sriox_status_reg; 312232812Sjmallett 313232812Sjmallett /* cn66xx pass1.0 has only 2 SRIO interfaces. */ 314232812Sjmallett if ((interface == 5 || interface == 7) && OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_0)) 315232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 316232812Sjmallett 317215990Sjmallett sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(interface-4)); 318215990Sjmallett if (sriox_status_reg.s.srio) 319215990Sjmallett return CVMX_HELPER_INTERFACE_MODE_SRIO; 320215990Sjmallett else 321215990Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 322215990Sjmallett } 323215990Sjmallett 324232812Sjmallett /* Interface 5 always disabled in CN66XX */ 325232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 326232812Sjmallett { 327232812Sjmallett cvmx_mio_qlmx_cfg_t mio_qlm_cfg; 328232812Sjmallett 329232812Sjmallett /* QLM2 is SGMII0 and QLM1 is SGMII1 */ 330232812Sjmallett if (interface == 0) 331232812Sjmallett mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); 332232812Sjmallett else if (interface == 1) 333232812Sjmallett mio_qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 334232812Sjmallett else 335232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 336232812Sjmallett 337232812Sjmallett if (mio_qlm_cfg.s.qlm_spd == 15) 338232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 339232812Sjmallett 340232812Sjmallett if (mio_qlm_cfg.s.qlm_cfg == 9) 341232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_SGMII; 342232812Sjmallett else if (mio_qlm_cfg.s.qlm_cfg == 11) 343232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_XAUI; 344232812Sjmallett else 345232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 346232812Sjmallett } 347232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 348232812Sjmallett { 349232812Sjmallett cvmx_mio_qlmx_cfg_t qlm_cfg; 350232812Sjmallett 351232812Sjmallett if (interface == 0) 352232812Sjmallett { 353232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(2)); 354232812Sjmallett if (qlm_cfg.s.qlm_cfg == 2) 355232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_SGMII; 356232812Sjmallett else if (qlm_cfg.s.qlm_cfg == 3) 357232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_XAUI; 358232812Sjmallett else 359232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 360232812Sjmallett } 361232812Sjmallett else if (interface == 1) 362232812Sjmallett { 363232812Sjmallett /* If QLM 1 is PEV0/PEM1 mode, them QLM0 cannot be SGMII/XAUI */ 364232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 365232812Sjmallett if (qlm_cfg.s.qlm_cfg == 1) 366232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 367232812Sjmallett 368232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(0)); 369232812Sjmallett if (qlm_cfg.s.qlm_cfg == 2) 370232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_SGMII; 371232812Sjmallett else if (qlm_cfg.s.qlm_cfg == 3) 372232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_XAUI; 373232812Sjmallett else 374232812Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 375232812Sjmallett } 376232812Sjmallett } 377232812Sjmallett 378210284Sjmallett if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1) 379210284Sjmallett { 380210284Sjmallett /* Lie about interface type of CN3005 board. This board has a switch on port 1 like 381210284Sjmallett ** the other evaluation boards, but it is connected over RGMII instead of GMII. Report 382210284Sjmallett ** GMII mode so that the speed is forced to 1 Gbit full duplex. Other than some initial configuration 383210284Sjmallett ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes. 384210284Sjmallett */ 385210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_GMII; 386210284Sjmallett } 387210284Sjmallett 388210284Sjmallett /* Interface 1 is always disabled on CN31XX and CN30XX */ 389232812Sjmallett if ((interface == 1) 390232812Sjmallett && (OCTEON_IS_MODEL(OCTEON_CN31XX) 391232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN30XX) 392232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN50XX) 393232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN52XX) 394232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CN63XX) 395232812Sjmallett || OCTEON_IS_MODEL(OCTEON_CNF71XX))) 396210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 397210284Sjmallett 398210284Sjmallett mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 399210284Sjmallett 400210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 401210284Sjmallett { 402210284Sjmallett switch(mode.cn56xx.mode) 403210284Sjmallett { 404210284Sjmallett case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 405210284Sjmallett case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 406210284Sjmallett case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII; 407210284Sjmallett case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG; 408210284Sjmallett default:return CVMX_HELPER_INTERFACE_MODE_DISABLED; 409210284Sjmallett } 410210284Sjmallett } 411232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN63XX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 412215990Sjmallett { 413232812Sjmallett switch(mode.cn63xx.mode) 414232812Sjmallett { 415232812Sjmallett case 0: return CVMX_HELPER_INTERFACE_MODE_SGMII; 416232812Sjmallett case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 417232812Sjmallett default: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 418232812Sjmallett } 419215990Sjmallett } 420210284Sjmallett else 421210284Sjmallett { 422210284Sjmallett if (!mode.s.en) 423210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_DISABLED; 424210284Sjmallett 425210284Sjmallett if (mode.s.type) 426210284Sjmallett { 427210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) 428210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_SPI; 429210284Sjmallett else 430210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_GMII; 431210284Sjmallett } 432210284Sjmallett else 433210284Sjmallett return CVMX_HELPER_INTERFACE_MODE_RGMII; 434210284Sjmallett } 435210284Sjmallett} 436215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 437215990SjmallettEXPORT_SYMBOL(cvmx_helper_interface_get_mode); 438215990Sjmallett#endif 439210284Sjmallett 440210284Sjmallett/** 441210284Sjmallett * @INTERNAL 442210284Sjmallett * Configure the IPD/PIP tagging and QoS options for a specific 443210284Sjmallett * port. This function determines the POW work queue entry 444210284Sjmallett * contents for a port. The setup performed here is controlled by 445210284Sjmallett * the defines in executive-config.h. 446210284Sjmallett * 447232812Sjmallett * @param ipd_port Port/Port kind to configure. This follows the IPD numbering, 448232812Sjmallett * not the per interface numbering 449210284Sjmallett * 450210284Sjmallett * @return Zero on success, negative on failure 451210284Sjmallett */ 452210284Sjmallettstatic int __cvmx_helper_port_setup_ipd(int ipd_port) 453210284Sjmallett{ 454215990Sjmallett cvmx_pip_prt_cfgx_t port_config; 455215990Sjmallett cvmx_pip_prt_tagx_t tag_config; 456210284Sjmallett 457232812Sjmallett if (octeon_has_feature(OCTEON_FEATURE_PKND)) 458232812Sjmallett { 459232812Sjmallett int interface, index, pknd; 460232812Sjmallett cvmx_pip_prt_cfgbx_t prt_cfgbx; 461210284Sjmallett 462232812Sjmallett interface = cvmx_helper_get_interface_num(ipd_port); 463232812Sjmallett index = cvmx_helper_get_interface_index_num(ipd_port); 464232812Sjmallett pknd = cvmx_helper_get_pknd(interface, index); 465210284Sjmallett 466232812Sjmallett port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd)); 467232812Sjmallett tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(pknd)); 468232812Sjmallett 469232812Sjmallett port_config.s.qos = pknd & 0x7; 470232812Sjmallett 471232812Sjmallett /* Default BPID to use for packets on this port-kind */ 472232812Sjmallett prt_cfgbx.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGBX(pknd)); 473232812Sjmallett prt_cfgbx.s.bpid = pknd; 474232812Sjmallett cvmx_write_csr(CVMX_PIP_PRT_CFGBX(pknd), prt_cfgbx.u64); 475232812Sjmallett } 476232812Sjmallett else 477232812Sjmallett { 478232812Sjmallett port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 479232812Sjmallett tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); 480232812Sjmallett 481232812Sjmallett /* Have each port go to a different POW queue */ 482232812Sjmallett port_config.s.qos = ipd_port & 0x7; 483232812Sjmallett } 484232812Sjmallett 485210284Sjmallett /* Process the headers and place the IP header in the work queue */ 486210284Sjmallett port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; 487210284Sjmallett 488210284Sjmallett tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; 489210284Sjmallett tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; 490210284Sjmallett tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; 491210284Sjmallett tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; 492210284Sjmallett tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; 493210284Sjmallett tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; 494210284Sjmallett tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; 495210284Sjmallett tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; 496210284Sjmallett tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; 497210284Sjmallett tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; 498210284Sjmallett tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; 499210284Sjmallett tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 500210284Sjmallett tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 501210284Sjmallett tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 502210284Sjmallett tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 503210284Sjmallett tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 504210284Sjmallett /* Put all packets in group 0. Other groups can be used by the app */ 505210284Sjmallett tag_config.s.grp = 0; 506210284Sjmallett 507210284Sjmallett cvmx_pip_config_port(ipd_port, port_config, tag_config); 508210284Sjmallett 509210284Sjmallett /* Give the user a chance to override our setting for each port */ 510210284Sjmallett if (cvmx_override_ipd_port_setup) 511210284Sjmallett cvmx_override_ipd_port_setup(ipd_port); 512210284Sjmallett 513210284Sjmallett return 0; 514210284Sjmallett} 515210284Sjmallett 516232812Sjmallett/** 517232812Sjmallett * Enable or disable FCS stripping for all the ports on an interface. 518232812Sjmallett * 519232812Sjmallett * @param interface 520232812Sjmallett * @param nports number of ports 521232812Sjmallett * @param has_fcs 0 for disable and !0 for enable 522232812Sjmallett */ 523232812Sjmallettstatic int cvmx_helper_fcs_op(int interface, int nports, int has_fcs) 524232812Sjmallett{ 525232812Sjmallett uint64_t port_bit; 526232812Sjmallett int index; 527232812Sjmallett int pknd; 528232812Sjmallett cvmx_pip_sub_pkind_fcsx_t pkind_fcsx; 529232812Sjmallett cvmx_pip_prt_cfgx_t port_cfg; 530232812Sjmallett 531232812Sjmallett if (!octeon_has_feature(OCTEON_FEATURE_PKND)) 532232812Sjmallett return 0; 533210284Sjmallett 534232812Sjmallett port_bit = 0; 535232812Sjmallett for (index = 0; index < nports; index++) 536232812Sjmallett port_bit |= ((uint64_t)1 << cvmx_helper_get_pknd(interface, index)); 537232812Sjmallett 538232812Sjmallett pkind_fcsx.u64 = cvmx_read_csr(CVMX_PIP_SUB_PKIND_FCSX(0)); 539232812Sjmallett if (has_fcs) 540232812Sjmallett pkind_fcsx.s.port_bit |= port_bit; 541232812Sjmallett else 542232812Sjmallett pkind_fcsx.s.port_bit &= ~port_bit; 543232812Sjmallett cvmx_write_csr(CVMX_PIP_SUB_PKIND_FCSX(0), pkind_fcsx.u64); 544232812Sjmallett 545232812Sjmallett for (pknd = 0; pknd < 64; pknd++) 546232812Sjmallett { 547232812Sjmallett if ((1ull << pknd) & port_bit) 548232812Sjmallett { 549232812Sjmallett port_cfg.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(pknd)); 550232812Sjmallett port_cfg.s.crc_en = (has_fcs) ? 1 : 0; 551232812Sjmallett cvmx_write_csr(CVMX_PIP_PRT_CFGX(pknd), port_cfg.u64); 552232812Sjmallett } 553232812Sjmallett } 554232812Sjmallett 555232812Sjmallett return 0; 556232812Sjmallett} 557232812Sjmallett 558210284Sjmallett/** 559232812Sjmallett * Determine the actual number of hardware ports connected to an 560232812Sjmallett * interface. It doesn't setup the ports or enable them. 561210284Sjmallett * 562232812Sjmallett * @param interface Interface to enumerate 563232812Sjmallett * 564232812Sjmallett * @return The number of ports on the interface, negative on failure 565232812Sjmallett */ 566232812Sjmallettint cvmx_helper_interface_enumerate(int interface) 567232812Sjmallett{ 568232812Sjmallett switch (cvmx_helper_interface_get_mode(interface)) { 569232812Sjmallett /* XAUI is a single high speed port */ 570232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 571232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 572232812Sjmallett return __cvmx_helper_xaui_enumerate(interface); 573232812Sjmallett /* RGMII/GMII/MII are all treated about the same. Most functions 574232812Sjmallett refer to these ports as RGMII */ 575232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 576232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 577232812Sjmallett return __cvmx_helper_rgmii_enumerate(interface); 578232812Sjmallett /* SPI4 can have 1-16 ports depending on the device at the other end */ 579232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 580232812Sjmallett return __cvmx_helper_spi_enumerate(interface); 581232812Sjmallett /* SGMII can have 1-4 ports depending on how many are hooked up */ 582232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 583232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 584232812Sjmallett return __cvmx_helper_sgmii_enumerate(interface); 585232812Sjmallett /* PCI target Network Packet Interface */ 586232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 587232812Sjmallett return __cvmx_helper_npi_enumerate(interface); 588232812Sjmallett /* Special loopback only ports. These are not the same 589232812Sjmallett * as other ports in loopback mode */ 590232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 591232812Sjmallett return __cvmx_helper_loop_enumerate(interface); 592232812Sjmallett /* SRIO has 2^N ports, where N is number of interfaces */ 593232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 594232812Sjmallett return __cvmx_helper_srio_enumerate(interface); 595232812Sjmallett 596232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 597232812Sjmallett return __cvmx_helper_ilk_enumerate(interface); 598232812Sjmallett /* These types don't support ports to IPD/PKO */ 599232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 600232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 601232812Sjmallett default: 602232812Sjmallett return 0; 603232812Sjmallett } 604232812Sjmallett} 605232812Sjmallett 606232812Sjmallett/** 607232812Sjmallett * This function probes an interface to determine the actual number of 608232812Sjmallett * hardware ports connected to it. It does some setup the ports but 609232812Sjmallett * doesn't enable them. The main goal here is to set the global 610232812Sjmallett * interface_port_count[interface] correctly. Final hardware setup of 611232812Sjmallett * the ports will be performed later. 612232812Sjmallett * 613210284Sjmallett * @param interface Interface to probe 614210284Sjmallett * 615210284Sjmallett * @return Zero on success, negative on failure 616210284Sjmallett */ 617210284Sjmallettint cvmx_helper_interface_probe(int interface) 618210284Sjmallett{ 619210284Sjmallett /* At this stage in the game we don't want packets to be moving yet. 620210284Sjmallett The following probe calls should perform hardware setup 621210284Sjmallett needed to determine port counts. Receive must still be disabled */ 622232812Sjmallett int nports; 623232812Sjmallett int has_fcs; 624232812Sjmallett enum cvmx_pko_padding padding = CVMX_PKO_PADDING_NONE; 625232812Sjmallett 626232812Sjmallett nports = -1; 627232812Sjmallett has_fcs = 0; 628210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 629210284Sjmallett { 630210284Sjmallett /* These types don't support ports to IPD/PKO */ 631210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 632210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 633232812Sjmallett nports = 0; 634210284Sjmallett break; 635210284Sjmallett /* XAUI is a single high speed port */ 636210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 637232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 638232812Sjmallett nports = __cvmx_helper_xaui_probe(interface); 639232812Sjmallett has_fcs = 1; 640232812Sjmallett padding = CVMX_PKO_PADDING_60; 641210284Sjmallett break; 642210284Sjmallett /* RGMII/GMII/MII are all treated about the same. Most functions 643210284Sjmallett refer to these ports as RGMII */ 644210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 645210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 646232812Sjmallett nports = __cvmx_helper_rgmii_probe(interface); 647232812Sjmallett padding = CVMX_PKO_PADDING_60; 648210284Sjmallett break; 649210284Sjmallett /* SPI4 can have 1-16 ports depending on the device at the other end */ 650210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 651232812Sjmallett nports = __cvmx_helper_spi_probe(interface); 652232812Sjmallett padding = CVMX_PKO_PADDING_60; 653210284Sjmallett break; 654210284Sjmallett /* SGMII can have 1-4 ports depending on how many are hooked up */ 655210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 656232812Sjmallett padding = CVMX_PKO_PADDING_60; 657210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 658232812Sjmallett nports = __cvmx_helper_sgmii_probe(interface); 659232812Sjmallett has_fcs = 1; 660210284Sjmallett break; 661210284Sjmallett /* PCI target Network Packet Interface */ 662210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 663232812Sjmallett nports = __cvmx_helper_npi_probe(interface); 664210284Sjmallett break; 665210284Sjmallett /* Special loopback only ports. These are not the same as other ports 666210284Sjmallett in loopback mode */ 667210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 668232812Sjmallett nports = __cvmx_helper_loop_probe(interface); 669210284Sjmallett break; 670232812Sjmallett /* SRIO has 2^N ports, where N is number of interfaces */ 671232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 672232812Sjmallett nports = __cvmx_helper_srio_probe(interface); 673232812Sjmallett break; 674232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 675232812Sjmallett nports = __cvmx_helper_ilk_probe(interface); 676232812Sjmallett has_fcs = 1; 677232812Sjmallett padding = CVMX_PKO_PADDING_60; 678232812Sjmallett break; 679210284Sjmallett } 680210284Sjmallett 681232812Sjmallett if (nports == -1) 682232812Sjmallett return -1; 683210284Sjmallett 684232812Sjmallett if (!octeon_has_feature(OCTEON_FEATURE_PKND)) 685232812Sjmallett has_fcs = 0; 686232812Sjmallett 687232812Sjmallett nports = __cvmx_helper_board_interface_probe(interface, nports); 688232812Sjmallett __cvmx_helper_init_interface(interface, nports, has_fcs, padding); 689232812Sjmallett cvmx_helper_fcs_op(interface, nports, has_fcs); 690232812Sjmallett 691210284Sjmallett /* Make sure all global variables propagate to other cores */ 692210284Sjmallett CVMX_SYNCWS; 693210284Sjmallett 694210284Sjmallett return 0; 695210284Sjmallett} 696210284Sjmallett 697210284Sjmallett 698210284Sjmallett/** 699210284Sjmallett * @INTERNAL 700210284Sjmallett * Setup the IPD/PIP for the ports on an interface. Packet 701210284Sjmallett * classification and tagging are set for every port on the 702210284Sjmallett * interface. The number of ports on the interface must already 703210284Sjmallett * have been probed. 704210284Sjmallett * 705210284Sjmallett * @param interface Interface to setup IPD/PIP for 706210284Sjmallett * 707210284Sjmallett * @return Zero on success, negative on failure 708210284Sjmallett */ 709210284Sjmallettstatic int __cvmx_helper_interface_setup_ipd(int interface) 710210284Sjmallett{ 711232812Sjmallett 712232812Sjmallett cvmx_helper_interface_mode_t mode; 713210284Sjmallett int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 714232812Sjmallett int num_ports = cvmx_helper_ports_on_interface(interface); 715232812Sjmallett int delta; 716210284Sjmallett 717232812Sjmallett if (num_ports == CVMX_HELPER_CFG_INVALID_VALUE) 718232812Sjmallett return 0; 719232812Sjmallett 720232812Sjmallett mode = cvmx_helper_interface_get_mode(interface); 721232812Sjmallett 722232812Sjmallett if (mode == CVMX_HELPER_INTERFACE_MODE_LOOP) 723232812Sjmallett __cvmx_helper_loop_enable(interface); 724232812Sjmallett 725232812Sjmallett delta = 1; 726232812Sjmallett if (octeon_has_feature(OCTEON_FEATURE_PKND)) 727232812Sjmallett { 728232812Sjmallett if (mode == CVMX_HELPER_INTERFACE_MODE_SGMII) 729232812Sjmallett delta = 16; 730232812Sjmallett } 731232812Sjmallett 732210284Sjmallett while (num_ports--) 733210284Sjmallett { 734210284Sjmallett __cvmx_helper_port_setup_ipd(ipd_port); 735232812Sjmallett ipd_port += delta; 736210284Sjmallett } 737232812Sjmallett 738210284Sjmallett return 0; 739210284Sjmallett} 740210284Sjmallett 741210284Sjmallett 742210284Sjmallett/** 743210284Sjmallett * @INTERNAL 744210284Sjmallett * Setup global setting for IPD/PIP not related to a specific 745210284Sjmallett * interface or port. This must be called before IPD is enabled. 746210284Sjmallett * 747210284Sjmallett * @return Zero on success, negative on failure. 748210284Sjmallett */ 749210284Sjmallettstatic int __cvmx_helper_global_setup_ipd(void) 750210284Sjmallett{ 751215990Sjmallett#ifndef CVMX_HELPER_IPD_DRAM_MODE 752215990Sjmallett#define CVMX_HELPER_IPD_DRAM_MODE CVMX_IPD_OPC_MODE_STT 753215990Sjmallett#endif 754210284Sjmallett /* Setup the global packet input options */ 755210284Sjmallett cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8, 756210284Sjmallett CVMX_HELPER_FIRST_MBUFF_SKIP/8, 757210284Sjmallett CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8, 758210284Sjmallett (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 759210284Sjmallett (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 760210284Sjmallett CVMX_FPA_WQE_POOL, 761215990Sjmallett CVMX_HELPER_IPD_DRAM_MODE, 762215990Sjmallett 1); 763210284Sjmallett return 0; 764210284Sjmallett} 765210284Sjmallett 766210284Sjmallett 767210284Sjmallett/** 768210284Sjmallett * @INTERNAL 769210284Sjmallett * Setup the PKO for the ports on an interface. The number of 770210284Sjmallett * queues per port and the priority of each PKO output queue 771210284Sjmallett * is set here. PKO must be disabled when this function is called. 772210284Sjmallett * 773210284Sjmallett * @param interface Interface to setup PKO for 774210284Sjmallett * 775210284Sjmallett * @return Zero on success, negative on failure 776210284Sjmallett */ 777210284Sjmallettstatic int __cvmx_helper_interface_setup_pko(int interface) 778210284Sjmallett{ 779210284Sjmallett /* Each packet output queue has an associated priority. The higher the 780210284Sjmallett priority, the more often it can send a packet. A priority of 8 means 781210284Sjmallett it can send in all 8 rounds of contention. We're going to make each 782210284Sjmallett queue one less than the last. 783210284Sjmallett The vector of priorities has been extended to support CN5xxx CPUs, 784210284Sjmallett where up to 16 queues can be associated to a port. 785210284Sjmallett To keep backward compatibility we don't change the initial 8 786210284Sjmallett priorities and replicate them in the second half. 787210284Sjmallett With per-core PKO queues (PKO lockless operation) all queues have 788210284Sjmallett the same priority. */ 789232812Sjmallett /* uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; */ 790232812Sjmallett uint64_t priorities[16] = {[0 ... 15] = 8}; 791210284Sjmallett 792210284Sjmallett /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet 793210284Sjmallett classification, tagging and output priorities are set */ 794210284Sjmallett int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 795232812Sjmallett int num_ports = cvmx_helper_ports_on_interface(interface); 796210284Sjmallett while (num_ports--) 797210284Sjmallett { 798210284Sjmallett /* Give the user a chance to override the per queue priorities */ 799210284Sjmallett if (cvmx_override_pko_queue_priority) 800210284Sjmallett cvmx_override_pko_queue_priority(ipd_port, priorities); 801210284Sjmallett 802210284Sjmallett cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0), 803210284Sjmallett cvmx_pko_get_num_queues(ipd_port), priorities); 804210284Sjmallett ipd_port++; 805210284Sjmallett } 806210284Sjmallett return 0; 807210284Sjmallett} 808210284Sjmallett 809210284Sjmallett 810210284Sjmallett/** 811210284Sjmallett * @INTERNAL 812210284Sjmallett * Setup global setting for PKO not related to a specific 813210284Sjmallett * interface or port. This must be called before PKO is enabled. 814210284Sjmallett * 815210284Sjmallett * @return Zero on success, negative on failure. 816210284Sjmallett */ 817210284Sjmallettstatic int __cvmx_helper_global_setup_pko(void) 818210284Sjmallett{ 819210284Sjmallett /* Disable tagwait FAU timeout. This needs to be done before anyone might 820210284Sjmallett start packet output using tags */ 821210284Sjmallett cvmx_iob_fau_timeout_t fau_to; 822210284Sjmallett fau_to.u64 = 0; 823210284Sjmallett fau_to.s.tout_val = 0xfff; 824210284Sjmallett fau_to.s.tout_enb = 0; 825210284Sjmallett cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 826232812Sjmallett 827232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { 828232812Sjmallett cvmx_pko_reg_min_pkt_t min_pkt; 829232812Sjmallett 830232812Sjmallett min_pkt.u64 = 0; 831232812Sjmallett min_pkt.s.size1 = 59; 832232812Sjmallett min_pkt.s.size2 = 59; 833232812Sjmallett min_pkt.s.size3 = 59; 834232812Sjmallett min_pkt.s.size4 = 59; 835232812Sjmallett min_pkt.s.size5 = 59; 836232812Sjmallett min_pkt.s.size6 = 59; 837232812Sjmallett min_pkt.s.size7 = 59; 838232812Sjmallett cvmx_write_csr(CVMX_PKO_REG_MIN_PKT, min_pkt.u64); 839232812Sjmallett } 840232812Sjmallett 841210284Sjmallett return 0; 842210284Sjmallett} 843210284Sjmallett 844210284Sjmallett 845210284Sjmallett/** 846210284Sjmallett * @INTERNAL 847210284Sjmallett * Setup global backpressure setting. 848210284Sjmallett * 849210284Sjmallett * @return Zero on success, negative on failure 850210284Sjmallett */ 851210284Sjmallettstatic int __cvmx_helper_global_setup_backpressure(void) 852210284Sjmallett{ 853210284Sjmallett#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 854210284Sjmallett /* Disable backpressure if configured to do so */ 855210284Sjmallett /* Disable backpressure (pause frame) generation */ 856210284Sjmallett int num_interfaces = cvmx_helper_get_number_of_interfaces(); 857210284Sjmallett int interface; 858210284Sjmallett for (interface=0; interface<num_interfaces; interface++) 859210284Sjmallett { 860210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 861210284Sjmallett { 862210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 863210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 864215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 865232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 866210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 867210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 868210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 869232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 870210284Sjmallett break; 871210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 872210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 873210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 874210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 875210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 876210284Sjmallett cvmx_gmx_set_backpressure_override(interface, 0xf); 877210284Sjmallett break; 878210284Sjmallett } 879210284Sjmallett } 880210284Sjmallett //cvmx_dprintf("Disabling backpressure\n"); 881210284Sjmallett#endif 882210284Sjmallett 883210284Sjmallett return 0; 884210284Sjmallett} 885210284Sjmallett 886215990Sjmallett/** 887215990Sjmallett * @INTERNAL 888215990Sjmallett * Verify the per port IPD backpressure is aligned properly. 889215990Sjmallett * @return Zero if working, non zero if misaligned 890215990Sjmallett */ 891215990Sjmallettstatic int __cvmx_helper_backpressure_is_misaligned(void) 892215990Sjmallett{ 893215990Sjmallett uint64_t ipd_int_enb; 894215990Sjmallett cvmx_ipd_ctl_status_t ipd_reg; 895215990Sjmallett uint64_t bp_status0; 896215990Sjmallett uint64_t bp_status1; 897215990Sjmallett const int port0 = 0; 898215990Sjmallett const int port1 = 16; 899215990Sjmallett cvmx_helper_interface_mode_t mode0 = cvmx_helper_interface_get_mode(0); 900215990Sjmallett cvmx_helper_interface_mode_t mode1 = cvmx_helper_interface_get_mode(1); 901210284Sjmallett 902215990Sjmallett /* Disable error interrupts while we check backpressure */ 903215990Sjmallett ipd_int_enb = cvmx_read_csr(CVMX_IPD_INT_ENB); 904215990Sjmallett cvmx_write_csr(CVMX_IPD_INT_ENB, 0); 905215990Sjmallett 906215990Sjmallett /* Enable per port backpressure */ 907215990Sjmallett ipd_reg.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 908215990Sjmallett ipd_reg.s.pbp_en = 1; 909215990Sjmallett cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_reg.u64); 910215990Sjmallett 911215990Sjmallett if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 912215990Sjmallett { 913215990Sjmallett /* Enable backpressure for port with a zero threshold */ 914215990Sjmallett cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 1<<17); 915215990Sjmallett /* Add 1000 to the page count to simulate packets coming in */ 916215990Sjmallett cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | 1000); 917215990Sjmallett } 918215990Sjmallett 919215990Sjmallett if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 920215990Sjmallett { 921215990Sjmallett /* Enable backpressure for port with a zero threshold */ 922215990Sjmallett cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 1<<17); 923215990Sjmallett /* Add 1000 to the page count to simulate packets coming in */ 924215990Sjmallett cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | 1000); 925215990Sjmallett } 926215990Sjmallett 927215990Sjmallett /* Wait 500 cycles for the BP to update */ 928215990Sjmallett cvmx_wait(500); 929215990Sjmallett 930215990Sjmallett /* Read the BP state from the debug select register */ 931215990Sjmallett switch (mode0) 932215990Sjmallett { 933215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 934215990Sjmallett cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9004); 935215990Sjmallett bp_status0 = cvmx_read_csr(CVMX_DBG_DATA); 936215990Sjmallett bp_status0 = 0xffff & ~bp_status0; 937215990Sjmallett break; 938215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 939215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 940215990Sjmallett cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x0e00); 941215990Sjmallett bp_status0 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 942215990Sjmallett break; 943215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 944215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 945215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 946215990Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x0e00); 947215990Sjmallett bp_status0 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 948215990Sjmallett break; 949215990Sjmallett default: 950215990Sjmallett bp_status0 = 1<<port0; 951215990Sjmallett break; 952215990Sjmallett } 953215990Sjmallett 954215990Sjmallett /* Read the BP state from the debug select register */ 955215990Sjmallett switch (mode1) 956215990Sjmallett { 957215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 958215990Sjmallett cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x9804); 959215990Sjmallett bp_status1 = cvmx_read_csr(CVMX_DBG_DATA); 960215990Sjmallett bp_status1 = 0xffff & ~bp_status1; 961215990Sjmallett break; 962215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 963215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 964215990Sjmallett cvmx_write_csr(CVMX_NPI_DBG_SELECT, 0x1600); 965215990Sjmallett bp_status1 = 0xffff & cvmx_read_csr(CVMX_DBG_DATA); 966215990Sjmallett break; 967215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 968215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 969215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 970215990Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, 0x1600); 971215990Sjmallett bp_status1 = 0xffff & cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 972215990Sjmallett break; 973215990Sjmallett default: 974215990Sjmallett bp_status1 = 1<<(port1-16); 975215990Sjmallett break; 976215990Sjmallett } 977215990Sjmallett 978215990Sjmallett if (mode0 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 979215990Sjmallett { 980215990Sjmallett /* Shutdown BP */ 981215990Sjmallett cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port0<<25) | (0x1ffffff & -1000)); 982215990Sjmallett cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port0), 0); 983215990Sjmallett } 984215990Sjmallett 985215990Sjmallett if (mode1 != CVMX_HELPER_INTERFACE_MODE_DISABLED) 986215990Sjmallett { 987215990Sjmallett /* Shutdown BP */ 988215990Sjmallett cvmx_write_csr(CVMX_IPD_SUB_PORT_BP_PAGE_CNT, (port1<<25) | (0x1ffffff & -1000)); 989215990Sjmallett cvmx_write_csr(CVMX_IPD_PORTX_BP_PAGE_CNT(port1), 0); 990215990Sjmallett } 991215990Sjmallett 992215990Sjmallett /* Clear any error interrupts that might have been set */ 993215990Sjmallett cvmx_write_csr(CVMX_IPD_INT_SUM, 0x1f); 994215990Sjmallett cvmx_write_csr(CVMX_IPD_INT_ENB, ipd_int_enb); 995215990Sjmallett 996215990Sjmallett return ((bp_status0 != 1ull<<port0) || (bp_status1 != 1ull<<(port1-16))); 997215990Sjmallett} 998215990Sjmallett 999215990Sjmallett 1000210284Sjmallett/** 1001210284Sjmallett * @INTERNAL 1002210284Sjmallett * Enable packet input/output from the hardware. This function is 1003210284Sjmallett * called after all internal setup is complete and IPD is enabled. 1004210284Sjmallett * After this function completes, packets will be accepted from the 1005210284Sjmallett * hardware ports. PKO should still be disabled to make sure packets 1006210284Sjmallett * aren't sent out partially setup hardware. 1007210284Sjmallett * 1008210284Sjmallett * @param interface Interface to enable 1009210284Sjmallett * 1010210284Sjmallett * @return Zero on success, negative on failure 1011210284Sjmallett */ 1012210284Sjmallettstatic int __cvmx_helper_packet_hardware_enable(int interface) 1013210284Sjmallett{ 1014210284Sjmallett int result = 0; 1015210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1016210284Sjmallett { 1017210284Sjmallett /* These types don't support ports to IPD/PKO */ 1018210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1019210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1020232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1021210284Sjmallett /* Nothing to do */ 1022210284Sjmallett break; 1023210284Sjmallett /* XAUI is a single high speed port */ 1024210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1025232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1026210284Sjmallett result = __cvmx_helper_xaui_enable(interface); 1027210284Sjmallett break; 1028210284Sjmallett /* RGMII/GMII/MII are all treated about the same. Most functions 1029210284Sjmallett refer to these ports as RGMII */ 1030210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1031210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1032210284Sjmallett result = __cvmx_helper_rgmii_enable(interface); 1033210284Sjmallett break; 1034210284Sjmallett /* SPI4 can have 1-16 ports depending on the device at the other end */ 1035210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1036210284Sjmallett result = __cvmx_helper_spi_enable(interface); 1037210284Sjmallett break; 1038210284Sjmallett /* SGMII can have 1-4 ports depending on how many are hooked up */ 1039210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1040210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1041210284Sjmallett result = __cvmx_helper_sgmii_enable(interface); 1042210284Sjmallett break; 1043210284Sjmallett /* PCI target Network Packet Interface */ 1044210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1045210284Sjmallett result = __cvmx_helper_npi_enable(interface); 1046210284Sjmallett break; 1047232812Sjmallett /* SRIO has 2^N ports, where N is number of interfaces */ 1048232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1049232812Sjmallett result = __cvmx_helper_srio_enable(interface); 1050210284Sjmallett break; 1051232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1052232812Sjmallett result = __cvmx_helper_ilk_enable(interface); 1053232812Sjmallett break; 1054210284Sjmallett } 1055210284Sjmallett result |= __cvmx_helper_board_hardware_enable(interface); 1056210284Sjmallett return result; 1057210284Sjmallett} 1058210284Sjmallett 1059210284Sjmallett 1060210284Sjmallett/** 1061210284Sjmallett * Called after all internal packet IO paths are setup. This 1062210284Sjmallett * function enables IPD/PIP and begins packet input and output. 1063210284Sjmallett * 1064210284Sjmallett * @return Zero on success, negative on failure 1065210284Sjmallett */ 1066210284Sjmallettint cvmx_helper_ipd_and_packet_input_enable(void) 1067210284Sjmallett{ 1068210284Sjmallett int num_interfaces; 1069210284Sjmallett int interface; 1070210284Sjmallett 1071210284Sjmallett /* Enable IPD */ 1072210284Sjmallett cvmx_ipd_enable(); 1073210284Sjmallett 1074210284Sjmallett /* Time to enable hardware ports packet input and output. Note that at this 1075210284Sjmallett point IPD/PIP must be fully functional and PKO must be disabled */ 1076210284Sjmallett num_interfaces = cvmx_helper_get_number_of_interfaces(); 1077210284Sjmallett for (interface=0; interface<num_interfaces; interface++) 1078210284Sjmallett { 1079210284Sjmallett if (cvmx_helper_ports_on_interface(interface) > 0) 1080210284Sjmallett { 1081210284Sjmallett //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface); 1082210284Sjmallett __cvmx_helper_packet_hardware_enable(interface); 1083210284Sjmallett } 1084210284Sjmallett } 1085210284Sjmallett 1086210284Sjmallett /* Finally enable PKO now that the entire path is up and running */ 1087210284Sjmallett cvmx_pko_enable(); 1088210284Sjmallett 1089210284Sjmallett if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) && 1090210284Sjmallett (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) 1091210284Sjmallett __cvmx_helper_errata_fix_ipd_ptr_alignment(); 1092210284Sjmallett return 0; 1093210284Sjmallett} 1094215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1095215990SjmallettEXPORT_SYMBOL(cvmx_helper_ipd_and_packet_input_enable); 1096215990Sjmallett#endif 1097210284Sjmallett 1098232812Sjmallett#define __CVMX_SSO_RWQ_SIZE 256 1099232812Sjmallett 1100232812Sjmallettint cvmx_helper_initialize_sso(int wqe_entries) 1101232812Sjmallett{ 1102232812Sjmallett int cvm_oct_sso_number_rwq_bufs; 1103232812Sjmallett char *mem; 1104232812Sjmallett int i; 1105232812Sjmallett cvmx_sso_cfg_t sso_cfg; 1106232812Sjmallett cvmx_fpa_fpfx_marks_t fpa_marks; 1107232812Sjmallett 1108232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1109232812Sjmallett return 0; 1110232812Sjmallett 1111232812Sjmallett /* 1112232812Sjmallett * CN68XX-P1 may reset with the wrong values, put in 1113232812Sjmallett * the correct values. 1114232812Sjmallett */ 1115232812Sjmallett fpa_marks.u64 = 0; 1116232812Sjmallett fpa_marks.s.fpf_wr = 0xa4; 1117232812Sjmallett fpa_marks.s.fpf_rd = 0x40; 1118232812Sjmallett cvmx_write_csr(CVMX_FPA_FPF8_MARKS, fpa_marks.u64); 1119232812Sjmallett 1120232812Sjmallett cvm_oct_sso_number_rwq_bufs = ((wqe_entries - 1) / 26) + 1 + 48 + 8; 1121232812Sjmallett 1122232812Sjmallett mem = cvmx_bootmem_alloc(__CVMX_SSO_RWQ_SIZE * cvm_oct_sso_number_rwq_bufs, CVMX_CACHE_LINE_SIZE); 1123232812Sjmallett if (mem == NULL) { 1124232812Sjmallett cvmx_dprintf("Out of memory initializing sso pool\n"); 1125232812Sjmallett return -1; 1126232812Sjmallett } 1127232812Sjmallett /* Make sure RWI/RWO is disabled. */ 1128232812Sjmallett sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1129232812Sjmallett sso_cfg.s.rwen = 0; 1130232812Sjmallett cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1131232812Sjmallett 1132232812Sjmallett for (i = cvm_oct_sso_number_rwq_bufs - 8; i > 0; i--) { 1133232812Sjmallett cvmx_sso_rwq_psh_fptr_t fptr; 1134232812Sjmallett 1135232812Sjmallett for (;;) { 1136232812Sjmallett fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR); 1137232812Sjmallett if (!fptr.s.full) 1138232812Sjmallett break; 1139232812Sjmallett cvmx_wait(1000); 1140232812Sjmallett } 1141232812Sjmallett fptr.s.fptr = cvmx_ptr_to_phys(mem) >> 7; 1142232812Sjmallett cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64); 1143232812Sjmallett mem = mem + __CVMX_SSO_RWQ_SIZE; 1144232812Sjmallett } 1145232812Sjmallett 1146232812Sjmallett for (i = 0; i < 8; i++) { 1147232812Sjmallett cvmx_sso_rwq_head_ptrx_t head_ptr; 1148232812Sjmallett cvmx_sso_rwq_tail_ptrx_t tail_ptr; 1149232812Sjmallett 1150232812Sjmallett head_ptr.u64 = 0; 1151232812Sjmallett tail_ptr.u64 = 0; 1152232812Sjmallett head_ptr.s.ptr = cvmx_ptr_to_phys(mem) >> 7; 1153232812Sjmallett tail_ptr.s.ptr = head_ptr.s.ptr; 1154232812Sjmallett cvmx_write_csr(CVMX_SSO_RWQ_HEAD_PTRX(i), head_ptr.u64); 1155232812Sjmallett cvmx_write_csr(CVMX_SSO_RWQ_TAIL_PTRX(i), tail_ptr.u64); 1156232812Sjmallett mem = mem + __CVMX_SSO_RWQ_SIZE; 1157232812Sjmallett } 1158232812Sjmallett 1159232812Sjmallett sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1160232812Sjmallett sso_cfg.s.rwen = 1; 1161232812Sjmallett sso_cfg.s.dwb = cvmx_helper_cfg_opt_get(CVMX_HELPER_CFG_OPT_USE_DWB); 1162232812Sjmallett sso_cfg.s.rwq_byp_dis = 0; 1163232812Sjmallett sso_cfg.s.rwio_byp_dis = 0; 1164232812Sjmallett cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1165232812Sjmallett 1166232812Sjmallett return 0; 1167232812Sjmallett} 1168232812Sjmallett 1169232812Sjmallettint cvmx_helper_uninitialize_sso(void) 1170232812Sjmallett{ 1171232812Sjmallett cvmx_fpa_quex_available_t queue_available; 1172232812Sjmallett cvmx_sso_cfg_t sso_cfg; 1173232812Sjmallett cvmx_sso_rwq_pop_fptr_t pop_fptr; 1174232812Sjmallett cvmx_sso_rwq_psh_fptr_t fptr; 1175232812Sjmallett cvmx_sso_fpage_cnt_t fpage_cnt; 1176232812Sjmallett int num_to_transfer, i; 1177232812Sjmallett char *mem; 1178232812Sjmallett 1179232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1180232812Sjmallett return 0; 1181232812Sjmallett 1182232812Sjmallett sso_cfg.u64 = cvmx_read_csr(CVMX_SSO_CFG); 1183232812Sjmallett sso_cfg.s.rwen = 0; 1184232812Sjmallett sso_cfg.s.rwq_byp_dis = 1; 1185232812Sjmallett cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1186232812Sjmallett cvmx_read_csr(CVMX_SSO_CFG); 1187232812Sjmallett queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8)); 1188232812Sjmallett 1189232812Sjmallett /* Make CVMX_FPA_QUEX_AVAILABLE(8) % 16 == 0*/ 1190232812Sjmallett for (num_to_transfer = (16 - queue_available.s.que_siz) % 16; 1191232812Sjmallett num_to_transfer > 0; num_to_transfer--) { 1192232812Sjmallett do { 1193232812Sjmallett pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR); 1194232812Sjmallett } while (!pop_fptr.s.val); 1195232812Sjmallett for (;;) { 1196232812Sjmallett fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_PSH_FPTR); 1197232812Sjmallett if (!fptr.s.full) 1198232812Sjmallett break; 1199232812Sjmallett cvmx_wait(1000); 1200232812Sjmallett } 1201232812Sjmallett fptr.s.fptr = pop_fptr.s.fptr; 1202232812Sjmallett cvmx_write_csr(CVMX_SSO_RWQ_PSH_FPTR, fptr.u64); 1203232812Sjmallett } 1204232812Sjmallett cvmx_read_csr(CVMX_SSO_CFG); 1205232812Sjmallett 1206232812Sjmallett do { 1207232812Sjmallett queue_available.u64 = cvmx_read_csr(CVMX_FPA_QUEX_AVAILABLE(8)); 1208232812Sjmallett } while (queue_available.s.que_siz % 16); 1209232812Sjmallett 1210232812Sjmallett sso_cfg.s.rwen = 1; 1211232812Sjmallett sso_cfg.s.rwq_byp_dis = 0; 1212232812Sjmallett cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1213232812Sjmallett 1214232812Sjmallett for (i = 0; i < 8; i++) { 1215232812Sjmallett cvmx_sso_rwq_head_ptrx_t head_ptr; 1216232812Sjmallett cvmx_sso_rwq_tail_ptrx_t tail_ptr; 1217232812Sjmallett 1218232812Sjmallett head_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_HEAD_PTRX(i)); 1219232812Sjmallett tail_ptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_TAIL_PTRX(i)); 1220232812Sjmallett if (head_ptr.s.ptr != tail_ptr.s.ptr) { 1221232812Sjmallett cvmx_dprintf("head_ptr.s.ptr != tail_ptr.s.ptr, idx: %d\n", i); 1222232812Sjmallett } 1223232812Sjmallett 1224232812Sjmallett mem = cvmx_phys_to_ptr(((uint64_t)head_ptr.s.ptr) << 7); 1225232812Sjmallett /* Leak the memory */ 1226232812Sjmallett } 1227232812Sjmallett 1228232812Sjmallett do { 1229232812Sjmallett do { 1230232812Sjmallett pop_fptr.u64 = cvmx_read_csr(CVMX_SSO_RWQ_POP_FPTR); 1231232812Sjmallett if (pop_fptr.s.val) { 1232232812Sjmallett mem = cvmx_phys_to_ptr(((uint64_t)pop_fptr.s.fptr) << 7); 1233232812Sjmallett /* Leak the memory */ 1234232812Sjmallett } 1235232812Sjmallett } while (pop_fptr.s.val); 1236232812Sjmallett fpage_cnt.u64 = cvmx_read_csr(CVMX_SSO_FPAGE_CNT); 1237232812Sjmallett } while (fpage_cnt.s.fpage_cnt); 1238232812Sjmallett 1239232812Sjmallett sso_cfg.s.rwen = 0; 1240232812Sjmallett sso_cfg.s.rwq_byp_dis = 0; 1241232812Sjmallett cvmx_write_csr(CVMX_SSO_CFG, sso_cfg.u64); 1242232812Sjmallett 1243232812Sjmallett return 0; 1244232812Sjmallett} 1245232812Sjmallett 1246210284Sjmallett/** 1247210284Sjmallett * Initialize the PIP, IPD, and PKO hardware to support 1248210284Sjmallett * simple priority based queues for the ethernet ports. Each 1249210284Sjmallett * port is configured with a number of priority queues based 1250210284Sjmallett * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower 1251210284Sjmallett * priority than the previous. 1252210284Sjmallett * 1253210284Sjmallett * @return Zero on success, non-zero on failure 1254210284Sjmallett */ 1255210284Sjmallettint cvmx_helper_initialize_packet_io_global(void) 1256210284Sjmallett{ 1257210284Sjmallett int result = 0; 1258210284Sjmallett int interface; 1259210284Sjmallett cvmx_l2c_cfg_t l2c_cfg; 1260210284Sjmallett cvmx_smix_en_t smix_en; 1261210284Sjmallett const int num_interfaces = cvmx_helper_get_number_of_interfaces(); 1262210284Sjmallett 1263210284Sjmallett /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */ 1264210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 1265210284Sjmallett __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); 1266210284Sjmallett 1267210284Sjmallett /* Tell L2 to give the IOB statically higher priority compared to the 1268210284Sjmallett cores. This avoids conditions where IO blocks might be starved under 1269210284Sjmallett very high L2 loads */ 1270232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF7XXX)) 1271210284Sjmallett { 1272215990Sjmallett cvmx_l2c_ctl_t l2c_ctl; 1273215990Sjmallett l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL); 1274215990Sjmallett l2c_ctl.s.rsp_arb_mode = 1; 1275215990Sjmallett l2c_ctl.s.xmc_arb_mode = 0; 1276215990Sjmallett cvmx_write_csr(CVMX_L2C_CTL, l2c_ctl.u64); 1277210284Sjmallett } 1278215990Sjmallett else 1279215990Sjmallett { 1280215990Sjmallett l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 1281215990Sjmallett l2c_cfg.s.lrf_arb_mode = 0; 1282215990Sjmallett l2c_cfg.s.rfb_arb_mode = 0; 1283215990Sjmallett cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); 1284215990Sjmallett } 1285210284Sjmallett 1286215990Sjmallett if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 1287210284Sjmallett { 1288232812Sjmallett int smi_inf = 1; 1289232812Sjmallett int i; 1290215990Sjmallett 1291232812Sjmallett /* Newer chips have more than one SMI/MDIO interface */ 1292232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 1293232812Sjmallett smi_inf = 4; 1294232812Sjmallett else if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) 1295232812Sjmallett && !OCTEON_IS_MODEL(OCTEON_CN58XX) 1296232812Sjmallett && !OCTEON_IS_MODEL(OCTEON_CN50XX)) 1297232812Sjmallett smi_inf = 2; 1298232812Sjmallett 1299232812Sjmallett for (i = 0; i < smi_inf; i++) 1300215990Sjmallett { 1301232812Sjmallett /* Make sure SMI/MDIO is enabled so we can query PHYs */ 1302232812Sjmallett smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(i)); 1303215990Sjmallett if (!smix_en.s.en) 1304215990Sjmallett { 1305215990Sjmallett smix_en.s.en = 1; 1306232812Sjmallett cvmx_write_csr(CVMX_SMIX_EN(i), smix_en.u64); 1307215990Sjmallett } 1308215990Sjmallett } 1309210284Sjmallett } 1310210284Sjmallett 1311232812Sjmallett __cvmx_helper_cfg_init(); 1312232812Sjmallett 1313215990Sjmallett for (interface=0; interface<num_interfaces; interface++) 1314215990Sjmallett result |= cvmx_helper_interface_probe(interface); 1315215990Sjmallett 1316210284Sjmallett cvmx_pko_initialize_global(); 1317210284Sjmallett for (interface=0; interface<num_interfaces; interface++) 1318210284Sjmallett { 1319210284Sjmallett if (cvmx_helper_ports_on_interface(interface) > 0) 1320210284Sjmallett cvmx_dprintf("Interface %d has %d ports (%s)\n", 1321210284Sjmallett interface, cvmx_helper_ports_on_interface(interface), 1322210284Sjmallett cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface))); 1323210284Sjmallett result |= __cvmx_helper_interface_setup_ipd(interface); 1324232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 1325232812Sjmallett result |= __cvmx_helper_interface_setup_pko(interface); 1326210284Sjmallett } 1327210284Sjmallett 1328210284Sjmallett result |= __cvmx_helper_global_setup_ipd(); 1329210284Sjmallett result |= __cvmx_helper_global_setup_pko(); 1330210284Sjmallett 1331210284Sjmallett /* Enable any flow control and backpressure */ 1332210284Sjmallett result |= __cvmx_helper_global_setup_backpressure(); 1333210284Sjmallett 1334210284Sjmallett#if CVMX_HELPER_ENABLE_IPD 1335210284Sjmallett result |= cvmx_helper_ipd_and_packet_input_enable(); 1336210284Sjmallett#endif 1337210284Sjmallett return result; 1338210284Sjmallett} 1339215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1340215990SjmallettEXPORT_SYMBOL(cvmx_helper_initialize_packet_io_global); 1341215990Sjmallett#endif 1342210284Sjmallett 1343210284Sjmallett 1344210284Sjmallett/** 1345210284Sjmallett * Does core local initialization for packet io 1346210284Sjmallett * 1347210284Sjmallett * @return Zero on success, non-zero on failure 1348210284Sjmallett */ 1349210284Sjmallettint cvmx_helper_initialize_packet_io_local(void) 1350210284Sjmallett{ 1351210284Sjmallett return cvmx_pko_initialize_local(); 1352210284Sjmallett} 1353210284Sjmallett 1354232812Sjmallett/** 1355232812Sjmallett * wait for the pko queue to drain 1356232812Sjmallett * 1357232812Sjmallett * @param queue a valid pko queue 1358232812Sjmallett * @return count is the length of the queue after calling this 1359232812Sjmallett * function 1360232812Sjmallett */ 1361232812Sjmallettstatic int cvmx_helper_wait_pko_queue_drain(int queue) 1362232812Sjmallett{ 1363232812Sjmallett const int timeout = 5; /* Wait up to 5 seconds for timeouts */ 1364232812Sjmallett int count; 1365232812Sjmallett uint64_t start_cycle, stop_cycle; 1366210284Sjmallett 1367232812Sjmallett count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 1368232812Sjmallett start_cycle = cvmx_get_cycle(); 1369232812Sjmallett stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 1370232812Sjmallett while (count && (cvmx_get_cycle() < stop_cycle)) 1371232812Sjmallett { 1372232812Sjmallett cvmx_wait(10000); 1373232812Sjmallett count = cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)); 1374232812Sjmallett } 1375232812Sjmallett 1376232812Sjmallett return count; 1377232812Sjmallett} 1378232812Sjmallett 1379232812Sjmallettstruct cvmx_buffer_list { 1380232812Sjmallett struct cvmx_buffer_list *next; 1381232812Sjmallett}; 1382232812Sjmallett 1383210284Sjmallett/** 1384215990Sjmallett * Undo the initialization performed in 1385215990Sjmallett * cvmx_helper_initialize_packet_io_global(). After calling this routine and the 1386215990Sjmallett * local version on each core, packet IO for Octeon will be disabled and placed 1387215990Sjmallett * in the initial reset state. It will then be safe to call the initialize 1388215990Sjmallett * later on. Note that this routine does not empty the FPA pools. It frees all 1389215990Sjmallett * buffers used by the packet IO hardware to the FPA so a function emptying the 1390215990Sjmallett * FPA after shutdown should find all packet buffers in the FPA. 1391215990Sjmallett * 1392215990Sjmallett * @return Zero on success, negative on failure. 1393215990Sjmallett */ 1394215990Sjmallettint cvmx_helper_shutdown_packet_io_global(void) 1395215990Sjmallett{ 1396215990Sjmallett const int timeout = 5; /* Wait up to 5 seconds for timeouts */ 1397215990Sjmallett int result = 0; 1398215990Sjmallett int num_interfaces; 1399215990Sjmallett int interface; 1400215990Sjmallett int num_ports; 1401215990Sjmallett int index; 1402232812Sjmallett struct cvmx_buffer_list *pool0_buffers; 1403232812Sjmallett struct cvmx_buffer_list *pool0_buffers_tail; 1404215990Sjmallett cvmx_wqe_t *work; 1405215990Sjmallett 1406215990Sjmallett /* Step 1: Disable all backpressure */ 1407232812Sjmallett for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1408215990Sjmallett if (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_DISABLED) 1409215990Sjmallett cvmx_gmx_set_backpressure_override(interface, 0xf); 1410215990Sjmallett 1411215990Sjmallettstep2: 1412215990Sjmallett /* Step 2: Wait for the PKO queues to drain */ 1413232812Sjmallett if (octeon_has_feature(OCTEON_FEATURE_PKND)) 1414215990Sjmallett { 1415232812Sjmallett int queue, max_queue; 1416232812Sjmallett 1417232812Sjmallett max_queue = __cvmx_helper_cfg_pko_max_queue(); 1418232812Sjmallett for (queue = 0; queue < max_queue; queue++) 1419232812Sjmallett { 1420232812Sjmallett if (cvmx_helper_wait_pko_queue_drain(queue)) 1421232812Sjmallett { 1422232812Sjmallett result = -1; 1423232812Sjmallett goto step3; 1424232812Sjmallett } 1425232812Sjmallett } 1426232812Sjmallett } 1427232812Sjmallett else 1428232812Sjmallett { 1429232812Sjmallett num_interfaces = cvmx_helper_get_number_of_interfaces(); 1430232812Sjmallett for (interface=0; interface<num_interfaces; interface++) 1431215990Sjmallett { 1432232812Sjmallett num_ports = cvmx_helper_ports_on_interface(interface); 1433232812Sjmallett for (index=0; index<num_ports; index++) 1434215990Sjmallett { 1435232812Sjmallett int pko_port = cvmx_helper_get_ipd_port(interface, index); 1436232812Sjmallett int queue = cvmx_pko_get_base_queue(pko_port); 1437232812Sjmallett int max_queue = queue + cvmx_pko_get_num_queues(pko_port); 1438232812Sjmallett while (queue < max_queue) 1439215990Sjmallett { 1440232812Sjmallett if (cvmx_helper_wait_pko_queue_drain(queue)) 1441232812Sjmallett { 1442232812Sjmallett result = -1; 1443232812Sjmallett goto step3; 1444232812Sjmallett } 1445232812Sjmallett queue++; 1446215990Sjmallett } 1447215990Sjmallett } 1448215990Sjmallett } 1449215990Sjmallett } 1450215990Sjmallett 1451232812Sjmallettstep3: 1452215990Sjmallett /* Step 3: Disable TX and RX on all ports */ 1453232812Sjmallett for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1454215990Sjmallett { 1455215990Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1456215990Sjmallett { 1457215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1458215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1459215990Sjmallett /* Not a packet interface */ 1460215990Sjmallett break; 1461215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1462215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1463232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1464215990Sjmallett /* We don't handle the NPI/NPEI/SRIO packet engines. The caller 1465215990Sjmallett must know these are idle */ 1466215990Sjmallett break; 1467215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1468215990Sjmallett /* Nothing needed. Once PKO is idle, the loopback devices 1469215990Sjmallett must be idle */ 1470215990Sjmallett break; 1471215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1472215990Sjmallett /* SPI cannot be disabled from Octeon. It is the responsibility 1473215990Sjmallett of the caller to make sure SPI is idle before doing 1474215990Sjmallett shutdown */ 1475215990Sjmallett /* Fall through and do the same processing as RGMII/GMII */ 1476215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1477215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1478215990Sjmallett /* Disable outermost RX at the ASX block */ 1479215990Sjmallett cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), 0); 1480215990Sjmallett num_ports = cvmx_helper_ports_on_interface(interface); 1481215990Sjmallett if (num_ports > 4) 1482215990Sjmallett num_ports = 4; 1483215990Sjmallett for (index=0; index<num_ports; index++) 1484215990Sjmallett { 1485215990Sjmallett cvmx_gmxx_prtx_cfg_t gmx_cfg; 1486215990Sjmallett gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 1487215990Sjmallett gmx_cfg.s.en = 0; 1488215990Sjmallett cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 1489215990Sjmallett /* Poll the GMX state machine waiting for it to become idle */ 1490215990Sjmallett cvmx_write_csr(CVMX_NPI_DBG_SELECT, interface*0x800 + index*0x100 + 0x880); 1491215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&7, ==, 0, timeout*1000000)) 1492215990Sjmallett { 1493215990Sjmallett cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 1494215990Sjmallett result = -1; 1495215990Sjmallett } 1496215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_DBG_DATA, cvmx_dbg_data_t, data&0xf, ==, 0, timeout*1000000)) 1497215990Sjmallett { 1498215990Sjmallett cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 1499215990Sjmallett result = -1; 1500215990Sjmallett } 1501215990Sjmallett } 1502215990Sjmallett /* Disable outermost TX at the ASX block */ 1503215990Sjmallett cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), 0); 1504215990Sjmallett /* Disable interrupts for interface */ 1505215990Sjmallett cvmx_write_csr(CVMX_ASXX_INT_EN(interface), 0); 1506215990Sjmallett cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0); 1507215990Sjmallett break; 1508215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1509232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1510215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1511215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1512215990Sjmallett num_ports = cvmx_helper_ports_on_interface(interface); 1513215990Sjmallett if (num_ports > 4) 1514215990Sjmallett num_ports = 4; 1515215990Sjmallett for (index=0; index<num_ports; index++) 1516215990Sjmallett { 1517215990Sjmallett cvmx_gmxx_prtx_cfg_t gmx_cfg; 1518215990Sjmallett gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); 1519215990Sjmallett gmx_cfg.s.en = 0; 1520215990Sjmallett cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); 1521215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, timeout*1000000)) 1522215990Sjmallett { 1523215990Sjmallett cvmx_dprintf("GMX RX path timeout waiting for idle\n"); 1524215990Sjmallett result = -1; 1525215990Sjmallett } 1526215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(index, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, timeout*1000000)) 1527215990Sjmallett { 1528215990Sjmallett cvmx_dprintf("GMX TX path timeout waiting for idle\n"); 1529215990Sjmallett result = -1; 1530215990Sjmallett } 1531215990Sjmallett } 1532215990Sjmallett break; 1533215990Sjmallett } 1534215990Sjmallett } 1535215990Sjmallett 1536215990Sjmallett /* Step 4: Retrieve all packets from the POW and free them */ 1537215990Sjmallett while ((work = cvmx_pow_work_request_sync(CVMX_POW_WAIT))) 1538215990Sjmallett { 1539215990Sjmallett cvmx_helper_free_packet_data(work); 1540215990Sjmallett cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 0); 1541215990Sjmallett } 1542215990Sjmallett 1543215990Sjmallett /* Step 4b: Special workaround for pass 2 errata */ 1544215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1545215990Sjmallett { 1546215990Sjmallett cvmx_ipd_ptr_count_t ipd_cnt; 1547215990Sjmallett int to_add; 1548215990Sjmallett ipd_cnt.u64 = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 1549215990Sjmallett to_add = (ipd_cnt.s.wqev_cnt + ipd_cnt.s.wqe_pcnt) & 0x7; 1550215990Sjmallett if (to_add) 1551215990Sjmallett { 1552215990Sjmallett int port = -1; 1553215990Sjmallett cvmx_dprintf("Aligning CN38XX pass 2 IPD counters\n"); 1554215990Sjmallett if (cvmx_helper_interface_get_mode(0) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1555215990Sjmallett port = 0; 1556215990Sjmallett else if (cvmx_helper_interface_get_mode(1) == CVMX_HELPER_INTERFACE_MODE_RGMII) 1557215990Sjmallett port = 16; 1558215990Sjmallett 1559215990Sjmallett if (port != -1) 1560215990Sjmallett { 1561215990Sjmallett char *buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); 1562215990Sjmallett if (buffer) 1563215990Sjmallett { 1564215990Sjmallett int queue = cvmx_pko_get_base_queue(port); 1565215990Sjmallett cvmx_pko_command_word0_t pko_command; 1566215990Sjmallett cvmx_buf_ptr_t packet; 1567215990Sjmallett uint64_t start_cycle; 1568215990Sjmallett uint64_t stop_cycle; 1569215990Sjmallett 1570215990Sjmallett /* Populate a minimal packet */ 1571215990Sjmallett memset(buffer, 0xff, 6); 1572215990Sjmallett memset(buffer+6, 0, 54); 1573215990Sjmallett pko_command.u64 = 0; 1574215990Sjmallett pko_command.s.dontfree = 1; 1575215990Sjmallett pko_command.s.total_bytes = 60; 1576215990Sjmallett pko_command.s.segs = 1; 1577215990Sjmallett packet.u64 = 0; 1578215990Sjmallett packet.s.addr = cvmx_ptr_to_phys(buffer); 1579215990Sjmallett packet.s.size = CVMX_FPA_PACKET_POOL_SIZE; 1580215990Sjmallett __cvmx_helper_rgmii_configure_loopback(port, 1, 0); 1581215990Sjmallett while (to_add--) 1582215990Sjmallett { 1583215990Sjmallett cvmx_pko_send_packet_prepare(port, queue, CVMX_PKO_LOCK_CMD_QUEUE); 1584215990Sjmallett if (cvmx_pko_send_packet_finish(port, queue, pko_command, packet, CVMX_PKO_LOCK_CMD_QUEUE)) 1585215990Sjmallett { 1586215990Sjmallett cvmx_dprintf("ERROR: Unable to align IPD counters (PKO failed)\n"); 1587215990Sjmallett break; 1588215990Sjmallett } 1589215990Sjmallett } 1590215990Sjmallett cvmx_fpa_free(buffer, CVMX_FPA_PACKET_POOL, 0); 1591215990Sjmallett 1592215990Sjmallett /* Wait for the packets to loop back */ 1593215990Sjmallett start_cycle = cvmx_get_cycle(); 1594215990Sjmallett stop_cycle = start_cycle + cvmx_clock_get_rate(CVMX_CLOCK_CORE) * timeout; 1595215990Sjmallett while (cvmx_cmd_queue_length(CVMX_CMD_QUEUE_PKO(queue)) && 1596215990Sjmallett (cvmx_get_cycle() < stop_cycle)) 1597215990Sjmallett { 1598215990Sjmallett cvmx_wait(1000); 1599215990Sjmallett } 1600215990Sjmallett cvmx_wait(1000); 1601215990Sjmallett __cvmx_helper_rgmii_configure_loopback(port, 0, 0); 1602215990Sjmallett if (to_add == -1) 1603215990Sjmallett goto step2; 1604215990Sjmallett } 1605215990Sjmallett else 1606215990Sjmallett cvmx_dprintf("ERROR: Unable to align IPD counters (Packet pool empty)\n"); 1607215990Sjmallett } 1608215990Sjmallett else 1609215990Sjmallett cvmx_dprintf("ERROR: Unable to align IPD counters\n"); 1610215990Sjmallett } 1611215990Sjmallett } 1612215990Sjmallett 1613232812Sjmallett /* Step 5 */ 1614215990Sjmallett cvmx_ipd_disable(); 1615215990Sjmallett 1616215990Sjmallett /* Step 6: Drain all prefetched buffers from IPD/PIP. Note that IPD/PIP 1617215990Sjmallett have not been reset yet */ 1618215990Sjmallett __cvmx_ipd_free_ptr(); 1619215990Sjmallett 1620215990Sjmallett /* Step 7: Free the PKO command buffers and put PKO in reset */ 1621215990Sjmallett cvmx_pko_shutdown(); 1622215990Sjmallett 1623215990Sjmallett /* Step 8: Disable MAC address filtering */ 1624232812Sjmallett for (interface=0; interface<CVMX_HELPER_MAX_GMX; interface++) 1625215990Sjmallett { 1626215990Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1627215990Sjmallett { 1628215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1629215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1630215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1631232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1632215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1633215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1634215990Sjmallett break; 1635215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1636232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1637215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1638215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1639215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1640215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1641215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1642215990Sjmallett num_ports = cvmx_helper_ports_on_interface(interface); 1643215990Sjmallett if (num_ports > 4) 1644215990Sjmallett num_ports = 4; 1645215990Sjmallett for (index=0; index<num_ports; index++) 1646215990Sjmallett { 1647215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CTL(index, interface), 1); 1648215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM_EN(index, interface), 0); 1649215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM0(index, interface), 0); 1650215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM1(index, interface), 0); 1651215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM2(index, interface), 0); 1652215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM3(index, interface), 0); 1653215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM4(index, interface), 0); 1654215990Sjmallett cvmx_write_csr(CVMX_GMXX_RXX_ADR_CAM5(index, interface), 0); 1655215990Sjmallett } 1656215990Sjmallett break; 1657215990Sjmallett } 1658215990Sjmallett } 1659215990Sjmallett 1660232812Sjmallett /* Step 9: Drain all FPA buffers out of pool 0 before we reset 1661232812Sjmallett * IPD/PIP. This is needed to keep IPD_QUE0_FREE_PAGE_CNT in 1662232812Sjmallett * sync. We temporarily keep the buffers in the pool0_buffers 1663232812Sjmallett * list. 1664232812Sjmallett */ 1665232812Sjmallett pool0_buffers = NULL; 1666232812Sjmallett pool0_buffers_tail = NULL; 1667215990Sjmallett while (1) 1668215990Sjmallett { 1669232812Sjmallett struct cvmx_buffer_list *buffer = cvmx_fpa_alloc(0); 1670232812Sjmallett if (buffer) { 1671232812Sjmallett buffer->next = NULL; 1672232812Sjmallett 1673232812Sjmallett if (pool0_buffers == NULL) 1674232812Sjmallett pool0_buffers = buffer; 1675232812Sjmallett else 1676232812Sjmallett pool0_buffers_tail->next = buffer; 1677232812Sjmallett 1678232812Sjmallett pool0_buffers_tail = buffer; 1679215990Sjmallett } 1680215990Sjmallett else 1681215990Sjmallett break; 1682215990Sjmallett } 1683215990Sjmallett 1684215990Sjmallett /* Step 10: Reset IPD and PIP */ 1685215990Sjmallett { 1686215990Sjmallett cvmx_ipd_ctl_status_t ipd_ctl_status; 1687215990Sjmallett ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS); 1688215990Sjmallett ipd_ctl_status.s.reset = 1; 1689215990Sjmallett cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1690215990Sjmallett 1691215990Sjmallett if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && 1692215990Sjmallett (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))) 1693215990Sjmallett { 1694215990Sjmallett /* only try 1000 times. Normally if this works it will happen in 1695215990Sjmallett ** the first 50 loops. */ 1696215990Sjmallett int max_loops = 1000; 1697215990Sjmallett int loop = 0; 1698215990Sjmallett /* Per port backpressure counters can get misaligned after an 1699215990Sjmallett IPD reset. This code realigns them by performing repeated 1700215990Sjmallett resets. See IPD-13473 */ 1701215990Sjmallett cvmx_wait(100); 1702215990Sjmallett if (__cvmx_helper_backpressure_is_misaligned()) 1703215990Sjmallett { 1704215990Sjmallett cvmx_dprintf("Starting to align per port backpressure counters.\n"); 1705215990Sjmallett while (__cvmx_helper_backpressure_is_misaligned() && (loop++ < max_loops)) 1706215990Sjmallett { 1707215990Sjmallett cvmx_write_csr(CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 1708215990Sjmallett cvmx_wait(123); 1709215990Sjmallett } 1710215990Sjmallett if (loop < max_loops) 1711215990Sjmallett cvmx_dprintf("Completed aligning per port backpressure counters (%d loops).\n", loop); 1712215990Sjmallett else 1713215990Sjmallett { 1714215990Sjmallett cvmx_dprintf("ERROR: unable to align per port backpressure counters.\n"); 1715215990Sjmallett /* For now, don't hang.... */ 1716215990Sjmallett } 1717215990Sjmallett } 1718215990Sjmallett } 1719215990Sjmallett 1720215990Sjmallett /* PIP_SFT_RST not present in CN38XXp{1,2} */ 1721215990Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN38XX_PASS2)) 1722215990Sjmallett { 1723215990Sjmallett cvmx_pip_sft_rst_t pip_sft_rst; 1724215990Sjmallett pip_sft_rst.u64 = cvmx_read_csr(CVMX_PIP_SFT_RST); 1725215990Sjmallett pip_sft_rst.s.rst = 1; 1726215990Sjmallett cvmx_write_csr(CVMX_PIP_SFT_RST, pip_sft_rst.u64); 1727215990Sjmallett } 1728232812Sjmallett 1729232812Sjmallett /* Make sure IPD has finished reset. */ 1730232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 1731232812Sjmallett { 1732232812Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_IPD_CTL_STATUS, cvmx_ipd_ctl_status_t, rst_done, ==, 0, 1000)) 1733232812Sjmallett { 1734232812Sjmallett cvmx_dprintf("IPD reset timeout waiting for idle\n"); 1735232812Sjmallett result = -1; 1736232812Sjmallett } 1737232812Sjmallett } 1738215990Sjmallett } 1739215990Sjmallett 1740215990Sjmallett /* Step 11: Restore the FPA buffers into pool 0 */ 1741232812Sjmallett while (pool0_buffers) { 1742232812Sjmallett struct cvmx_buffer_list *n = pool0_buffers->next; 1743232812Sjmallett cvmx_fpa_free(pool0_buffers, 0, 0); 1744232812Sjmallett pool0_buffers = n; 1745232812Sjmallett } 1746215990Sjmallett 1747232812Sjmallett /* Step 12: Release interface structures */ 1748232812Sjmallett __cvmx_helper_shutdown_interfaces(); 1749232812Sjmallett 1750215990Sjmallett return result; 1751215990Sjmallett} 1752215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1753215990SjmallettEXPORT_SYMBOL(cvmx_helper_shutdown_packet_io_global); 1754215990Sjmallett#endif 1755215990Sjmallett 1756215990Sjmallett 1757215990Sjmallett/** 1758215990Sjmallett * Does core local shutdown of packet io 1759215990Sjmallett * 1760215990Sjmallett * @return Zero on success, non-zero on failure 1761215990Sjmallett */ 1762215990Sjmallettint cvmx_helper_shutdown_packet_io_local(void) 1763215990Sjmallett{ 1764215990Sjmallett /* Currently there is nothing to do per core. This may change in 1765215990Sjmallett the future */ 1766215990Sjmallett return 0; 1767215990Sjmallett} 1768215990Sjmallett 1769215990Sjmallett 1770215990Sjmallett 1771215990Sjmallett/** 1772210284Sjmallett * Auto configure an IPD/PKO port link state and speed. This 1773210284Sjmallett * function basically does the equivalent of: 1774210284Sjmallett * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); 1775210284Sjmallett * 1776210284Sjmallett * @param ipd_port IPD/PKO port to auto configure 1777210284Sjmallett * 1778210284Sjmallett * @return Link state after configure 1779210284Sjmallett */ 1780210284Sjmallettcvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) 1781210284Sjmallett{ 1782210284Sjmallett cvmx_helper_link_info_t link_info; 1783210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 1784210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 1785210284Sjmallett 1786210284Sjmallett if (index >= cvmx_helper_ports_on_interface(interface)) 1787210284Sjmallett { 1788210284Sjmallett link_info.u64 = 0; 1789210284Sjmallett return link_info; 1790210284Sjmallett } 1791210284Sjmallett 1792210284Sjmallett link_info = cvmx_helper_link_get(ipd_port); 1793232812Sjmallett if (link_info.u64 == (__cvmx_helper_get_link_info(interface, index)).u64) 1794210284Sjmallett return link_info; 1795210284Sjmallett 1796215990Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1797215990Sjmallett if (!link_info.s.link_up) 1798215990Sjmallett cvmx_error_disable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1799215990Sjmallett#endif 1800215990Sjmallett 1801210284Sjmallett /* If we fail to set the link speed, port_link_info will not change */ 1802210284Sjmallett cvmx_helper_link_set(ipd_port, link_info); 1803210284Sjmallett 1804215990Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 1805215990Sjmallett if (link_info.s.link_up) 1806215990Sjmallett cvmx_error_enable_group(CVMX_ERROR_GROUP_ETHERNET, ipd_port); 1807215990Sjmallett#endif 1808215990Sjmallett 1809232812Sjmallett return link_info; 1810210284Sjmallett} 1811215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1812215990SjmallettEXPORT_SYMBOL(cvmx_helper_link_autoconf); 1813215990Sjmallett#endif 1814210284Sjmallett 1815210284Sjmallett/** 1816210284Sjmallett * Return the link state of an IPD/PKO port as returned by 1817210284Sjmallett * auto negotiation. The result of this function may not match 1818210284Sjmallett * Octeon's link config if auto negotiation has changed since 1819210284Sjmallett * the last call to cvmx_helper_link_set(). 1820210284Sjmallett * 1821210284Sjmallett * @param ipd_port IPD/PKO port to query 1822210284Sjmallett * 1823210284Sjmallett * @return Link state 1824210284Sjmallett */ 1825210284Sjmallettcvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) 1826210284Sjmallett{ 1827210284Sjmallett cvmx_helper_link_info_t result; 1828210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 1829210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 1830210284Sjmallett 1831210284Sjmallett /* The default result will be a down link unless the code below 1832210284Sjmallett changes it */ 1833210284Sjmallett result.u64 = 0; 1834210284Sjmallett 1835210284Sjmallett if (index >= cvmx_helper_ports_on_interface(interface)) 1836210284Sjmallett return result; 1837210284Sjmallett 1838210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1839210284Sjmallett { 1840210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1841210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1842210284Sjmallett /* Network links are not supported */ 1843210284Sjmallett break; 1844210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1845232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1846210284Sjmallett result = __cvmx_helper_xaui_link_get(ipd_port); 1847210284Sjmallett break; 1848210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1849210284Sjmallett if (index == 0) 1850210284Sjmallett result = __cvmx_helper_rgmii_link_get(ipd_port); 1851210284Sjmallett else 1852210284Sjmallett { 1853210284Sjmallett result.s.full_duplex = 1; 1854210284Sjmallett result.s.link_up = 1; 1855210284Sjmallett result.s.speed = 1000; 1856210284Sjmallett } 1857210284Sjmallett break; 1858210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1859210284Sjmallett result = __cvmx_helper_rgmii_link_get(ipd_port); 1860210284Sjmallett break; 1861210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1862210284Sjmallett result = __cvmx_helper_spi_link_get(ipd_port); 1863210284Sjmallett break; 1864210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1865210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1866210284Sjmallett result = __cvmx_helper_sgmii_link_get(ipd_port); 1867210284Sjmallett break; 1868215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1869215990Sjmallett result = __cvmx_helper_srio_link_get(ipd_port); 1870215990Sjmallett break; 1871232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1872232812Sjmallett result = __cvmx_helper_ilk_link_get(ipd_port); 1873232812Sjmallett break; 1874210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1875210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1876210284Sjmallett /* Network links are not supported */ 1877210284Sjmallett break; 1878210284Sjmallett } 1879210284Sjmallett return result; 1880210284Sjmallett} 1881215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1882215990SjmallettEXPORT_SYMBOL(cvmx_helper_link_get); 1883215990Sjmallett#endif 1884210284Sjmallett 1885210284Sjmallett 1886210284Sjmallett/** 1887210284Sjmallett * Configure an IPD/PKO port for the specified link state. This 1888210284Sjmallett * function does not influence auto negotiation at the PHY level. 1889210284Sjmallett * The passed link state must always match the link state returned 1890210284Sjmallett * by cvmx_helper_link_get(). It is normally best to use 1891210284Sjmallett * cvmx_helper_link_autoconf() instead. 1892210284Sjmallett * 1893210284Sjmallett * @param ipd_port IPD/PKO port to configure 1894210284Sjmallett * @param link_info The new link state 1895210284Sjmallett * 1896210284Sjmallett * @return Zero on success, negative on failure 1897210284Sjmallett */ 1898210284Sjmallettint cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 1899210284Sjmallett{ 1900210284Sjmallett int result = -1; 1901210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 1902210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 1903210284Sjmallett 1904210284Sjmallett if (index >= cvmx_helper_ports_on_interface(interface)) 1905210284Sjmallett return -1; 1906210284Sjmallett 1907210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1908210284Sjmallett { 1909210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1910210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1911210284Sjmallett break; 1912210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1913232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1914210284Sjmallett result = __cvmx_helper_xaui_link_set(ipd_port, link_info); 1915210284Sjmallett break; 1916210284Sjmallett /* RGMII/GMII/MII are all treated about the same. Most functions 1917210284Sjmallett refer to these ports as RGMII */ 1918210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1919210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1920210284Sjmallett result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); 1921210284Sjmallett break; 1922210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1923210284Sjmallett result = __cvmx_helper_spi_link_set(ipd_port, link_info); 1924210284Sjmallett break; 1925210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1926210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1927210284Sjmallett result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); 1928210284Sjmallett break; 1929215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1930215990Sjmallett result = __cvmx_helper_srio_link_set(ipd_port, link_info); 1931215990Sjmallett break; 1932232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1933232812Sjmallett result = __cvmx_helper_ilk_link_set(ipd_port, link_info); 1934232812Sjmallett break; 1935210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1936210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1937210284Sjmallett break; 1938210284Sjmallett } 1939210284Sjmallett /* Set the port_link_info here so that the link status is updated 1940210284Sjmallett no matter how cvmx_helper_link_set is called. We don't change 1941210284Sjmallett the value if link_set failed */ 1942210284Sjmallett if (result == 0) 1943232812Sjmallett __cvmx_helper_set_link_info(interface, index, link_info); 1944210284Sjmallett return result; 1945210284Sjmallett} 1946215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1947215990SjmallettEXPORT_SYMBOL(cvmx_helper_link_set); 1948215990Sjmallett#endif 1949210284Sjmallett 1950210284Sjmallett 1951210284Sjmallett/** 1952210284Sjmallett * Configure a port for internal and/or external loopback. Internal loopback 1953210284Sjmallett * causes packets sent by the port to be received by Octeon. External loopback 1954210284Sjmallett * causes packets received from the wire to sent out again. 1955210284Sjmallett * 1956210284Sjmallett * @param ipd_port IPD/PKO port to loopback. 1957210284Sjmallett * @param enable_internal 1958210284Sjmallett * Non zero if you want internal loopback 1959210284Sjmallett * @param enable_external 1960210284Sjmallett * Non zero if you want external loopback 1961210284Sjmallett * 1962210284Sjmallett * @return Zero on success, negative on failure. 1963210284Sjmallett */ 1964210284Sjmallettint cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external) 1965210284Sjmallett{ 1966210284Sjmallett int result = -1; 1967210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 1968210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 1969210284Sjmallett 1970210284Sjmallett if (index >= cvmx_helper_ports_on_interface(interface)) 1971210284Sjmallett return -1; 1972210284Sjmallett 1973210284Sjmallett switch (cvmx_helper_interface_get_mode(interface)) 1974210284Sjmallett { 1975210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1976210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PCIE: 1977215990Sjmallett case CVMX_HELPER_INTERFACE_MODE_SRIO: 1978232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_ILK: 1979210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SPI: 1980210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_NPI: 1981210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_LOOP: 1982210284Sjmallett break; 1983210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_XAUI: 1984232812Sjmallett case CVMX_HELPER_INTERFACE_MODE_RXAUI: 1985210284Sjmallett result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external); 1986210284Sjmallett break; 1987210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_RGMII: 1988210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_GMII: 1989210284Sjmallett result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1990210284Sjmallett break; 1991210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_SGMII: 1992210284Sjmallett case CVMX_HELPER_INTERFACE_MODE_PICMG: 1993210284Sjmallett result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external); 1994210284Sjmallett break; 1995210284Sjmallett } 1996210284Sjmallett return result; 1997210284Sjmallett} 1998210284Sjmallett 1999210284Sjmallett#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 2000