1232809Sjmallett/***********************license start*************** 2232809Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3232809Sjmallett * reserved. 4232809Sjmallett * 5232809Sjmallett * 6232809Sjmallett * Redistribution and use in source and binary forms, with or without 7232809Sjmallett * modification, are permitted provided that the following conditions are 8232809Sjmallett * met: 9232809Sjmallett * 10232809Sjmallett * * Redistributions of source code must retain the above copyright 11232809Sjmallett * notice, this list of conditions and the following disclaimer. 12232809Sjmallett * 13232809Sjmallett * * Redistributions in binary form must reproduce the above 14232809Sjmallett * copyright notice, this list of conditions and the following 15232809Sjmallett * disclaimer in the documentation and/or other materials provided 16232809Sjmallett * with the distribution. 17232809Sjmallett 18232809Sjmallett * * Neither the name of Cavium Inc. nor the names of 19232809Sjmallett * its contributors may be used to endorse or promote products 20232809Sjmallett * derived from this software without specific prior written 21232809Sjmallett * permission. 22232809Sjmallett 23232809Sjmallett * This Software, including technical data, may be subject to U.S. export control 24232809Sjmallett * laws, including the U.S. Export Administration Act and its associated 25232809Sjmallett * regulations, and may be subject to export or import regulations in other 26232809Sjmallett * countries. 27232809Sjmallett 28232809Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232809Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30232809Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31232809Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32232809Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33232809Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34232809Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35232809Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36232809Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37232809Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38232809Sjmallett ***********************license end**************************************/ 39232809Sjmallett 40232809Sjmallett/** 41232809Sjmallett * @file 42232809Sjmallett * 43232809Sjmallett * Support library for the ILK 44232809Sjmallett * 45232809Sjmallett * <hr>$Revision: 49448 $<hr> 46232809Sjmallett */ 47232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 48232809Sjmallett#include <linux/module.h> 49232809Sjmallett#include <asm/octeon/cvmx.h> 50232809Sjmallett#include <asm/octeon/cvmx-config.h> 51232809Sjmallett#include <asm/octeon/cvmx-sysinfo.h> 52232809Sjmallett#include <asm/octeon/cvmx-pko.h> 53232809Sjmallett#include <asm/octeon/cvmx-ilk.h> 54232809Sjmallett#include <asm/octeon/cvmx-ilk-defs.h> 55232809Sjmallett#include <asm/octeon/cvmx-helper-util.h> 56232809Sjmallett#include <asm/octeon/cvmx-helper-ilk.h> 57232809Sjmallett#else 58232809Sjmallett#include "cvmx.h" 59232812Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 60232809Sjmallett#include "cvmx-config.h" 61232812Sjmallett#endif 62232809Sjmallett#include "cvmx-sysinfo.h" 63232809Sjmallett#include "cvmx-pko.h" 64232809Sjmallett#include "cvmx-ilk.h" 65232809Sjmallett#include "cvmx-helper-util.h" 66232809Sjmallett#include "cvmx-helper-ilk.h" 67232809Sjmallett#endif 68232809Sjmallett 69232809Sjmallett#ifdef CVMX_ENABLE_HELPER_FUNCTIONS 70232809Sjmallett 71232809Sjmallett/* 72232809Sjmallett * global configurations. to disable the 2nd ILK, set 73232809Sjmallett * cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xff, 0x0} and 74232809Sjmallett * cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 0} 75232809Sjmallett */ 76232809Sjmallettunsigned char cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xf, 0xf0}; 77232809Sjmallett//#define SINGLE_PORT_SIM_ILK 78232809Sjmallett#ifdef SINGLE_PORT_SIM_ILK 79232809Sjmallettunsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {1, 1}; 80232809Sjmallettunsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] = 81232809Sjmallett{{0}, 82232809Sjmallett {0}}; 83232809Sjmallett#else /* sample case */ 84232809Sjmallettunsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 8}; 85232809Sjmallettunsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] = 86232809Sjmallett{{0, 1, 2, 3, 4, 5, 6, 7}, 87232809Sjmallett {0, 1, 2, 3, 4, 5, 6, 7}}; 88232809Sjmallett#endif 89232809Sjmallett 90232809Sjmallett/* Default callbacks, can be overridden 91232809Sjmallett * using cvmx_ilk_get_callbacks/cvmx_ilk_set_callbacks 92232809Sjmallett */ 93232809Sjmallettstatic cvmx_ilk_callbacks_t cvmx_ilk_callbacks = { 94232809Sjmallett .calendar_setup_rx = cvmx_ilk_cal_setup_rx, 95232809Sjmallett}; 96232809Sjmallett 97232809Sjmallettstatic cvmx_ilk_intf_t cvmx_ilk_intf_cfg[CVMX_NUM_ILK_INTF]; 98232809Sjmallett 99232809Sjmallett/** 100232809Sjmallett * Get current ILK initialization callbacks 101232809Sjmallett * 102232809Sjmallett * @param callbacks Pointer to the callbacks structure.to fill 103232809Sjmallett * 104232809Sjmallett * @return Pointer to cvmx_ilk_callbacks_t structure. 105232809Sjmallett */ 106232809Sjmallettvoid cvmx_ilk_get_callbacks(cvmx_ilk_callbacks_t * callbacks) 107232809Sjmallett{ 108232809Sjmallett memcpy(callbacks, &cvmx_ilk_callbacks, sizeof(cvmx_ilk_callbacks)); 109232809Sjmallett} 110232809Sjmallett 111232809Sjmallett/** 112232809Sjmallett * Set new ILK initialization callbacks 113232809Sjmallett * 114232809Sjmallett * @param new_callbacks Pointer to an updated callbacks structure. 115232809Sjmallett */ 116232809Sjmallettvoid cvmx_ilk_set_callbacks(cvmx_ilk_callbacks_t * new_callbacks) 117232809Sjmallett{ 118232809Sjmallett memcpy(&cvmx_ilk_callbacks, new_callbacks, sizeof(cvmx_ilk_callbacks)); 119232809Sjmallett} 120232809Sjmallett 121232809Sjmallett/** 122232809Sjmallett * Initialize and start the ILK interface. 123232809Sjmallett * 124232809Sjmallett * @param interface The identifier of the packet interface to configure and 125232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 126232809Sjmallett * ilk1. 127232809Sjmallett * 128232809Sjmallett * @param lane_mask the lane group for this interface 129232809Sjmallett * 130232809Sjmallett * @return Zero on success, negative of failure. 131232809Sjmallett */ 132232809Sjmallettint cvmx_ilk_start_interface (int interface, unsigned char lane_mask) 133232809Sjmallett{ 134232809Sjmallett int res = -1; 135232809Sjmallett int other_intf, this_qlm, other_qlm; 136232809Sjmallett unsigned char uni_mask; 137232809Sjmallett cvmx_mio_qlmx_cfg_t mio_qlmx_cfg, other_mio_qlmx_cfg; 138232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 139232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 140232809Sjmallett cvmx_ilk_ser_cfg_t ilk_ser_cfg; 141232809Sjmallett 142232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 143232809Sjmallett return res; 144232809Sjmallett 145232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 146232809Sjmallett return res; 147232809Sjmallett 148232809Sjmallett if (lane_mask == 0) 149232809Sjmallett return res; 150232809Sjmallett 151232809Sjmallett /* check conflicts between 2 ilk interfaces. 1 lane can be assigned to 1 152232809Sjmallett * interface only */ 153232809Sjmallett other_intf = !interface; 154232809Sjmallett this_qlm = interface + CVMX_ILK_QLM_BASE; 155232809Sjmallett other_qlm = other_intf + CVMX_ILK_QLM_BASE; 156232809Sjmallett if (cvmx_ilk_intf_cfg[other_intf].lane_en_mask & lane_mask) 157232809Sjmallett { 158232809Sjmallett cvmx_dprintf ("ILK%d: %s: lane assignment conflict\n", interface, 159232809Sjmallett __FUNCTION__); 160232809Sjmallett return res; 161232809Sjmallett } 162232809Sjmallett 163232809Sjmallett /* check the legality of the lane mask. interface 0 can have 8 lanes, 164232809Sjmallett * while interface 1 can have 4 lanes at most */ 165232809Sjmallett uni_mask = lane_mask >> (interface * 4); 166232809Sjmallett if ((uni_mask != 0x1 && uni_mask != 0x3 && uni_mask != 0xf && 167232809Sjmallett uni_mask != 0xff) || (interface == 1 && lane_mask > 0xf0)) 168232809Sjmallett { 169232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS 170232809Sjmallett cvmx_dprintf ("ILK%d: %s: incorrect lane mask: 0x%x \n", interface, 171232809Sjmallett __FUNCTION__, uni_mask); 172232809Sjmallett#endif 173232809Sjmallett return res; 174232809Sjmallett } 175232809Sjmallett 176232809Sjmallett /* check the availability of qlms. qlm_cfg = 001 means the chip is fused 177232809Sjmallett * to give this qlm to ilk */ 178232809Sjmallett mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(this_qlm)); 179232809Sjmallett other_mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(other_qlm)); 180232809Sjmallett if (mio_qlmx_cfg.s.qlm_cfg != 1 || 181232809Sjmallett (uni_mask == 0xff && other_mio_qlmx_cfg.s.qlm_cfg != 1)) 182232809Sjmallett { 183232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS 184232809Sjmallett cvmx_dprintf ("ILK%d: %s: qlm unavailable\n", interface, __FUNCTION__); 185232809Sjmallett#endif 186232809Sjmallett return res; 187232809Sjmallett } 188232809Sjmallett 189232809Sjmallett /* power up the serdes */ 190232809Sjmallett ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG); 191232809Sjmallett if (ilk_ser_cfg.s.ser_pwrup == 0) 192232809Sjmallett { 193232809Sjmallett ilk_ser_cfg.s.ser_rxpol_auto = 1; 194232809Sjmallett ilk_ser_cfg.s.ser_rxpol = 0; 195232809Sjmallett ilk_ser_cfg.s.ser_txpol = 0; 196232809Sjmallett ilk_ser_cfg.s.ser_reset_n = 0xff; 197232809Sjmallett ilk_ser_cfg.s.ser_haul = 0; 198232809Sjmallett } 199232809Sjmallett ilk_ser_cfg.s.ser_pwrup |= ((interface ==0) && (lane_mask > 0xf)) ? 200232809Sjmallett 0x3 : (1 << interface); 201232809Sjmallett cvmx_write_csr (CVMX_ILK_SER_CFG, ilk_ser_cfg.u64); 202232809Sjmallett 203232809Sjmallett /* configure the lane enable of the interface */ 204232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 205232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 206232809Sjmallett ilk_txx_cfg0.s.lane_ena = ilk_rxx_cfg0.s.lane_ena = lane_mask; 207232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 208232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 209232809Sjmallett 210232809Sjmallett /* write to local cache. for lane speed, if interface 0 has 8 lanes, 211232809Sjmallett * assume both qlms have the same speed */ 212232809Sjmallett cvmx_ilk_intf_cfg[interface].intf_en = 1; 213232809Sjmallett cvmx_ilk_intf_cfg[interface].lane_en_mask = lane_mask; 214232809Sjmallett res = 0; 215232809Sjmallett 216232809Sjmallett return res; 217232809Sjmallett} 218232809Sjmallett 219232809Sjmallett/** 220232809Sjmallett * set pipe group base and length for the interface 221232809Sjmallett * 222232809Sjmallett * @param interface The identifier of the packet interface to configure and 223232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 224232809Sjmallett * ilk1. 225232809Sjmallett * 226232809Sjmallett * @param pipe_base the base of the pipe group 227232809Sjmallett * @param pipe_len the length of the pipe group 228232809Sjmallett * 229232809Sjmallett * @return Zero on success, negative of failure. 230232809Sjmallett */ 231232809Sjmallettint cvmx_ilk_set_pipe (int interface, int pipe_base, unsigned int pipe_len) 232232809Sjmallett{ 233232809Sjmallett int res = -1; 234232809Sjmallett cvmx_ilk_txx_pipe_t ilk_txx_pipe; 235232809Sjmallett 236232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 237232809Sjmallett return res; 238232809Sjmallett 239232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 240232809Sjmallett return res; 241232809Sjmallett 242232809Sjmallett /* base should be between 0 and 127. base + length should be <127 */ 243232809Sjmallett if (!(pipe_base >= 0 && pipe_base <= 127) || (pipe_base + pipe_len > 127)) 244232809Sjmallett { 245232809Sjmallett#if CVMX_ENABLE_DEBUG_PRINTS 246232809Sjmallett cvmx_dprintf ("ILK%d: %s: pipe base/length out of bounds\n", interface, 247232809Sjmallett __FUNCTION__); 248232809Sjmallett#endif 249232809Sjmallett return res; 250232809Sjmallett } 251232809Sjmallett 252232809Sjmallett /* set them in ilk tx section */ 253232809Sjmallett ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface)); 254232809Sjmallett ilk_txx_pipe.s.base = pipe_base; 255232809Sjmallett ilk_txx_pipe.s.nump = pipe_len; 256232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_PIPE(interface), ilk_txx_pipe.u64); 257232809Sjmallett res = 0; 258232809Sjmallett 259232809Sjmallett return res; 260232809Sjmallett} 261232809Sjmallett 262232809Sjmallett/** 263232809Sjmallett * set logical channels for tx 264232809Sjmallett * 265232809Sjmallett * @param interface The identifier of the packet interface to configure and 266232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 267232809Sjmallett * ilk1. 268232809Sjmallett * 269232809Sjmallett * @param pch pointer to an array of pipe-channel pair 270232809Sjmallett * @param num_chs the number of entries in the pipe-channel array 271232809Sjmallett * 272232809Sjmallett * @return Zero on success, negative of failure. 273232809Sjmallett */ 274232809Sjmallettint cvmx_ilk_tx_set_channel (int interface, cvmx_ilk_pipe_chan_t *pch, 275232809Sjmallett unsigned int num_chs) 276232809Sjmallett{ 277232809Sjmallett int res = -1; 278232809Sjmallett cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap; 279232809Sjmallett unsigned int i; 280232809Sjmallett 281232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 282232809Sjmallett return res; 283232809Sjmallett 284232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 285232809Sjmallett return res; 286232809Sjmallett 287232809Sjmallett if (pch == NULL || num_chs > CVMX_MAX_ILK_PIPES) 288232809Sjmallett return res; 289232809Sjmallett 290232809Sjmallett /* write the pair to ilk tx */ 291232809Sjmallett for (i = 0; i < num_chs; i++) 292232809Sjmallett { 293232809Sjmallett ilk_txx_idx_pmap.u64 = 0; 294232809Sjmallett ilk_txx_idx_pmap.s.index = pch->pipe; 295232809Sjmallett cvmx_write_csr(CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64); 296232809Sjmallett cvmx_write_csr(CVMX_ILK_TXX_MEM_PMAP(interface), pch->chan); 297232809Sjmallett pch++; 298232809Sjmallett } 299232809Sjmallett res = 0; 300232809Sjmallett 301232809Sjmallett return res; 302232809Sjmallett} 303232809Sjmallett 304232809Sjmallett/** 305232809Sjmallett * set pkind for rx 306232809Sjmallett * 307232809Sjmallett * @param interface The identifier of the packet interface to configure and 308232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 309232809Sjmallett * ilk1. 310232809Sjmallett * 311232809Sjmallett * @param chpknd pointer to an array of channel-pkind pair 312232809Sjmallett * @param num_pknd the number of entries in the channel-pkind array 313232809Sjmallett * 314232809Sjmallett * @return Zero on success, negative of failure. 315232809Sjmallett */ 316232809Sjmallettint cvmx_ilk_rx_set_pknd (int interface, cvmx_ilk_chan_pknd_t *chpknd, 317232809Sjmallett unsigned int num_pknd) 318232809Sjmallett{ 319232809Sjmallett int res = -1; 320232809Sjmallett cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap; 321232809Sjmallett unsigned int i; 322232809Sjmallett 323232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 324232809Sjmallett return res; 325232809Sjmallett 326232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 327232809Sjmallett return res; 328232809Sjmallett 329232809Sjmallett if (chpknd == NULL || num_pknd > CVMX_MAX_ILK_PKNDS) 330232809Sjmallett return res; 331232809Sjmallett 332232809Sjmallett /* write the pair to ilk rx. note the channels for different interfaces 333232809Sjmallett * are given in *chpknd and interface is not used as a param */ 334232809Sjmallett for (i = 0; i < num_pknd; i++) 335232809Sjmallett { 336232809Sjmallett ilk_rxf_idx_pmap.u64 = 0; 337232809Sjmallett ilk_rxf_idx_pmap.s.index = interface * 256 + chpknd->chan; 338232809Sjmallett cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64); 339232809Sjmallett cvmx_write_csr (CVMX_ILK_RXF_MEM_PMAP, chpknd->pknd); 340232809Sjmallett chpknd++; 341232809Sjmallett } 342232809Sjmallett res = 0; 343232809Sjmallett 344232809Sjmallett return res; 345232809Sjmallett} 346232809Sjmallett 347232809Sjmallett/** 348232809Sjmallett * configure calendar for rx 349232809Sjmallett * 350232809Sjmallett * @param interface The identifier of the packet interface to configure and 351232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 352232809Sjmallett * ilk1. 353232809Sjmallett * 354232809Sjmallett * @param cal_depth the number of calendar entries 355232809Sjmallett * @param pent pointer to calendar entries 356232809Sjmallett * 357232809Sjmallett * @return Zero on success, negative of failure. 358232809Sjmallett */ 359232812Sjmallettstatic int cvmx_ilk_rx_cal_conf (int interface, int cal_depth, 360232809Sjmallett cvmx_ilk_cal_entry_t *pent) 361232809Sjmallett{ 362232809Sjmallett int res = -1, num_grp, num_rest, i, j; 363232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 364232809Sjmallett cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal; 365232809Sjmallett cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0; 366232809Sjmallett cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1; 367232809Sjmallett unsigned long int tmp; 368232809Sjmallett 369232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 370232809Sjmallett return res; 371232809Sjmallett 372232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 373232809Sjmallett return res; 374232809Sjmallett 375232809Sjmallett if (cal_depth < CVMX_ILK_RX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL 376232809Sjmallett || pent == NULL) 377232809Sjmallett return res; 378232809Sjmallett 379232809Sjmallett /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */ 380232809Sjmallett /* TODO: test effectiveness */ 381232809Sjmallett#if 0 382232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID) 383232809Sjmallett for (i = 0; i < cal_depth; i++) 384232809Sjmallett pent->ent_ctrl = LINK; 385232809Sjmallett#endif 386232809Sjmallett 387232809Sjmallett /* set the depth */ 388232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 389232809Sjmallett ilk_rxx_cfg0.s.cal_depth = cal_depth; 390232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 391232809Sjmallett 392232809Sjmallett /* set the calendar index */ 393232809Sjmallett num_grp = cal_depth / CVMX_ILK_CAL_GRP_SZ; 394232809Sjmallett num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ; 395232809Sjmallett ilk_rxx_idx_cal.u64 = 0; 396232809Sjmallett ilk_rxx_idx_cal.s.inc = 1; 397232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64); 398232809Sjmallett 399232809Sjmallett /* set the calendar entries. each group has both cal0 and cal1 registers */ 400232809Sjmallett for (i = 0; i < num_grp; i++) 401232809Sjmallett { 402232809Sjmallett ilk_rxx_mem_cal0.u64 = 0; 403232809Sjmallett for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 404232809Sjmallett { 405232809Sjmallett tmp = 0; 406232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 407232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 408232809Sjmallett ilk_rxx_mem_cal0.u64 |= tmp; 409232809Sjmallett 410232809Sjmallett tmp = 0; 411232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 412232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 413232809Sjmallett CVMX_ILK_PIPE_BPID_SZ; 414232809Sjmallett ilk_rxx_mem_cal0.u64 |= tmp; 415232809Sjmallett pent++; 416232809Sjmallett } 417232809Sjmallett cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64); 418232809Sjmallett 419232809Sjmallett ilk_rxx_mem_cal1.u64 = 0; 420232809Sjmallett for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 421232809Sjmallett { 422232809Sjmallett tmp = 0; 423232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 424232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 425232809Sjmallett ilk_rxx_mem_cal1.u64 |= tmp; 426232809Sjmallett 427232809Sjmallett tmp = 0; 428232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 429232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 430232809Sjmallett CVMX_ILK_PIPE_BPID_SZ; 431232809Sjmallett ilk_rxx_mem_cal1.u64 |= tmp; 432232809Sjmallett pent++; 433232809Sjmallett } 434232809Sjmallett cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64); 435232809Sjmallett } 436232809Sjmallett 437232809Sjmallett /* set the calendar entries, the fraction of a group. but both cal0 and 438232809Sjmallett * cal1 must be written */ 439232809Sjmallett ilk_rxx_mem_cal0.u64 = 0; 440232809Sjmallett ilk_rxx_mem_cal1.u64 = 0; 441232809Sjmallett for (i = 0; i < num_rest; i++) 442232809Sjmallett { 443232809Sjmallett if (i < CVMX_ILK_CAL_GRP_SZ/2) 444232809Sjmallett { 445232809Sjmallett tmp = 0; 446232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 447232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i; 448232809Sjmallett ilk_rxx_mem_cal0.u64 |= tmp; 449232809Sjmallett 450232809Sjmallett tmp = 0; 451232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 452232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i + 453232809Sjmallett CVMX_ILK_PIPE_BPID_SZ; 454232809Sjmallett ilk_rxx_mem_cal0.u64 |= tmp; 455232809Sjmallett pent++; 456232809Sjmallett } 457232809Sjmallett 458232809Sjmallett if (i >= CVMX_ILK_CAL_GRP_SZ/2) 459232809Sjmallett { 460232809Sjmallett tmp = 0; 461232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 462232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * 463232809Sjmallett (i - CVMX_ILK_CAL_GRP_SZ/2); 464232809Sjmallett ilk_rxx_mem_cal1.u64 |= tmp; 465232809Sjmallett 466232809Sjmallett tmp = 0; 467232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 468232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * 469232809Sjmallett (i - CVMX_ILK_CAL_GRP_SZ/2) + CVMX_ILK_PIPE_BPID_SZ; 470232809Sjmallett ilk_rxx_mem_cal1.u64 |= tmp; 471232809Sjmallett pent++; 472232809Sjmallett } 473232809Sjmallett } 474232809Sjmallett cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64); 475232809Sjmallett cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64); 476232809Sjmallett cvmx_read_csr (CVMX_ILK_RXX_MEM_CAL1(interface)); 477232809Sjmallett 478232809Sjmallett return 0; 479232809Sjmallett} 480232809Sjmallett 481232809Sjmallett/** 482232809Sjmallett * set high water mark for rx 483232809Sjmallett * 484232809Sjmallett * @param interface The identifier of the packet interface to configure and 485232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 486232809Sjmallett * ilk1. 487232809Sjmallett * 488232809Sjmallett * @param hi_wm high water mark for this interface 489232809Sjmallett * 490232809Sjmallett * @return Zero on success, negative of failure. 491232809Sjmallett */ 492232812Sjmallettstatic int cvmx_ilk_rx_set_hwm (int interface, int hi_wm) 493232809Sjmallett{ 494232809Sjmallett int res = -1; 495232809Sjmallett cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 496232809Sjmallett 497232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 498232809Sjmallett return res; 499232809Sjmallett 500232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 501232809Sjmallett return res; 502232809Sjmallett 503232809Sjmallett if (hi_wm <= 0) 504232809Sjmallett return res; 505232809Sjmallett 506232809Sjmallett /* set the hwm */ 507232809Sjmallett ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 508232809Sjmallett ilk_rxx_cfg1.s.rx_fifo_hwm = hi_wm; 509232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64); 510232809Sjmallett res = 0; 511232809Sjmallett 512232809Sjmallett return res; 513232809Sjmallett} 514232809Sjmallett 515232809Sjmallett/** 516232809Sjmallett * enable calendar for rx 517232809Sjmallett * 518232809Sjmallett * @param interface The identifier of the packet interface to configure and 519232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 520232809Sjmallett * ilk1. 521232809Sjmallett * 522232809Sjmallett * @param cal_ena enable or disable calendar 523232809Sjmallett * 524232809Sjmallett * @return Zero on success, negative of failure. 525232809Sjmallett */ 526232812Sjmallettstatic int cvmx_ilk_rx_cal_ena (int interface, unsigned char cal_ena) 527232809Sjmallett{ 528232809Sjmallett int res = -1; 529232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 530232809Sjmallett 531232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 532232809Sjmallett return res; 533232809Sjmallett 534232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 535232809Sjmallett return res; 536232809Sjmallett 537232809Sjmallett /* set the enable */ 538232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 539232809Sjmallett ilk_rxx_cfg0.s.cal_ena = cal_ena; 540232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 541232809Sjmallett cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 542232809Sjmallett res = 0; 543232809Sjmallett 544232809Sjmallett return res; 545232809Sjmallett} 546232809Sjmallett 547232809Sjmallett/** 548232809Sjmallett * set up calendar for rx 549232809Sjmallett * 550232809Sjmallett * @param interface The identifier of the packet interface to configure and 551232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 552232809Sjmallett * ilk1. 553232809Sjmallett * 554232809Sjmallett * @param cal_depth the number of calendar entries 555232809Sjmallett * @param pent pointer to calendar entries 556232809Sjmallett * @param hi_wm high water mark for this interface 557232809Sjmallett * @param cal_ena enable or disable calendar 558232809Sjmallett * 559232809Sjmallett * @return Zero on success, negative of failure. 560232809Sjmallett */ 561232809Sjmallettint cvmx_ilk_cal_setup_rx (int interface, int cal_depth, 562232809Sjmallett cvmx_ilk_cal_entry_t *pent, int hi_wm, 563232809Sjmallett unsigned char cal_ena) 564232809Sjmallett{ 565232809Sjmallett int res = -1; 566232809Sjmallett 567232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 568232809Sjmallett return res; 569232809Sjmallett 570232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 571232809Sjmallett return res; 572232809Sjmallett 573232809Sjmallett res = cvmx_ilk_rx_cal_conf (interface, cal_depth, pent); 574232809Sjmallett if (res < 0) 575232809Sjmallett return res; 576232809Sjmallett 577232809Sjmallett res = cvmx_ilk_rx_set_hwm (interface, hi_wm); 578232809Sjmallett if (res < 0) 579232809Sjmallett return res; 580232809Sjmallett 581232809Sjmallett res = cvmx_ilk_rx_cal_ena (interface, cal_ena); 582232809Sjmallett return res; 583232809Sjmallett} 584232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 585232809SjmallettEXPORT_SYMBOL(cvmx_ilk_cal_setup_rx); 586232809Sjmallett#endif 587232809Sjmallett 588232809Sjmallett/** 589232809Sjmallett * configure calendar for tx 590232809Sjmallett * 591232809Sjmallett * @param interface The identifier of the packet interface to configure and 592232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 593232809Sjmallett * ilk1. 594232809Sjmallett * 595232809Sjmallett * @param cal_depth the number of calendar entries 596232809Sjmallett * @param pent pointer to calendar entries 597232809Sjmallett * 598232809Sjmallett * @return Zero on success, negative of failure. 599232809Sjmallett */ 600232812Sjmallettstatic int cvmx_ilk_tx_cal_conf (int interface, int cal_depth, 601232809Sjmallett cvmx_ilk_cal_entry_t *pent) 602232809Sjmallett{ 603232809Sjmallett int res = -1, num_grp, num_rest, i, j; 604232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 605232809Sjmallett cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal; 606232809Sjmallett cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0; 607232809Sjmallett cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1; 608232809Sjmallett unsigned long int tmp; 609232809Sjmallett cvmx_ilk_cal_entry_t *ent_tmp; 610232809Sjmallett 611232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 612232809Sjmallett return res; 613232809Sjmallett 614232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 615232809Sjmallett return res; 616232809Sjmallett 617232809Sjmallett if (cal_depth < CVMX_ILK_TX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL 618232809Sjmallett || pent == NULL) 619232809Sjmallett return res; 620232809Sjmallett 621232809Sjmallett /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */ 622232809Sjmallett /* TODO: test effectiveness */ 623232809Sjmallett#if 0 624232809Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID) 625232809Sjmallett for (i = 0; i < cal_depth; i++) 626232809Sjmallett pent->ent_ctrl = LINK; 627232809Sjmallett#endif 628232809Sjmallett 629232809Sjmallett /* tx calendar depth must be a multiple of 8 */ 630232809Sjmallett num_grp = (cal_depth - 1) / CVMX_ILK_CAL_GRP_SZ + 1; 631232809Sjmallett num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ; 632232809Sjmallett if (num_rest != 0) 633232809Sjmallett { 634232809Sjmallett ent_tmp = pent + cal_depth; 635232809Sjmallett for (i = num_rest; i < 8; i++, ent_tmp++) 636232809Sjmallett { 637232809Sjmallett ent_tmp->pipe_bpid = 0; 638232809Sjmallett ent_tmp->ent_ctrl = XOFF; 639232809Sjmallett } 640232809Sjmallett } 641232809Sjmallett cal_depth = num_grp * 8; 642232809Sjmallett 643232809Sjmallett /* set the depth */ 644232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 645232809Sjmallett ilk_txx_cfg0.s.cal_depth = cal_depth; 646232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 647232809Sjmallett 648232809Sjmallett /* set the calendar index */ 649232809Sjmallett ilk_txx_idx_cal.u64 = 0; 650232809Sjmallett ilk_txx_idx_cal.s.inc = 1; 651232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64); 652232809Sjmallett 653232809Sjmallett /* set the calendar entries. each group has both cal0 and cal1 registers */ 654232809Sjmallett for (i = 0; i < num_grp; i++) 655232809Sjmallett { 656232809Sjmallett ilk_txx_mem_cal0.u64 = 0; 657232809Sjmallett for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 658232809Sjmallett { 659232809Sjmallett tmp = 0; 660232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 661232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 662232809Sjmallett ilk_txx_mem_cal0.u64 |= tmp; 663232809Sjmallett 664232809Sjmallett tmp = 0; 665232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 666232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 667232809Sjmallett CVMX_ILK_PIPE_BPID_SZ; 668232809Sjmallett ilk_txx_mem_cal0.u64 |= tmp; 669232809Sjmallett pent++; 670232809Sjmallett } 671232809Sjmallett cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL0(interface), ilk_txx_mem_cal0.u64); 672232809Sjmallett 673232809Sjmallett ilk_txx_mem_cal1.u64 = 0; 674232809Sjmallett for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 675232809Sjmallett { 676232809Sjmallett tmp = 0; 677232809Sjmallett tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 678232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 679232809Sjmallett ilk_txx_mem_cal1.u64 |= tmp; 680232809Sjmallett 681232809Sjmallett tmp = 0; 682232809Sjmallett tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 683232809Sjmallett tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 684232809Sjmallett CVMX_ILK_PIPE_BPID_SZ; 685232809Sjmallett ilk_txx_mem_cal1.u64 |= tmp; 686232809Sjmallett pent++; 687232809Sjmallett } 688232809Sjmallett cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL1(interface), ilk_txx_mem_cal1.u64); 689232809Sjmallett } 690232809Sjmallett cvmx_read_csr (CVMX_ILK_TXX_MEM_CAL1(interface)); 691232809Sjmallett 692232809Sjmallett return 0; 693232809Sjmallett} 694232809Sjmallett 695232812Sjmallett#ifdef CVMX_ILK_BP_CONF_ENA 696232809Sjmallett/** 697232809Sjmallett * configure backpressure for tx 698232809Sjmallett * 699232809Sjmallett * @param interface The identifier of the packet interface to configure and 700232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 701232809Sjmallett * ilk1. 702232809Sjmallett * 703232809Sjmallett * @param cal_depth the number of calendar entries 704232809Sjmallett * @param pent pointer to calendar entries 705232809Sjmallett * 706232809Sjmallett * @return Zero on success, negative of failure. 707232809Sjmallett */ 708232812Sjmallettstatic int cvmx_ilk_bp_conf (int interface, int cal_depth, cvmx_ilk_cal_entry_t *pent) 709232809Sjmallett{ 710232809Sjmallett int res = -1, i; 711232809Sjmallett cvmx_ipd_ctl_status_t ipd_ctl_status; 712232809Sjmallett cvmx_ilk_cal_entry_t *tmp; 713232809Sjmallett unsigned char bpid; 714232809Sjmallett cvmx_ipd_bpidx_mbuf_th_t ipd_bpidx_mbuf_th; 715232809Sjmallett 716232809Sjmallett /* enable bp for the interface */ 717232809Sjmallett ipd_ctl_status.u64 = cvmx_read_csr (CVMX_IPD_CTL_STATUS); 718232809Sjmallett ipd_ctl_status.s.pbp_en = 1; 719232809Sjmallett cvmx_write_csr (CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 720232809Sjmallett 721232809Sjmallett /* enable bp for each id */ 722232809Sjmallett for (i = 0, tmp = pent; i < cal_depth; i++, tmp++) 723232809Sjmallett { 724232809Sjmallett bpid = tmp->pipe_bpid; 725232809Sjmallett ipd_bpidx_mbuf_th.u64 = 726232809Sjmallett cvmx_read_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid)); 727232809Sjmallett ipd_bpidx_mbuf_th.s.page_cnt = 1; /* 256 buffers */ 728232809Sjmallett ipd_bpidx_mbuf_th.s.bp_enb = 1; 729232809Sjmallett cvmx_write_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid), ipd_bpidx_mbuf_th.u64); 730232809Sjmallett } 731232809Sjmallett res = 0; 732232809Sjmallett 733232809Sjmallett return res; 734232809Sjmallett} 735232812Sjmallett#endif 736232809Sjmallett 737232809Sjmallett/** 738232809Sjmallett * enable calendar for tx 739232809Sjmallett * 740232809Sjmallett * @param interface The identifier of the packet interface to configure and 741232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 742232809Sjmallett * ilk1. 743232809Sjmallett * 744232809Sjmallett * @param cal_ena enable or disable calendar 745232809Sjmallett * 746232809Sjmallett * @return Zero on success, negative of failure. 747232809Sjmallett */ 748232812Sjmallettstatic int cvmx_ilk_tx_cal_ena (int interface, unsigned char cal_ena) 749232809Sjmallett{ 750232809Sjmallett int res = -1; 751232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 752232809Sjmallett 753232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 754232809Sjmallett return res; 755232809Sjmallett 756232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 757232809Sjmallett return res; 758232809Sjmallett 759232809Sjmallett /* set the enable */ 760232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 761232809Sjmallett ilk_txx_cfg0.s.cal_ena = cal_ena; 762232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 763232809Sjmallett cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 764232809Sjmallett res = 0; 765232809Sjmallett 766232809Sjmallett return res; 767232809Sjmallett} 768232809Sjmallett 769232809Sjmallett/** 770232809Sjmallett * set up calendar for tx 771232809Sjmallett * 772232809Sjmallett * @param interface The identifier of the packet interface to configure and 773232809Sjmallett * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 774232809Sjmallett * ilk1. 775232809Sjmallett * 776232809Sjmallett * @param cal_depth the number of calendar entries 777232809Sjmallett * @param pent pointer to calendar entries 778232809Sjmallett * @param cal_ena enable or disable calendar 779232809Sjmallett * 780232809Sjmallett * @return Zero on success, negative of failure. 781232809Sjmallett */ 782232809Sjmallettint cvmx_ilk_cal_setup_tx (int interface, int cal_depth, 783232809Sjmallett cvmx_ilk_cal_entry_t *pent, unsigned char cal_ena) 784232809Sjmallett{ 785232809Sjmallett int res = -1; 786232809Sjmallett 787232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 788232809Sjmallett return res; 789232809Sjmallett 790232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 791232809Sjmallett return res; 792232809Sjmallett 793232809Sjmallett res = cvmx_ilk_tx_cal_conf (interface, cal_depth, pent); 794232809Sjmallett if (res < 0) 795232809Sjmallett return res; 796232809Sjmallett 797232809Sjmallett#ifdef CVMX_ILK_BP_CONF_ENA 798232809Sjmallett res = cvmx_ilk_bp_conf (interface, cal_depth, pent); 799232809Sjmallett if (res < 0) 800232809Sjmallett return res; 801232809Sjmallett#endif 802232809Sjmallett 803232809Sjmallett res = cvmx_ilk_tx_cal_ena (interface, cal_ena); 804232809Sjmallett return res; 805232809Sjmallett} 806232809Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 807232809SjmallettEXPORT_SYMBOL(cvmx_ilk_cal_setup_tx); 808232809Sjmallett#endif 809232809Sjmallett 810232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 811232809Sjmallettstatic void cvmx_ilk_reg_dump_rx (int interface) 812232809Sjmallett{ 813232809Sjmallett int i; 814232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 815232809Sjmallett cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 816232809Sjmallett cvmx_ilk_rxx_int_t ilk_rxx_int; 817232809Sjmallett cvmx_ilk_rxx_jabber_t ilk_rxx_jabber; 818232809Sjmallett cvmx_ilk_rx_lnex_cfg_t ilk_rx_lnex_cfg; 819232809Sjmallett cvmx_ilk_rx_lnex_int_t ilk_rx_lnex_int; 820232809Sjmallett cvmx_ilk_gbl_cfg_t ilk_gbl_cfg; 821232809Sjmallett cvmx_ilk_ser_cfg_t ilk_ser_cfg; 822232809Sjmallett cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap; 823232809Sjmallett cvmx_ilk_rxf_mem_pmap_t ilk_rxf_mem_pmap; 824232809Sjmallett cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal; 825232809Sjmallett cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0; 826232809Sjmallett cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1; 827232809Sjmallett 828232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 829232809Sjmallett cvmx_dprintf ("ilk rxx cfg0: 0x%16lx\n", ilk_rxx_cfg0.u64); 830232809Sjmallett 831232809Sjmallett ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 832232809Sjmallett cvmx_dprintf ("ilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64); 833232809Sjmallett 834232809Sjmallett ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface)); 835232809Sjmallett cvmx_dprintf ("ilk rxx int: 0x%16lx\n", ilk_rxx_int.u64); 836232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64); 837232809Sjmallett 838232809Sjmallett ilk_rxx_jabber.u64 = cvmx_read_csr (CVMX_ILK_RXX_JABBER(interface)); 839232809Sjmallett cvmx_dprintf ("ilk rxx jabber: 0x%16lx\n", ilk_rxx_jabber.u64); 840232809Sjmallett 841232809Sjmallett#define LNE_NUM_DBG 4 842232809Sjmallett for (i = 0; i < LNE_NUM_DBG; i++) 843232809Sjmallett { 844232809Sjmallett ilk_rx_lnex_cfg.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_CFG(i)); 845232809Sjmallett cvmx_dprintf ("ilk rx lnex cfg lane: %d 0x%16lx\n", i, 846232809Sjmallett ilk_rx_lnex_cfg.u64); 847232809Sjmallett } 848232809Sjmallett 849232809Sjmallett for (i = 0; i < LNE_NUM_DBG; i++) 850232809Sjmallett { 851232809Sjmallett ilk_rx_lnex_int.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_INT(i)); 852232809Sjmallett cvmx_dprintf ("ilk rx lnex int lane: %d 0x%16lx\n", i, 853232809Sjmallett ilk_rx_lnex_int.u64); 854232809Sjmallett cvmx_write_csr (CVMX_ILK_RX_LNEX_INT(i), ilk_rx_lnex_int.u64); 855232809Sjmallett } 856232809Sjmallett 857232809Sjmallett ilk_gbl_cfg.u64 = cvmx_read_csr (CVMX_ILK_GBL_CFG); 858232809Sjmallett cvmx_dprintf ("ilk gbl cfg: 0x%16lx\n", ilk_gbl_cfg.u64); 859232809Sjmallett 860232809Sjmallett ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG); 861232809Sjmallett cvmx_dprintf ("ilk ser cfg: 0x%16lx\n", ilk_ser_cfg.u64); 862232809Sjmallett 863232809Sjmallett#define CHAN_NUM_DBG 8 864232809Sjmallett ilk_rxf_idx_pmap.u64 = 0; 865232809Sjmallett ilk_rxf_idx_pmap.s.index = interface * 256; 866232809Sjmallett ilk_rxf_idx_pmap.s.inc = 1; 867232809Sjmallett cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64); 868232809Sjmallett for (i = 0; i < CHAN_NUM_DBG; i++) 869232809Sjmallett { 870232809Sjmallett ilk_rxf_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_RXF_MEM_PMAP); 871232809Sjmallett cvmx_dprintf ("ilk rxf mem pmap chan: %3d 0x%16lx\n", i, 872232809Sjmallett ilk_rxf_mem_pmap.u64); 873232809Sjmallett } 874232809Sjmallett 875232809Sjmallett#define CAL_NUM_DBG 2 876232809Sjmallett ilk_rxx_idx_cal.u64 = 0; 877232809Sjmallett ilk_rxx_idx_cal.s.inc = 1; 878232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64); 879232809Sjmallett for (i = 0; i < CAL_NUM_DBG; i++) 880232809Sjmallett { 881232809Sjmallett ilk_rxx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_RXX_IDX_CAL(interface)); 882232809Sjmallett cvmx_dprintf ("ilk rxx idx cal: 0x%16lx\n", ilk_rxx_idx_cal.u64); 883232809Sjmallett 884232809Sjmallett ilk_rxx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL0(interface)); 885232809Sjmallett cvmx_dprintf ("ilk rxx mem cal0: 0x%16lx\n", ilk_rxx_mem_cal0.u64); 886232809Sjmallett ilk_rxx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL1(interface)); 887232809Sjmallett cvmx_dprintf ("ilk rxx mem cal1: 0x%16lx\n", ilk_rxx_mem_cal1.u64); 888232809Sjmallett } 889232809Sjmallett} 890232809Sjmallett 891232809Sjmallettstatic void cvmx_ilk_reg_dump_tx (int interface) 892232809Sjmallett{ 893232809Sjmallett int i; 894232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 895232809Sjmallett cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 896232809Sjmallett cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap; 897232809Sjmallett cvmx_ilk_txx_mem_pmap_t ilk_txx_mem_pmap; 898232809Sjmallett cvmx_ilk_txx_int_t ilk_txx_int; 899232809Sjmallett cvmx_ilk_txx_pipe_t ilk_txx_pipe; 900232809Sjmallett cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal; 901232809Sjmallett cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0; 902232809Sjmallett cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1; 903232809Sjmallett 904232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 905232809Sjmallett cvmx_dprintf ("ilk txx cfg0: 0x%16lx\n", ilk_txx_cfg0.u64); 906232809Sjmallett 907232809Sjmallett ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 908232809Sjmallett cvmx_dprintf ("ilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64); 909232809Sjmallett 910232809Sjmallett ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface)); 911232809Sjmallett cvmx_dprintf ("ilk txx pipe: 0x%16lx\n", ilk_txx_pipe.u64); 912232809Sjmallett 913232809Sjmallett ilk_txx_idx_pmap.u64 = 0; 914232809Sjmallett ilk_txx_idx_pmap.s.index = ilk_txx_pipe.s.base; 915232809Sjmallett ilk_txx_idx_pmap.s.inc = 1; 916232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64); 917232809Sjmallett for (i = 0; i < CHAN_NUM_DBG; i++) 918232809Sjmallett { 919232809Sjmallett ilk_txx_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_TXX_MEM_PMAP(interface)); 920232809Sjmallett cvmx_dprintf ("ilk txx mem pmap pipe: %3d 0x%16lx\n", 921232809Sjmallett ilk_txx_pipe.s.base + i, ilk_txx_mem_pmap.u64); 922232809Sjmallett } 923232809Sjmallett 924232809Sjmallett ilk_txx_int.u64 = cvmx_read_csr (CVMX_ILK_TXX_INT(interface)); 925232809Sjmallett cvmx_dprintf ("ilk txx int: 0x%16lx\n", ilk_txx_int.u64); 926232809Sjmallett 927232809Sjmallett ilk_txx_idx_cal.u64 = 0; 928232809Sjmallett ilk_txx_idx_cal.s.inc = 1; 929232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64); 930232809Sjmallett for (i = 0; i < CAL_NUM_DBG; i++) 931232809Sjmallett { 932232809Sjmallett ilk_txx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_TXX_IDX_CAL(interface)); 933232809Sjmallett cvmx_dprintf ("ilk txx idx cal: 0x%16lx\n", ilk_txx_idx_cal.u64); 934232809Sjmallett 935232809Sjmallett ilk_txx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL0(interface)); 936232809Sjmallett cvmx_dprintf ("ilk txx mem cal0: 0x%16lx\n", ilk_txx_mem_cal0.u64); 937232809Sjmallett ilk_txx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL1(interface)); 938232809Sjmallett cvmx_dprintf ("ilk txx mem cal1: 0x%16lx\n", ilk_txx_mem_cal1.u64); 939232809Sjmallett } 940232809Sjmallett} 941232809Sjmallett#endif 942232809Sjmallett 943232809Sjmallett/** 944232809Sjmallett * show run time status 945232809Sjmallett * 946232809Sjmallett * @param interface The identifier of the packet interface to enable. cn68xx 947232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 948232809Sjmallett * 949232809Sjmallett * @return nothing 950232809Sjmallett */ 951232809Sjmallett#ifdef CVMX_ILK_RUNTIME_DBG 952232809Sjmallettvoid cvmx_ilk_runtime_status (int interface) 953232809Sjmallett{ 954232809Sjmallett cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 955232809Sjmallett cvmx_ilk_txx_flow_ctl0_t ilk_txx_flow_ctl0; 956232809Sjmallett cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 957232809Sjmallett cvmx_ilk_rxx_int_t ilk_rxx_int; 958232809Sjmallett cvmx_ilk_rxx_flow_ctl0_t ilk_rxx_flow_ctl0; 959232809Sjmallett cvmx_ilk_rxx_flow_ctl1_t ilk_rxx_flow_ctl1; 960232809Sjmallett cvmx_ilk_gbl_int_t ilk_gbl_int; 961232809Sjmallett 962232809Sjmallett cvmx_dprintf ("\nilk run-time status: interface: %d\n", interface); 963232809Sjmallett 964232809Sjmallett ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 965232809Sjmallett cvmx_dprintf ("\nilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64); 966232809Sjmallett if (ilk_txx_cfg1.s.rx_link_fc) 967232809Sjmallett cvmx_dprintf ("link flow control received\n"); 968232809Sjmallett if (ilk_txx_cfg1.s.tx_link_fc) 969232809Sjmallett cvmx_dprintf ("link flow control sent\n"); 970232809Sjmallett 971232809Sjmallett ilk_txx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_TXX_FLOW_CTL0(interface)); 972232809Sjmallett cvmx_dprintf ("\nilk txx flow ctl0: 0x%16lx\n", ilk_txx_flow_ctl0.u64); 973232809Sjmallett 974232809Sjmallett ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 975232809Sjmallett cvmx_dprintf ("\nilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64); 976232809Sjmallett cvmx_dprintf ("rx fifo count: %d\n", ilk_rxx_cfg1.s.rx_fifo_cnt); 977232809Sjmallett 978232809Sjmallett ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface)); 979232809Sjmallett cvmx_dprintf ("\nilk rxx int: 0x%16lx\n", ilk_rxx_int.u64); 980232809Sjmallett if (ilk_rxx_int.s.pkt_drop_rxf) 981232809Sjmallett cvmx_dprintf ("rx fifo packet drop\n"); 982232809Sjmallett if (ilk_rxx_int.u64) 983232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64); 984232809Sjmallett 985232809Sjmallett ilk_rxx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL0(interface)); 986232809Sjmallett cvmx_dprintf ("\nilk rxx flow ctl0: 0x%16lx\n", ilk_rxx_flow_ctl0.u64); 987232809Sjmallett 988232809Sjmallett ilk_rxx_flow_ctl1.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL1(interface)); 989232809Sjmallett cvmx_dprintf ("\nilk rxx flow ctl1: 0x%16lx\n", ilk_rxx_flow_ctl1.u64); 990232809Sjmallett 991232809Sjmallett ilk_gbl_int.u64 = cvmx_read_csr (CVMX_ILK_GBL_INT); 992232809Sjmallett cvmx_dprintf ("\nilk gbl int: 0x%16lx\n", ilk_gbl_int.u64); 993232809Sjmallett if (ilk_gbl_int.s.rxf_push_full) 994232809Sjmallett cvmx_dprintf ("rx fifo overflow\n"); 995232809Sjmallett if (ilk_gbl_int.u64) 996232809Sjmallett cvmx_write_csr (CVMX_ILK_GBL_INT, ilk_gbl_int.u64); 997232809Sjmallett} 998232809Sjmallett#endif 999232809Sjmallett 1000232809Sjmallett/** 1001232809Sjmallett * enable interface 1002232809Sjmallett * 1003232809Sjmallett * @param interface The identifier of the packet interface to enable. cn68xx 1004232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1005232809Sjmallett * 1006232809Sjmallett * @return Zero on success, negative of failure. 1007232809Sjmallett */ 1008232809Sjmallett//#define CVMX_ILK_STATS_ENA 1 1009232809Sjmallettint cvmx_ilk_enable (int interface) 1010232809Sjmallett{ 1011232809Sjmallett int res = -1; 1012232809Sjmallett int retry_count = 0; 1013232809Sjmallett cvmx_helper_link_info_t result; 1014232809Sjmallett cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 1015232809Sjmallett cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 1016232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1017232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1018232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1019232809Sjmallett#endif 1020232809Sjmallett 1021232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1022232809Sjmallett return res; 1023232809Sjmallett 1024232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 1025232809Sjmallett return res; 1026232809Sjmallett 1027232809Sjmallett result.u64 = 0; 1028232809Sjmallett 1029232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1030232809Sjmallett cvmx_dprintf ("\n"); 1031232809Sjmallett cvmx_dprintf ("<<<< ILK%d: Before enabling ilk\n", interface); 1032232809Sjmallett cvmx_ilk_reg_dump_rx (interface); 1033232809Sjmallett cvmx_ilk_reg_dump_tx (interface); 1034232809Sjmallett#endif 1035232809Sjmallett 1036232809Sjmallett /* RX packet will be enabled only if link is up */ 1037232809Sjmallett 1038232809Sjmallett /* TX side */ 1039232809Sjmallett ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1040232809Sjmallett ilk_txx_cfg1.s.pkt_ena = 1; 1041232809Sjmallett ilk_txx_cfg1.s.rx_link_fc_ign = 1; /* cannot use link fc workaround */ 1042232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64); 1043232809Sjmallett cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1044232809Sjmallett 1045232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1046232809Sjmallett /* RX side stats */ 1047232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1048232809Sjmallett ilk_rxx_cfg0.s.lnk_stats_ena = 1; 1049232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1050232809Sjmallett 1051232809Sjmallett /* TX side stats */ 1052232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1053232809Sjmallett ilk_txx_cfg0.s.lnk_stats_ena = 1; 1054232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1055232809Sjmallett#endif 1056232809Sjmallett 1057232809Sjmallettretry: 1058232809Sjmallett retry_count++; 1059232809Sjmallett if (retry_count > 10) 1060232809Sjmallett goto out; 1061232809Sjmallett 1062232809Sjmallett /* Make sure the link is up, so that packets can be sent. */ 1063232809Sjmallett result = __cvmx_helper_ilk_link_get(cvmx_helper_get_ipd_port(interface + CVMX_ILK_GBL_BASE, 0)); 1064232809Sjmallett 1065232809Sjmallett /* Small delay before another retry. */ 1066232809Sjmallett cvmx_wait_usec(100); 1067232809Sjmallett 1068232809Sjmallett ilk_rxx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_RXX_CFG1(interface)); 1069232809Sjmallett if (ilk_rxx_cfg1.s.pkt_ena == 0) 1070232809Sjmallett goto retry; 1071232809Sjmallett 1072232809Sjmallettout: 1073232809Sjmallett 1074232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1075232809Sjmallett cvmx_dprintf (">>>> ILK%d: After ILK is enabled\n", interface); 1076232809Sjmallett cvmx_ilk_reg_dump_rx (interface); 1077232809Sjmallett cvmx_ilk_reg_dump_tx (interface); 1078232809Sjmallett#endif 1079232809Sjmallett 1080232809Sjmallett if (result.s.link_up) 1081232809Sjmallett return 0; 1082232809Sjmallett 1083232809Sjmallett return -1; 1084232809Sjmallett} 1085232809Sjmallett 1086232809Sjmallett/** 1087232809Sjmallett * Disable interface 1088232809Sjmallett * 1089232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1090232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1091232809Sjmallett * 1092232809Sjmallett * @return Zero on success, negative of failure. 1093232809Sjmallett */ 1094232809Sjmallettint cvmx_ilk_disable (int interface) 1095232809Sjmallett{ 1096232809Sjmallett int res = -1; 1097232809Sjmallett cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 1098232809Sjmallett cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 1099232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1100232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1101232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1102232809Sjmallett#endif 1103232809Sjmallett 1104232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1105232809Sjmallett return res; 1106232809Sjmallett 1107232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 1108232809Sjmallett return res; 1109232809Sjmallett 1110232809Sjmallett /* TX side */ 1111232809Sjmallett ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1112232809Sjmallett ilk_txx_cfg1.s.pkt_ena = 0; 1113232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64); 1114232809Sjmallett 1115232809Sjmallett /* RX side */ 1116232809Sjmallett ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 1117232809Sjmallett ilk_rxx_cfg1.s.pkt_ena = 0; 1118232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64); 1119232809Sjmallett 1120232809Sjmallett#ifdef CVMX_ILK_STATS_ENA 1121232809Sjmallett /* RX side stats */ 1122232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1123232809Sjmallett ilk_rxx_cfg0.s.lnk_stats_ena = 0; 1124232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1125232809Sjmallett 1126232809Sjmallett /* RX side stats */ 1127232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1128232809Sjmallett ilk_txx_cfg0.s.lnk_stats_ena = 0; 1129232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1130232809Sjmallett#endif 1131232809Sjmallett 1132232809Sjmallett return 0; 1133232809Sjmallett} 1134232809Sjmallett 1135232809Sjmallett/** 1136232809Sjmallett * Provide interface enable status 1137232809Sjmallett * 1138232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1139232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1140232809Sjmallett * 1141232809Sjmallett * @return Zero, not enabled; One, enabled. 1142232809Sjmallett */ 1143232809Sjmallettint cvmx_ilk_get_intf_ena (int interface) 1144232809Sjmallett{ 1145232809Sjmallett return cvmx_ilk_intf_cfg[interface].intf_en; 1146232809Sjmallett} 1147232809Sjmallett 1148232809Sjmallett/** 1149232809Sjmallett * bit counter 1150232809Sjmallett * 1151232809Sjmallett * @param uc the byte to be counted 1152232809Sjmallett * 1153232809Sjmallett * @return number of bits set 1154232809Sjmallett */ 1155232809Sjmallettunsigned char cvmx_ilk_bit_count (unsigned char uc) 1156232809Sjmallett{ 1157232809Sjmallett unsigned char count; 1158232809Sjmallett 1159232809Sjmallett for (count = 0; uc > 0; uc &= uc-1) 1160232809Sjmallett count++; 1161232809Sjmallett 1162232809Sjmallett return count; 1163232809Sjmallett} 1164232809Sjmallett 1165232809Sjmallett/** 1166232809Sjmallett * Provide interface lane mask 1167232809Sjmallett * 1168232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1169232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1170232809Sjmallett * 1171232809Sjmallett * @return lane mask 1172232809Sjmallett */ 1173232809Sjmallettunsigned char cvmx_ilk_get_intf_ln_msk (int interface) 1174232809Sjmallett{ 1175232809Sjmallett return cvmx_ilk_intf_cfg[interface].lane_en_mask; 1176232809Sjmallett} 1177232809Sjmallett 1178232809Sjmallett/** 1179232809Sjmallett * Provide channel info 1180232809Sjmallett * 1181232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1182232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1183232809Sjmallett * @param chans A pointer to a channel array 1184232809Sjmallett * @param num_chan A pointer to the number of channels 1185232809Sjmallett * 1186232809Sjmallett * @return Zero on success, negative of failure. 1187232809Sjmallett */ 1188232809Sjmallettint cvmx_ilk_get_chan_info (int interface, unsigned char **chans, 1189232809Sjmallett unsigned char *num_chan) 1190232809Sjmallett{ 1191232809Sjmallett *chans = cvmx_ilk_chan_map[interface]; 1192232809Sjmallett *num_chan = cvmx_ilk_chans[interface]; 1193232809Sjmallett 1194232809Sjmallett return 0; 1195232809Sjmallett} 1196232809Sjmallett 1197232809Sjmallett/** 1198232809Sjmallett * Show channel statistics 1199232809Sjmallett * 1200232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1201232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1202232809Sjmallett * @param pstats A pointer to cvmx_ilk_stats_ctrl_t that specifies which 1203232809Sjmallett * logical channels to access 1204232809Sjmallett * 1205232809Sjmallett * @return nothing 1206232809Sjmallett */ 1207232809Sjmallettvoid cvmx_ilk_show_stats (int interface, cvmx_ilk_stats_ctrl_t *pstats) 1208232809Sjmallett{ 1209232809Sjmallett unsigned int i; 1210232809Sjmallett cvmx_ilk_rxx_idx_stat0_t ilk_rxx_idx_stat0; 1211232809Sjmallett cvmx_ilk_rxx_idx_stat1_t ilk_rxx_idx_stat1; 1212232809Sjmallett cvmx_ilk_rxx_mem_stat0_t ilk_rxx_mem_stat0; 1213232809Sjmallett cvmx_ilk_rxx_mem_stat1_t ilk_rxx_mem_stat1; 1214232809Sjmallett 1215232809Sjmallett cvmx_ilk_txx_idx_stat0_t ilk_txx_idx_stat0; 1216232809Sjmallett cvmx_ilk_txx_idx_stat1_t ilk_txx_idx_stat1; 1217232809Sjmallett cvmx_ilk_txx_mem_stat0_t ilk_txx_mem_stat0; 1218232809Sjmallett cvmx_ilk_txx_mem_stat1_t ilk_txx_mem_stat1; 1219232809Sjmallett 1220232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1221232809Sjmallett return; 1222232809Sjmallett 1223232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 1224232809Sjmallett return; 1225232809Sjmallett 1226232809Sjmallett if (pstats == NULL) 1227232809Sjmallett return; 1228232809Sjmallett 1229232809Sjmallett /* discrete channels */ 1230232809Sjmallett if (pstats->chan_list != NULL) 1231232809Sjmallett { 1232232809Sjmallett for (i = 0; i < pstats->num_chans; i++) 1233232809Sjmallett { 1234232809Sjmallett 1235232809Sjmallett /* get the number of rx packets */ 1236232809Sjmallett ilk_rxx_idx_stat0.u64 = 0; 1237232809Sjmallett ilk_rxx_idx_stat0.s.index = *pstats->chan_list; 1238232809Sjmallett ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd; 1239232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), 1240232809Sjmallett ilk_rxx_idx_stat0.u64); 1241232809Sjmallett ilk_rxx_mem_stat0.u64 = cvmx_read_csr 1242232809Sjmallett (CVMX_ILK_RXX_MEM_STAT0(interface)); 1243232809Sjmallett 1244232809Sjmallett /* get the number of rx bytes */ 1245232809Sjmallett ilk_rxx_idx_stat1.u64 = 0; 1246232809Sjmallett ilk_rxx_idx_stat1.s.index = *pstats->chan_list; 1247232809Sjmallett ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd; 1248232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), 1249232809Sjmallett ilk_rxx_idx_stat1.u64); 1250232809Sjmallett ilk_rxx_mem_stat1.u64 = cvmx_read_csr 1251232809Sjmallett (CVMX_ILK_RXX_MEM_STAT1(interface)); 1252232809Sjmallett 1253232809Sjmallett cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, 1254232809Sjmallett *pstats->chan_list, ilk_rxx_mem_stat0.s.rx_pkt, 1255232809Sjmallett (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1256232809Sjmallett 1257232809Sjmallett /* get the number of tx packets */ 1258232809Sjmallett ilk_txx_idx_stat0.u64 = 0; 1259232809Sjmallett ilk_txx_idx_stat0.s.index = *pstats->chan_list; 1260232809Sjmallett ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd; 1261232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), 1262232809Sjmallett ilk_txx_idx_stat0.u64); 1263232809Sjmallett ilk_txx_mem_stat0.u64 = cvmx_read_csr 1264232809Sjmallett (CVMX_ILK_TXX_MEM_STAT0(interface)); 1265232809Sjmallett 1266232809Sjmallett /* get the number of tx bytes */ 1267232809Sjmallett ilk_txx_idx_stat1.u64 = 0; 1268232809Sjmallett ilk_txx_idx_stat1.s.index = *pstats->chan_list; 1269232809Sjmallett ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd; 1270232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), 1271232809Sjmallett ilk_txx_idx_stat1.u64); 1272232809Sjmallett ilk_txx_mem_stat1.u64 = cvmx_read_csr 1273232809Sjmallett (CVMX_ILK_TXX_MEM_STAT1(interface)); 1274232809Sjmallett 1275232809Sjmallett cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, 1276232809Sjmallett *pstats->chan_list, ilk_txx_mem_stat0.s.tx_pkt, 1277232809Sjmallett (unsigned int) ilk_txx_mem_stat1.s.tx_bytes); 1278232809Sjmallett 1279232809Sjmallett pstats++; 1280232809Sjmallett } 1281232809Sjmallett return; 1282232809Sjmallett } 1283232809Sjmallett 1284232809Sjmallett /* continuous channels */ 1285232809Sjmallett ilk_rxx_idx_stat0.u64 = 0; 1286232809Sjmallett ilk_rxx_idx_stat0.s.index = pstats->chan_start; 1287232809Sjmallett ilk_rxx_idx_stat0.s.inc = pstats->chan_step; 1288232809Sjmallett ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd; 1289232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), ilk_rxx_idx_stat0.u64); 1290232809Sjmallett 1291232809Sjmallett ilk_rxx_idx_stat1.u64 = 0; 1292232809Sjmallett ilk_rxx_idx_stat1.s.index = pstats->chan_start; 1293232809Sjmallett ilk_rxx_idx_stat1.s.inc = pstats->chan_step; 1294232809Sjmallett ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd; 1295232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), ilk_rxx_idx_stat1.u64); 1296232809Sjmallett 1297232809Sjmallett ilk_txx_idx_stat0.u64 = 0; 1298232809Sjmallett ilk_txx_idx_stat0.s.index = pstats->chan_start; 1299232809Sjmallett ilk_txx_idx_stat0.s.inc = pstats->chan_step; 1300232809Sjmallett ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd; 1301232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), ilk_txx_idx_stat0.u64); 1302232809Sjmallett 1303232809Sjmallett ilk_txx_idx_stat1.u64 = 0; 1304232809Sjmallett ilk_txx_idx_stat1.s.index = pstats->chan_start; 1305232809Sjmallett ilk_txx_idx_stat1.s.inc = pstats->chan_step; 1306232809Sjmallett ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd; 1307232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), ilk_txx_idx_stat1.u64); 1308232809Sjmallett 1309232809Sjmallett for (i = pstats->chan_start; i <= pstats->chan_end; i += pstats->chan_step) 1310232809Sjmallett { 1311232809Sjmallett ilk_rxx_mem_stat0.u64 = cvmx_read_csr 1312232809Sjmallett (CVMX_ILK_RXX_MEM_STAT0(interface)); 1313232809Sjmallett ilk_rxx_mem_stat1.u64 = cvmx_read_csr 1314232809Sjmallett (CVMX_ILK_RXX_MEM_STAT1(interface)); 1315232809Sjmallett cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, i, 1316232809Sjmallett ilk_rxx_mem_stat0.s.rx_pkt, 1317232809Sjmallett (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1318232809Sjmallett 1319232809Sjmallett ilk_txx_mem_stat0.u64 = cvmx_read_csr 1320232809Sjmallett (CVMX_ILK_TXX_MEM_STAT0(interface)); 1321232809Sjmallett ilk_txx_mem_stat1.u64 = cvmx_read_csr 1322232809Sjmallett (CVMX_ILK_TXX_MEM_STAT1(interface)); 1323232809Sjmallett cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, i, 1324232809Sjmallett ilk_rxx_mem_stat0.s.rx_pkt, 1325232809Sjmallett (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1326232809Sjmallett } 1327232809Sjmallett 1328232809Sjmallett return; 1329232809Sjmallett} 1330232809Sjmallett 1331232809Sjmallett/** 1332232809Sjmallett * enable or disable loopbacks 1333232809Sjmallett * 1334232809Sjmallett * @param interface The identifier of the packet interface to disable. cn68xx 1335232809Sjmallett * has 2 interfaces: ilk0 and ilk1. 1336232809Sjmallett * @param enable Enable or disable loopback 1337232809Sjmallett * @param mode Internal or external loopback 1338232809Sjmallett * 1339232809Sjmallett * @return Zero on success, negative of failure. 1340232809Sjmallett */ 1341232809Sjmallettint cvmx_ilk_lpbk (int interface, cvmx_ilk_lpbk_ena_t enable, 1342232809Sjmallett cvmx_ilk_lpbk_mode_t mode) 1343232809Sjmallett{ 1344232809Sjmallett int res = -1; 1345232809Sjmallett cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1346232809Sjmallett cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1347232809Sjmallett 1348232809Sjmallett if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1349232809Sjmallett return res; 1350232809Sjmallett 1351232809Sjmallett if (interface >= CVMX_NUM_ILK_INTF) 1352232809Sjmallett return res; 1353232809Sjmallett 1354232809Sjmallett /* internal loopback. only 1 type of loopback can be on at 1 time */ 1355232809Sjmallett if (mode == CVMX_ILK_LPBK_INT) 1356232809Sjmallett { 1357232809Sjmallett if (enable == CVMX_ILK_LPBK_ENA) 1358232809Sjmallett { 1359232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1360232809Sjmallett ilk_txx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA; 1361232809Sjmallett ilk_txx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA; 1362232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1363232809Sjmallett 1364232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1365232809Sjmallett ilk_rxx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA; 1366232809Sjmallett ilk_rxx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA; 1367232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1368232809Sjmallett } 1369232809Sjmallett 1370232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1371232809Sjmallett ilk_txx_cfg0.s.int_lpbk = enable; 1372232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1373232809Sjmallett 1374232809Sjmallett res = 0; 1375232809Sjmallett return res; 1376232809Sjmallett } 1377232809Sjmallett 1378232809Sjmallett /* external loopback. only 1 type of loopback can be on at 1 time */ 1379232809Sjmallett if (enable == CVMX_ILK_LPBK_ENA) 1380232809Sjmallett { 1381232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1382232809Sjmallett ilk_txx_cfg0.s.int_lpbk = CVMX_ILK_LPBK_DISA; 1383232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1384232809Sjmallett } 1385232809Sjmallett 1386232809Sjmallett ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1387232809Sjmallett ilk_txx_cfg0.s.ext_lpbk = enable; 1388232809Sjmallett ilk_txx_cfg0.s.ext_lpbk_fc = enable; 1389232809Sjmallett cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1390232809Sjmallett 1391232809Sjmallett ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1392232809Sjmallett ilk_rxx_cfg0.s.ext_lpbk = enable; 1393232809Sjmallett ilk_rxx_cfg0.s.ext_lpbk_fc = enable; 1394232809Sjmallett cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1395232809Sjmallett 1396232809Sjmallett res = 0; 1397232809Sjmallett return res; 1398232809Sjmallett} 1399232809Sjmallett 1400232809Sjmallett#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ 1401