cvmx-ilk.c revision 232809
1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40/** 41 * @file 42 * 43 * Support library for the ILK 44 * 45 * <hr>$Revision: 49448 $<hr> 46 */ 47#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 48#include <linux/module.h> 49#include <asm/octeon/cvmx.h> 50#include <asm/octeon/cvmx-config.h> 51#include <asm/octeon/cvmx-sysinfo.h> 52#include <asm/octeon/cvmx-pko.h> 53#include <asm/octeon/cvmx-ilk.h> 54#include <asm/octeon/cvmx-ilk-defs.h> 55#include <asm/octeon/cvmx-helper-util.h> 56#include <asm/octeon/cvmx-helper-ilk.h> 57#else 58#include "cvmx.h" 59#include "cvmx-config.h" 60#include "cvmx-sysinfo.h" 61#include "cvmx-pko.h" 62#include "cvmx-ilk.h" 63#include "cvmx-helper-util.h" 64#include "cvmx-helper-ilk.h" 65#endif 66 67#ifdef CVMX_ENABLE_HELPER_FUNCTIONS 68 69/* 70 * global configurations. to disable the 2nd ILK, set 71 * cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xff, 0x0} and 72 * cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 0} 73 */ 74unsigned char cvmx_ilk_lane_mask[CVMX_NUM_ILK_INTF] = {0xf, 0xf0}; 75//#define SINGLE_PORT_SIM_ILK 76#ifdef SINGLE_PORT_SIM_ILK 77unsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {1, 1}; 78unsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] = 79{{0}, 80 {0}}; 81#else /* sample case */ 82unsigned char cvmx_ilk_chans[CVMX_NUM_ILK_INTF] = {8, 8}; 83unsigned char cvmx_ilk_chan_map[CVMX_NUM_ILK_INTF][CVMX_MAX_ILK_CHANS] = 84{{0, 1, 2, 3, 4, 5, 6, 7}, 85 {0, 1, 2, 3, 4, 5, 6, 7}}; 86#endif 87 88/* Default callbacks, can be overridden 89 * using cvmx_ilk_get_callbacks/cvmx_ilk_set_callbacks 90 */ 91static cvmx_ilk_callbacks_t cvmx_ilk_callbacks = { 92 .calendar_setup_rx = cvmx_ilk_cal_setup_rx, 93}; 94 95static cvmx_ilk_intf_t cvmx_ilk_intf_cfg[CVMX_NUM_ILK_INTF]; 96 97/** 98 * Get current ILK initialization callbacks 99 * 100 * @param callbacks Pointer to the callbacks structure.to fill 101 * 102 * @return Pointer to cvmx_ilk_callbacks_t structure. 103 */ 104void cvmx_ilk_get_callbacks(cvmx_ilk_callbacks_t * callbacks) 105{ 106 memcpy(callbacks, &cvmx_ilk_callbacks, sizeof(cvmx_ilk_callbacks)); 107} 108 109/** 110 * Set new ILK initialization callbacks 111 * 112 * @param new_callbacks Pointer to an updated callbacks structure. 113 */ 114void cvmx_ilk_set_callbacks(cvmx_ilk_callbacks_t * new_callbacks) 115{ 116 memcpy(&cvmx_ilk_callbacks, new_callbacks, sizeof(cvmx_ilk_callbacks)); 117} 118 119/** 120 * Initialize and start the ILK interface. 121 * 122 * @param interface The identifier of the packet interface to configure and 123 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 124 * ilk1. 125 * 126 * @param lane_mask the lane group for this interface 127 * 128 * @return Zero on success, negative of failure. 129 */ 130int cvmx_ilk_start_interface (int interface, unsigned char lane_mask) 131{ 132 int res = -1; 133 int other_intf, this_qlm, other_qlm; 134 unsigned char uni_mask; 135 cvmx_mio_qlmx_cfg_t mio_qlmx_cfg, other_mio_qlmx_cfg; 136 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 137 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 138 cvmx_ilk_ser_cfg_t ilk_ser_cfg; 139 140 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 141 return res; 142 143 if (interface >= CVMX_NUM_ILK_INTF) 144 return res; 145 146 if (lane_mask == 0) 147 return res; 148 149 /* check conflicts between 2 ilk interfaces. 1 lane can be assigned to 1 150 * interface only */ 151 other_intf = !interface; 152 this_qlm = interface + CVMX_ILK_QLM_BASE; 153 other_qlm = other_intf + CVMX_ILK_QLM_BASE; 154 if (cvmx_ilk_intf_cfg[other_intf].lane_en_mask & lane_mask) 155 { 156 cvmx_dprintf ("ILK%d: %s: lane assignment conflict\n", interface, 157 __FUNCTION__); 158 return res; 159 } 160 161 /* check the legality of the lane mask. interface 0 can have 8 lanes, 162 * while interface 1 can have 4 lanes at most */ 163 uni_mask = lane_mask >> (interface * 4); 164 if ((uni_mask != 0x1 && uni_mask != 0x3 && uni_mask != 0xf && 165 uni_mask != 0xff) || (interface == 1 && lane_mask > 0xf0)) 166 { 167#if CVMX_ENABLE_DEBUG_PRINTS 168 cvmx_dprintf ("ILK%d: %s: incorrect lane mask: 0x%x \n", interface, 169 __FUNCTION__, uni_mask); 170#endif 171 return res; 172 } 173 174 /* check the availability of qlms. qlm_cfg = 001 means the chip is fused 175 * to give this qlm to ilk */ 176 mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(this_qlm)); 177 other_mio_qlmx_cfg.u64 = cvmx_read_csr (CVMX_MIO_QLMX_CFG(other_qlm)); 178 if (mio_qlmx_cfg.s.qlm_cfg != 1 || 179 (uni_mask == 0xff && other_mio_qlmx_cfg.s.qlm_cfg != 1)) 180 { 181#if CVMX_ENABLE_DEBUG_PRINTS 182 cvmx_dprintf ("ILK%d: %s: qlm unavailable\n", interface, __FUNCTION__); 183#endif 184 return res; 185 } 186 187 /* power up the serdes */ 188 ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG); 189 if (ilk_ser_cfg.s.ser_pwrup == 0) 190 { 191 ilk_ser_cfg.s.ser_rxpol_auto = 1; 192 ilk_ser_cfg.s.ser_rxpol = 0; 193 ilk_ser_cfg.s.ser_txpol = 0; 194 ilk_ser_cfg.s.ser_reset_n = 0xff; 195 ilk_ser_cfg.s.ser_haul = 0; 196 } 197 ilk_ser_cfg.s.ser_pwrup |= ((interface ==0) && (lane_mask > 0xf)) ? 198 0x3 : (1 << interface); 199 cvmx_write_csr (CVMX_ILK_SER_CFG, ilk_ser_cfg.u64); 200 201 /* configure the lane enable of the interface */ 202 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 203 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 204 ilk_txx_cfg0.s.lane_ena = ilk_rxx_cfg0.s.lane_ena = lane_mask; 205 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 206 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 207 208 /* write to local cache. for lane speed, if interface 0 has 8 lanes, 209 * assume both qlms have the same speed */ 210 cvmx_ilk_intf_cfg[interface].intf_en = 1; 211 cvmx_ilk_intf_cfg[interface].lane_en_mask = lane_mask; 212 res = 0; 213 214 return res; 215} 216 217/** 218 * set pipe group base and length for the interface 219 * 220 * @param interface The identifier of the packet interface to configure and 221 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 222 * ilk1. 223 * 224 * @param pipe_base the base of the pipe group 225 * @param pipe_len the length of the pipe group 226 * 227 * @return Zero on success, negative of failure. 228 */ 229int cvmx_ilk_set_pipe (int interface, int pipe_base, unsigned int pipe_len) 230{ 231 int res = -1; 232 cvmx_ilk_txx_pipe_t ilk_txx_pipe; 233 234 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 235 return res; 236 237 if (interface >= CVMX_NUM_ILK_INTF) 238 return res; 239 240 /* base should be between 0 and 127. base + length should be <127 */ 241 if (!(pipe_base >= 0 && pipe_base <= 127) || (pipe_base + pipe_len > 127)) 242 { 243#if CVMX_ENABLE_DEBUG_PRINTS 244 cvmx_dprintf ("ILK%d: %s: pipe base/length out of bounds\n", interface, 245 __FUNCTION__); 246#endif 247 return res; 248 } 249 250 /* set them in ilk tx section */ 251 ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface)); 252 ilk_txx_pipe.s.base = pipe_base; 253 ilk_txx_pipe.s.nump = pipe_len; 254 cvmx_write_csr (CVMX_ILK_TXX_PIPE(interface), ilk_txx_pipe.u64); 255 res = 0; 256 257 return res; 258} 259 260/** 261 * set logical channels for tx 262 * 263 * @param interface The identifier of the packet interface to configure and 264 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 265 * ilk1. 266 * 267 * @param pch pointer to an array of pipe-channel pair 268 * @param num_chs the number of entries in the pipe-channel array 269 * 270 * @return Zero on success, negative of failure. 271 */ 272int cvmx_ilk_tx_set_channel (int interface, cvmx_ilk_pipe_chan_t *pch, 273 unsigned int num_chs) 274{ 275 int res = -1; 276 cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap; 277 unsigned int i; 278 279 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 280 return res; 281 282 if (interface >= CVMX_NUM_ILK_INTF) 283 return res; 284 285 if (pch == NULL || num_chs > CVMX_MAX_ILK_PIPES) 286 return res; 287 288 /* write the pair to ilk tx */ 289 for (i = 0; i < num_chs; i++) 290 { 291 ilk_txx_idx_pmap.u64 = 0; 292 ilk_txx_idx_pmap.s.index = pch->pipe; 293 cvmx_write_csr(CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64); 294 cvmx_write_csr(CVMX_ILK_TXX_MEM_PMAP(interface), pch->chan); 295 pch++; 296 } 297 res = 0; 298 299 return res; 300} 301 302/** 303 * set pkind for rx 304 * 305 * @param interface The identifier of the packet interface to configure and 306 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 307 * ilk1. 308 * 309 * @param chpknd pointer to an array of channel-pkind pair 310 * @param num_pknd the number of entries in the channel-pkind array 311 * 312 * @return Zero on success, negative of failure. 313 */ 314int cvmx_ilk_rx_set_pknd (int interface, cvmx_ilk_chan_pknd_t *chpknd, 315 unsigned int num_pknd) 316{ 317 int res = -1; 318 cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap; 319 unsigned int i; 320 321 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 322 return res; 323 324 if (interface >= CVMX_NUM_ILK_INTF) 325 return res; 326 327 if (chpknd == NULL || num_pknd > CVMX_MAX_ILK_PKNDS) 328 return res; 329 330 /* write the pair to ilk rx. note the channels for different interfaces 331 * are given in *chpknd and interface is not used as a param */ 332 for (i = 0; i < num_pknd; i++) 333 { 334 ilk_rxf_idx_pmap.u64 = 0; 335 ilk_rxf_idx_pmap.s.index = interface * 256 + chpknd->chan; 336 cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64); 337 cvmx_write_csr (CVMX_ILK_RXF_MEM_PMAP, chpknd->pknd); 338 chpknd++; 339 } 340 res = 0; 341 342 return res; 343} 344 345/** 346 * configure calendar for rx 347 * 348 * @param interface The identifier of the packet interface to configure and 349 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 350 * ilk1. 351 * 352 * @param cal_depth the number of calendar entries 353 * @param pent pointer to calendar entries 354 * 355 * @return Zero on success, negative of failure. 356 */ 357int cvmx_ilk_rx_cal_conf (int interface, int cal_depth, 358 cvmx_ilk_cal_entry_t *pent) 359{ 360 int res = -1, num_grp, num_rest, i, j; 361 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 362 cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal; 363 cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0; 364 cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1; 365 unsigned long int tmp; 366 367 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 368 return res; 369 370 if (interface >= CVMX_NUM_ILK_INTF) 371 return res; 372 373 if (cal_depth < CVMX_ILK_RX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL 374 || pent == NULL) 375 return res; 376 377 /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */ 378 /* TODO: test effectiveness */ 379#if 0 380 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID) 381 for (i = 0; i < cal_depth; i++) 382 pent->ent_ctrl = LINK; 383#endif 384 385 /* set the depth */ 386 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 387 ilk_rxx_cfg0.s.cal_depth = cal_depth; 388 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 389 390 /* set the calendar index */ 391 num_grp = cal_depth / CVMX_ILK_CAL_GRP_SZ; 392 num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ; 393 ilk_rxx_idx_cal.u64 = 0; 394 ilk_rxx_idx_cal.s.inc = 1; 395 cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64); 396 397 /* set the calendar entries. each group has both cal0 and cal1 registers */ 398 for (i = 0; i < num_grp; i++) 399 { 400 ilk_rxx_mem_cal0.u64 = 0; 401 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 402 { 403 tmp = 0; 404 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 405 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 406 ilk_rxx_mem_cal0.u64 |= tmp; 407 408 tmp = 0; 409 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 410 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 411 CVMX_ILK_PIPE_BPID_SZ; 412 ilk_rxx_mem_cal0.u64 |= tmp; 413 pent++; 414 } 415 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64); 416 417 ilk_rxx_mem_cal1.u64 = 0; 418 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 419 { 420 tmp = 0; 421 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 422 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 423 ilk_rxx_mem_cal1.u64 |= tmp; 424 425 tmp = 0; 426 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 427 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 428 CVMX_ILK_PIPE_BPID_SZ; 429 ilk_rxx_mem_cal1.u64 |= tmp; 430 pent++; 431 } 432 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64); 433 } 434 435 /* set the calendar entries, the fraction of a group. but both cal0 and 436 * cal1 must be written */ 437 ilk_rxx_mem_cal0.u64 = 0; 438 ilk_rxx_mem_cal1.u64 = 0; 439 for (i = 0; i < num_rest; i++) 440 { 441 if (i < CVMX_ILK_CAL_GRP_SZ/2) 442 { 443 tmp = 0; 444 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 445 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i; 446 ilk_rxx_mem_cal0.u64 |= tmp; 447 448 tmp = 0; 449 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 450 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * i + 451 CVMX_ILK_PIPE_BPID_SZ; 452 ilk_rxx_mem_cal0.u64 |= tmp; 453 pent++; 454 } 455 456 if (i >= CVMX_ILK_CAL_GRP_SZ/2) 457 { 458 tmp = 0; 459 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 460 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * 461 (i - CVMX_ILK_CAL_GRP_SZ/2); 462 ilk_rxx_mem_cal1.u64 |= tmp; 463 464 tmp = 0; 465 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 466 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * 467 (i - CVMX_ILK_CAL_GRP_SZ/2) + CVMX_ILK_PIPE_BPID_SZ; 468 ilk_rxx_mem_cal1.u64 |= tmp; 469 pent++; 470 } 471 } 472 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL0(interface), ilk_rxx_mem_cal0.u64); 473 cvmx_write_csr(CVMX_ILK_RXX_MEM_CAL1(interface), ilk_rxx_mem_cal1.u64); 474 cvmx_read_csr (CVMX_ILK_RXX_MEM_CAL1(interface)); 475 476 return 0; 477} 478 479/** 480 * set high water mark for rx 481 * 482 * @param interface The identifier of the packet interface to configure and 483 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 484 * ilk1. 485 * 486 * @param hi_wm high water mark for this interface 487 * 488 * @return Zero on success, negative of failure. 489 */ 490int cvmx_ilk_rx_set_hwm (int interface, int hi_wm) 491{ 492 int res = -1; 493 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 494 495 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 496 return res; 497 498 if (interface >= CVMX_NUM_ILK_INTF) 499 return res; 500 501 if (hi_wm <= 0) 502 return res; 503 504 /* set the hwm */ 505 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 506 ilk_rxx_cfg1.s.rx_fifo_hwm = hi_wm; 507 cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64); 508 res = 0; 509 510 return res; 511} 512 513/** 514 * enable calendar for rx 515 * 516 * @param interface The identifier of the packet interface to configure and 517 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 518 * ilk1. 519 * 520 * @param cal_ena enable or disable calendar 521 * 522 * @return Zero on success, negative of failure. 523 */ 524int cvmx_ilk_rx_cal_ena (int interface, unsigned char cal_ena) 525{ 526 int res = -1; 527 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 528 529 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 530 return res; 531 532 if (interface >= CVMX_NUM_ILK_INTF) 533 return res; 534 535 /* set the enable */ 536 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 537 ilk_rxx_cfg0.s.cal_ena = cal_ena; 538 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 539 cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 540 res = 0; 541 542 return res; 543} 544 545/** 546 * set up calendar for rx 547 * 548 * @param interface The identifier of the packet interface to configure and 549 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 550 * ilk1. 551 * 552 * @param cal_depth the number of calendar entries 553 * @param pent pointer to calendar entries 554 * @param hi_wm high water mark for this interface 555 * @param cal_ena enable or disable calendar 556 * 557 * @return Zero on success, negative of failure. 558 */ 559int cvmx_ilk_cal_setup_rx (int interface, int cal_depth, 560 cvmx_ilk_cal_entry_t *pent, int hi_wm, 561 unsigned char cal_ena) 562{ 563 int res = -1; 564 565 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 566 return res; 567 568 if (interface >= CVMX_NUM_ILK_INTF) 569 return res; 570 571 res = cvmx_ilk_rx_cal_conf (interface, cal_depth, pent); 572 if (res < 0) 573 return res; 574 575 res = cvmx_ilk_rx_set_hwm (interface, hi_wm); 576 if (res < 0) 577 return res; 578 579 res = cvmx_ilk_rx_cal_ena (interface, cal_ena); 580 return res; 581} 582#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 583EXPORT_SYMBOL(cvmx_ilk_cal_setup_rx); 584#endif 585 586/** 587 * configure calendar for tx 588 * 589 * @param interface The identifier of the packet interface to configure and 590 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 591 * ilk1. 592 * 593 * @param cal_depth the number of calendar entries 594 * @param pent pointer to calendar entries 595 * 596 * @return Zero on success, negative of failure. 597 */ 598int cvmx_ilk_tx_cal_conf (int interface, int cal_depth, 599 cvmx_ilk_cal_entry_t *pent) 600{ 601 int res = -1, num_grp, num_rest, i, j; 602 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 603 cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal; 604 cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0; 605 cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1; 606 unsigned long int tmp; 607 cvmx_ilk_cal_entry_t *ent_tmp; 608 609 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 610 return res; 611 612 if (interface >= CVMX_NUM_ILK_INTF) 613 return res; 614 615 if (cal_depth < CVMX_ILK_TX_MIN_CAL || cal_depth > CVMX_ILK_MAX_CAL 616 || pent == NULL) 617 return res; 618 619 /* mandatory link-level fc as workarounds for ILK-15397 and ILK-15479 */ 620 /* TODO: test effectiveness */ 621#if 0 622 if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1_0) && pent->ent_ctrl == PIPE_BPID) 623 for (i = 0; i < cal_depth; i++) 624 pent->ent_ctrl = LINK; 625#endif 626 627 /* tx calendar depth must be a multiple of 8 */ 628 num_grp = (cal_depth - 1) / CVMX_ILK_CAL_GRP_SZ + 1; 629 num_rest = cal_depth % CVMX_ILK_CAL_GRP_SZ; 630 if (num_rest != 0) 631 { 632 ent_tmp = pent + cal_depth; 633 for (i = num_rest; i < 8; i++, ent_tmp++) 634 { 635 ent_tmp->pipe_bpid = 0; 636 ent_tmp->ent_ctrl = XOFF; 637 } 638 } 639 cal_depth = num_grp * 8; 640 641 /* set the depth */ 642 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 643 ilk_txx_cfg0.s.cal_depth = cal_depth; 644 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 645 646 /* set the calendar index */ 647 ilk_txx_idx_cal.u64 = 0; 648 ilk_txx_idx_cal.s.inc = 1; 649 cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64); 650 651 /* set the calendar entries. each group has both cal0 and cal1 registers */ 652 for (i = 0; i < num_grp; i++) 653 { 654 ilk_txx_mem_cal0.u64 = 0; 655 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 656 { 657 tmp = 0; 658 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 659 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 660 ilk_txx_mem_cal0.u64 |= tmp; 661 662 tmp = 0; 663 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 664 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 665 CVMX_ILK_PIPE_BPID_SZ; 666 ilk_txx_mem_cal0.u64 |= tmp; 667 pent++; 668 } 669 cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL0(interface), ilk_txx_mem_cal0.u64); 670 671 ilk_txx_mem_cal1.u64 = 0; 672 for (j = 0; j < CVMX_ILK_CAL_GRP_SZ/2; j++) 673 { 674 tmp = 0; 675 tmp = pent->pipe_bpid & ~(~tmp << CVMX_ILK_PIPE_BPID_SZ); 676 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j; 677 ilk_txx_mem_cal1.u64 |= tmp; 678 679 tmp = 0; 680 tmp = pent->ent_ctrl & ~(~tmp << CVMX_ILK_ENT_CTRL_SZ); 681 tmp <<= (CVMX_ILK_PIPE_BPID_SZ + CVMX_ILK_ENT_CTRL_SZ) * j + 682 CVMX_ILK_PIPE_BPID_SZ; 683 ilk_txx_mem_cal1.u64 |= tmp; 684 pent++; 685 } 686 cvmx_write_csr(CVMX_ILK_TXX_MEM_CAL1(interface), ilk_txx_mem_cal1.u64); 687 } 688 cvmx_read_csr (CVMX_ILK_TXX_MEM_CAL1(interface)); 689 690 return 0; 691} 692 693/** 694 * configure backpressure for tx 695 * 696 * @param interface The identifier of the packet interface to configure and 697 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 698 * ilk1. 699 * 700 * @param cal_depth the number of calendar entries 701 * @param pent pointer to calendar entries 702 * 703 * @return Zero on success, negative of failure. 704 */ 705int cvmx_ilk_bp_conf (int interface, int cal_depth, cvmx_ilk_cal_entry_t *pent) 706{ 707 int res = -1, i; 708 cvmx_ipd_ctl_status_t ipd_ctl_status; 709 cvmx_ilk_cal_entry_t *tmp; 710 unsigned char bpid; 711 cvmx_ipd_bpidx_mbuf_th_t ipd_bpidx_mbuf_th; 712 713 /* enable bp for the interface */ 714 ipd_ctl_status.u64 = cvmx_read_csr (CVMX_IPD_CTL_STATUS); 715 ipd_ctl_status.s.pbp_en = 1; 716 cvmx_write_csr (CVMX_IPD_CTL_STATUS, ipd_ctl_status.u64); 717 718 /* enable bp for each id */ 719 for (i = 0, tmp = pent; i < cal_depth; i++, tmp++) 720 { 721 bpid = tmp->pipe_bpid; 722 ipd_bpidx_mbuf_th.u64 = 723 cvmx_read_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid)); 724 ipd_bpidx_mbuf_th.s.page_cnt = 1; /* 256 buffers */ 725 ipd_bpidx_mbuf_th.s.bp_enb = 1; 726 cvmx_write_csr (CVMX_IPD_BPIDX_MBUF_TH(bpid), ipd_bpidx_mbuf_th.u64); 727 } 728 res = 0; 729 730 return res; 731} 732 733/** 734 * enable calendar for tx 735 * 736 * @param interface The identifier of the packet interface to configure and 737 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 738 * ilk1. 739 * 740 * @param cal_ena enable or disable calendar 741 * 742 * @return Zero on success, negative of failure. 743 */ 744int cvmx_ilk_tx_cal_ena (int interface, unsigned char cal_ena) 745{ 746 int res = -1; 747 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 748 749 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 750 return res; 751 752 if (interface >= CVMX_NUM_ILK_INTF) 753 return res; 754 755 /* set the enable */ 756 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 757 ilk_txx_cfg0.s.cal_ena = cal_ena; 758 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 759 cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 760 res = 0; 761 762 return res; 763} 764 765/** 766 * set up calendar for tx 767 * 768 * @param interface The identifier of the packet interface to configure and 769 * use as a ILK interface. cn68xx has 2 interfaces: ilk0 and 770 * ilk1. 771 * 772 * @param cal_depth the number of calendar entries 773 * @param pent pointer to calendar entries 774 * @param cal_ena enable or disable calendar 775 * 776 * @return Zero on success, negative of failure. 777 */ 778int cvmx_ilk_cal_setup_tx (int interface, int cal_depth, 779 cvmx_ilk_cal_entry_t *pent, unsigned char cal_ena) 780{ 781 int res = -1; 782 783 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 784 return res; 785 786 if (interface >= CVMX_NUM_ILK_INTF) 787 return res; 788 789 res = cvmx_ilk_tx_cal_conf (interface, cal_depth, pent); 790 if (res < 0) 791 return res; 792 793#ifdef CVMX_ILK_BP_CONF_ENA 794 res = cvmx_ilk_bp_conf (interface, cal_depth, pent); 795 if (res < 0) 796 return res; 797#endif 798 799 res = cvmx_ilk_tx_cal_ena (interface, cal_ena); 800 return res; 801} 802#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 803EXPORT_SYMBOL(cvmx_ilk_cal_setup_tx); 804#endif 805 806#ifdef CVMX_ILK_STATS_ENA 807static void cvmx_ilk_reg_dump_rx (int interface) 808{ 809 int i; 810 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 811 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 812 cvmx_ilk_rxx_int_t ilk_rxx_int; 813 cvmx_ilk_rxx_jabber_t ilk_rxx_jabber; 814 cvmx_ilk_rx_lnex_cfg_t ilk_rx_lnex_cfg; 815 cvmx_ilk_rx_lnex_int_t ilk_rx_lnex_int; 816 cvmx_ilk_gbl_cfg_t ilk_gbl_cfg; 817 cvmx_ilk_ser_cfg_t ilk_ser_cfg; 818 cvmx_ilk_rxf_idx_pmap_t ilk_rxf_idx_pmap; 819 cvmx_ilk_rxf_mem_pmap_t ilk_rxf_mem_pmap; 820 cvmx_ilk_rxx_idx_cal_t ilk_rxx_idx_cal; 821 cvmx_ilk_rxx_mem_cal0_t ilk_rxx_mem_cal0; 822 cvmx_ilk_rxx_mem_cal1_t ilk_rxx_mem_cal1; 823 824 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 825 cvmx_dprintf ("ilk rxx cfg0: 0x%16lx\n", ilk_rxx_cfg0.u64); 826 827 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 828 cvmx_dprintf ("ilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64); 829 830 ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface)); 831 cvmx_dprintf ("ilk rxx int: 0x%16lx\n", ilk_rxx_int.u64); 832 cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64); 833 834 ilk_rxx_jabber.u64 = cvmx_read_csr (CVMX_ILK_RXX_JABBER(interface)); 835 cvmx_dprintf ("ilk rxx jabber: 0x%16lx\n", ilk_rxx_jabber.u64); 836 837#define LNE_NUM_DBG 4 838 for (i = 0; i < LNE_NUM_DBG; i++) 839 { 840 ilk_rx_lnex_cfg.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_CFG(i)); 841 cvmx_dprintf ("ilk rx lnex cfg lane: %d 0x%16lx\n", i, 842 ilk_rx_lnex_cfg.u64); 843 } 844 845 for (i = 0; i < LNE_NUM_DBG; i++) 846 { 847 ilk_rx_lnex_int.u64 = cvmx_read_csr (CVMX_ILK_RX_LNEX_INT(i)); 848 cvmx_dprintf ("ilk rx lnex int lane: %d 0x%16lx\n", i, 849 ilk_rx_lnex_int.u64); 850 cvmx_write_csr (CVMX_ILK_RX_LNEX_INT(i), ilk_rx_lnex_int.u64); 851 } 852 853 ilk_gbl_cfg.u64 = cvmx_read_csr (CVMX_ILK_GBL_CFG); 854 cvmx_dprintf ("ilk gbl cfg: 0x%16lx\n", ilk_gbl_cfg.u64); 855 856 ilk_ser_cfg.u64 = cvmx_read_csr (CVMX_ILK_SER_CFG); 857 cvmx_dprintf ("ilk ser cfg: 0x%16lx\n", ilk_ser_cfg.u64); 858 859#define CHAN_NUM_DBG 8 860 ilk_rxf_idx_pmap.u64 = 0; 861 ilk_rxf_idx_pmap.s.index = interface * 256; 862 ilk_rxf_idx_pmap.s.inc = 1; 863 cvmx_write_csr (CVMX_ILK_RXF_IDX_PMAP, ilk_rxf_idx_pmap.u64); 864 for (i = 0; i < CHAN_NUM_DBG; i++) 865 { 866 ilk_rxf_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_RXF_MEM_PMAP); 867 cvmx_dprintf ("ilk rxf mem pmap chan: %3d 0x%16lx\n", i, 868 ilk_rxf_mem_pmap.u64); 869 } 870 871#define CAL_NUM_DBG 2 872 ilk_rxx_idx_cal.u64 = 0; 873 ilk_rxx_idx_cal.s.inc = 1; 874 cvmx_write_csr (CVMX_ILK_RXX_IDX_CAL(interface), ilk_rxx_idx_cal.u64); 875 for (i = 0; i < CAL_NUM_DBG; i++) 876 { 877 ilk_rxx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_RXX_IDX_CAL(interface)); 878 cvmx_dprintf ("ilk rxx idx cal: 0x%16lx\n", ilk_rxx_idx_cal.u64); 879 880 ilk_rxx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL0(interface)); 881 cvmx_dprintf ("ilk rxx mem cal0: 0x%16lx\n", ilk_rxx_mem_cal0.u64); 882 ilk_rxx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_RXX_MEM_CAL1(interface)); 883 cvmx_dprintf ("ilk rxx mem cal1: 0x%16lx\n", ilk_rxx_mem_cal1.u64); 884 } 885} 886 887static void cvmx_ilk_reg_dump_tx (int interface) 888{ 889 int i; 890 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 891 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 892 cvmx_ilk_txx_idx_pmap_t ilk_txx_idx_pmap; 893 cvmx_ilk_txx_mem_pmap_t ilk_txx_mem_pmap; 894 cvmx_ilk_txx_int_t ilk_txx_int; 895 cvmx_ilk_txx_pipe_t ilk_txx_pipe; 896 cvmx_ilk_txx_idx_cal_t ilk_txx_idx_cal; 897 cvmx_ilk_txx_mem_cal0_t ilk_txx_mem_cal0; 898 cvmx_ilk_txx_mem_cal1_t ilk_txx_mem_cal1; 899 900 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 901 cvmx_dprintf ("ilk txx cfg0: 0x%16lx\n", ilk_txx_cfg0.u64); 902 903 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 904 cvmx_dprintf ("ilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64); 905 906 ilk_txx_pipe.u64 = cvmx_read_csr (CVMX_ILK_TXX_PIPE(interface)); 907 cvmx_dprintf ("ilk txx pipe: 0x%16lx\n", ilk_txx_pipe.u64); 908 909 ilk_txx_idx_pmap.u64 = 0; 910 ilk_txx_idx_pmap.s.index = ilk_txx_pipe.s.base; 911 ilk_txx_idx_pmap.s.inc = 1; 912 cvmx_write_csr (CVMX_ILK_TXX_IDX_PMAP(interface), ilk_txx_idx_pmap.u64); 913 for (i = 0; i < CHAN_NUM_DBG; i++) 914 { 915 ilk_txx_mem_pmap.u64 = cvmx_read_csr (CVMX_ILK_TXX_MEM_PMAP(interface)); 916 cvmx_dprintf ("ilk txx mem pmap pipe: %3d 0x%16lx\n", 917 ilk_txx_pipe.s.base + i, ilk_txx_mem_pmap.u64); 918 } 919 920 ilk_txx_int.u64 = cvmx_read_csr (CVMX_ILK_TXX_INT(interface)); 921 cvmx_dprintf ("ilk txx int: 0x%16lx\n", ilk_txx_int.u64); 922 923 ilk_txx_idx_cal.u64 = 0; 924 ilk_txx_idx_cal.s.inc = 1; 925 cvmx_write_csr (CVMX_ILK_TXX_IDX_CAL(interface), ilk_txx_idx_cal.u64); 926 for (i = 0; i < CAL_NUM_DBG; i++) 927 { 928 ilk_txx_idx_cal.u64 = cvmx_read_csr(CVMX_ILK_TXX_IDX_CAL(interface)); 929 cvmx_dprintf ("ilk txx idx cal: 0x%16lx\n", ilk_txx_idx_cal.u64); 930 931 ilk_txx_mem_cal0.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL0(interface)); 932 cvmx_dprintf ("ilk txx mem cal0: 0x%16lx\n", ilk_txx_mem_cal0.u64); 933 ilk_txx_mem_cal1.u64 = cvmx_read_csr(CVMX_ILK_TXX_MEM_CAL1(interface)); 934 cvmx_dprintf ("ilk txx mem cal1: 0x%16lx\n", ilk_txx_mem_cal1.u64); 935 } 936} 937#endif 938 939/** 940 * show run time status 941 * 942 * @param interface The identifier of the packet interface to enable. cn68xx 943 * has 2 interfaces: ilk0 and ilk1. 944 * 945 * @return nothing 946 */ 947#ifdef CVMX_ILK_RUNTIME_DBG 948void cvmx_ilk_runtime_status (int interface) 949{ 950 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 951 cvmx_ilk_txx_flow_ctl0_t ilk_txx_flow_ctl0; 952 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 953 cvmx_ilk_rxx_int_t ilk_rxx_int; 954 cvmx_ilk_rxx_flow_ctl0_t ilk_rxx_flow_ctl0; 955 cvmx_ilk_rxx_flow_ctl1_t ilk_rxx_flow_ctl1; 956 cvmx_ilk_gbl_int_t ilk_gbl_int; 957 958 cvmx_dprintf ("\nilk run-time status: interface: %d\n", interface); 959 960 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 961 cvmx_dprintf ("\nilk txx cfg1: 0x%16lx\n", ilk_txx_cfg1.u64); 962 if (ilk_txx_cfg1.s.rx_link_fc) 963 cvmx_dprintf ("link flow control received\n"); 964 if (ilk_txx_cfg1.s.tx_link_fc) 965 cvmx_dprintf ("link flow control sent\n"); 966 967 ilk_txx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_TXX_FLOW_CTL0(interface)); 968 cvmx_dprintf ("\nilk txx flow ctl0: 0x%16lx\n", ilk_txx_flow_ctl0.u64); 969 970 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 971 cvmx_dprintf ("\nilk rxx cfg1: 0x%16lx\n", ilk_rxx_cfg1.u64); 972 cvmx_dprintf ("rx fifo count: %d\n", ilk_rxx_cfg1.s.rx_fifo_cnt); 973 974 ilk_rxx_int.u64 = cvmx_read_csr (CVMX_ILK_RXX_INT(interface)); 975 cvmx_dprintf ("\nilk rxx int: 0x%16lx\n", ilk_rxx_int.u64); 976 if (ilk_rxx_int.s.pkt_drop_rxf) 977 cvmx_dprintf ("rx fifo packet drop\n"); 978 if (ilk_rxx_int.u64) 979 cvmx_write_csr (CVMX_ILK_RXX_INT(interface), ilk_rxx_int.u64); 980 981 ilk_rxx_flow_ctl0.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL0(interface)); 982 cvmx_dprintf ("\nilk rxx flow ctl0: 0x%16lx\n", ilk_rxx_flow_ctl0.u64); 983 984 ilk_rxx_flow_ctl1.u64 = cvmx_read_csr (CVMX_ILK_RXX_FLOW_CTL1(interface)); 985 cvmx_dprintf ("\nilk rxx flow ctl1: 0x%16lx\n", ilk_rxx_flow_ctl1.u64); 986 987 ilk_gbl_int.u64 = cvmx_read_csr (CVMX_ILK_GBL_INT); 988 cvmx_dprintf ("\nilk gbl int: 0x%16lx\n", ilk_gbl_int.u64); 989 if (ilk_gbl_int.s.rxf_push_full) 990 cvmx_dprintf ("rx fifo overflow\n"); 991 if (ilk_gbl_int.u64) 992 cvmx_write_csr (CVMX_ILK_GBL_INT, ilk_gbl_int.u64); 993} 994#endif 995 996/** 997 * enable interface 998 * 999 * @param interface The identifier of the packet interface to enable. cn68xx 1000 * has 2 interfaces: ilk0 and ilk1. 1001 * 1002 * @return Zero on success, negative of failure. 1003 */ 1004//#define CVMX_ILK_STATS_ENA 1 1005int cvmx_ilk_enable (int interface) 1006{ 1007 int res = -1; 1008 int retry_count = 0; 1009 cvmx_helper_link_info_t result; 1010 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 1011 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 1012#ifdef CVMX_ILK_STATS_ENA 1013 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1014 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1015#endif 1016 1017 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1018 return res; 1019 1020 if (interface >= CVMX_NUM_ILK_INTF) 1021 return res; 1022 1023 result.u64 = 0; 1024 1025#ifdef CVMX_ILK_STATS_ENA 1026 cvmx_dprintf ("\n"); 1027 cvmx_dprintf ("<<<< ILK%d: Before enabling ilk\n", interface); 1028 cvmx_ilk_reg_dump_rx (interface); 1029 cvmx_ilk_reg_dump_tx (interface); 1030#endif 1031 1032 /* RX packet will be enabled only if link is up */ 1033 1034 /* TX side */ 1035 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1036 ilk_txx_cfg1.s.pkt_ena = 1; 1037 ilk_txx_cfg1.s.rx_link_fc_ign = 1; /* cannot use link fc workaround */ 1038 cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64); 1039 cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1040 1041#ifdef CVMX_ILK_STATS_ENA 1042 /* RX side stats */ 1043 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1044 ilk_rxx_cfg0.s.lnk_stats_ena = 1; 1045 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1046 1047 /* TX side stats */ 1048 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1049 ilk_txx_cfg0.s.lnk_stats_ena = 1; 1050 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1051#endif 1052 1053retry: 1054 retry_count++; 1055 if (retry_count > 10) 1056 goto out; 1057 1058 /* Make sure the link is up, so that packets can be sent. */ 1059 result = __cvmx_helper_ilk_link_get(cvmx_helper_get_ipd_port(interface + CVMX_ILK_GBL_BASE, 0)); 1060 1061 /* Small delay before another retry. */ 1062 cvmx_wait_usec(100); 1063 1064 ilk_rxx_cfg1.u64 = cvmx_read_csr(CVMX_ILK_RXX_CFG1(interface)); 1065 if (ilk_rxx_cfg1.s.pkt_ena == 0) 1066 goto retry; 1067 1068out: 1069 1070#ifdef CVMX_ILK_STATS_ENA 1071 cvmx_dprintf (">>>> ILK%d: After ILK is enabled\n", interface); 1072 cvmx_ilk_reg_dump_rx (interface); 1073 cvmx_ilk_reg_dump_tx (interface); 1074#endif 1075 1076 if (result.s.link_up) 1077 return 0; 1078 1079 return -1; 1080} 1081 1082/** 1083 * Disable interface 1084 * 1085 * @param interface The identifier of the packet interface to disable. cn68xx 1086 * has 2 interfaces: ilk0 and ilk1. 1087 * 1088 * @return Zero on success, negative of failure. 1089 */ 1090int cvmx_ilk_disable (int interface) 1091{ 1092 int res = -1; 1093 cvmx_ilk_txx_cfg1_t ilk_txx_cfg1; 1094 cvmx_ilk_rxx_cfg1_t ilk_rxx_cfg1; 1095#ifdef CVMX_ILK_STATS_ENA 1096 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1097 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1098#endif 1099 1100 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1101 return res; 1102 1103 if (interface >= CVMX_NUM_ILK_INTF) 1104 return res; 1105 1106 /* TX side */ 1107 ilk_txx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG1(interface)); 1108 ilk_txx_cfg1.s.pkt_ena = 0; 1109 cvmx_write_csr (CVMX_ILK_TXX_CFG1(interface), ilk_txx_cfg1.u64); 1110 1111 /* RX side */ 1112 ilk_rxx_cfg1.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG1(interface)); 1113 ilk_rxx_cfg1.s.pkt_ena = 0; 1114 cvmx_write_csr (CVMX_ILK_RXX_CFG1(interface), ilk_rxx_cfg1.u64); 1115 1116#ifdef CVMX_ILK_STATS_ENA 1117 /* RX side stats */ 1118 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1119 ilk_rxx_cfg0.s.lnk_stats_ena = 0; 1120 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1121 1122 /* RX side stats */ 1123 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1124 ilk_txx_cfg0.s.lnk_stats_ena = 0; 1125 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1126#endif 1127 1128 return 0; 1129} 1130 1131/** 1132 * Provide interface enable status 1133 * 1134 * @param interface The identifier of the packet interface to disable. cn68xx 1135 * has 2 interfaces: ilk0 and ilk1. 1136 * 1137 * @return Zero, not enabled; One, enabled. 1138 */ 1139int cvmx_ilk_get_intf_ena (int interface) 1140{ 1141 return cvmx_ilk_intf_cfg[interface].intf_en; 1142} 1143 1144/** 1145 * bit counter 1146 * 1147 * @param uc the byte to be counted 1148 * 1149 * @return number of bits set 1150 */ 1151unsigned char cvmx_ilk_bit_count (unsigned char uc) 1152{ 1153 unsigned char count; 1154 1155 for (count = 0; uc > 0; uc &= uc-1) 1156 count++; 1157 1158 return count; 1159} 1160 1161/** 1162 * Provide interface lane mask 1163 * 1164 * @param interface The identifier of the packet interface to disable. cn68xx 1165 * has 2 interfaces: ilk0 and ilk1. 1166 * 1167 * @return lane mask 1168 */ 1169unsigned char cvmx_ilk_get_intf_ln_msk (int interface) 1170{ 1171 return cvmx_ilk_intf_cfg[interface].lane_en_mask; 1172} 1173 1174/** 1175 * Provide channel info 1176 * 1177 * @param interface The identifier of the packet interface to disable. cn68xx 1178 * has 2 interfaces: ilk0 and ilk1. 1179 * @param chans A pointer to a channel array 1180 * @param num_chan A pointer to the number of channels 1181 * 1182 * @return Zero on success, negative of failure. 1183 */ 1184int cvmx_ilk_get_chan_info (int interface, unsigned char **chans, 1185 unsigned char *num_chan) 1186{ 1187 *chans = cvmx_ilk_chan_map[interface]; 1188 *num_chan = cvmx_ilk_chans[interface]; 1189 1190 return 0; 1191} 1192 1193/** 1194 * Show channel statistics 1195 * 1196 * @param interface The identifier of the packet interface to disable. cn68xx 1197 * has 2 interfaces: ilk0 and ilk1. 1198 * @param pstats A pointer to cvmx_ilk_stats_ctrl_t that specifies which 1199 * logical channels to access 1200 * 1201 * @return nothing 1202 */ 1203void cvmx_ilk_show_stats (int interface, cvmx_ilk_stats_ctrl_t *pstats) 1204{ 1205 unsigned int i; 1206 cvmx_ilk_rxx_idx_stat0_t ilk_rxx_idx_stat0; 1207 cvmx_ilk_rxx_idx_stat1_t ilk_rxx_idx_stat1; 1208 cvmx_ilk_rxx_mem_stat0_t ilk_rxx_mem_stat0; 1209 cvmx_ilk_rxx_mem_stat1_t ilk_rxx_mem_stat1; 1210 1211 cvmx_ilk_txx_idx_stat0_t ilk_txx_idx_stat0; 1212 cvmx_ilk_txx_idx_stat1_t ilk_txx_idx_stat1; 1213 cvmx_ilk_txx_mem_stat0_t ilk_txx_mem_stat0; 1214 cvmx_ilk_txx_mem_stat1_t ilk_txx_mem_stat1; 1215 1216 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1217 return; 1218 1219 if (interface >= CVMX_NUM_ILK_INTF) 1220 return; 1221 1222 if (pstats == NULL) 1223 return; 1224 1225 /* discrete channels */ 1226 if (pstats->chan_list != NULL) 1227 { 1228 for (i = 0; i < pstats->num_chans; i++) 1229 { 1230 1231 /* get the number of rx packets */ 1232 ilk_rxx_idx_stat0.u64 = 0; 1233 ilk_rxx_idx_stat0.s.index = *pstats->chan_list; 1234 ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd; 1235 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), 1236 ilk_rxx_idx_stat0.u64); 1237 ilk_rxx_mem_stat0.u64 = cvmx_read_csr 1238 (CVMX_ILK_RXX_MEM_STAT0(interface)); 1239 1240 /* get the number of rx bytes */ 1241 ilk_rxx_idx_stat1.u64 = 0; 1242 ilk_rxx_idx_stat1.s.index = *pstats->chan_list; 1243 ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd; 1244 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), 1245 ilk_rxx_idx_stat1.u64); 1246 ilk_rxx_mem_stat1.u64 = cvmx_read_csr 1247 (CVMX_ILK_RXX_MEM_STAT1(interface)); 1248 1249 cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, 1250 *pstats->chan_list, ilk_rxx_mem_stat0.s.rx_pkt, 1251 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1252 1253 /* get the number of tx packets */ 1254 ilk_txx_idx_stat0.u64 = 0; 1255 ilk_txx_idx_stat0.s.index = *pstats->chan_list; 1256 ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd; 1257 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), 1258 ilk_txx_idx_stat0.u64); 1259 ilk_txx_mem_stat0.u64 = cvmx_read_csr 1260 (CVMX_ILK_TXX_MEM_STAT0(interface)); 1261 1262 /* get the number of tx bytes */ 1263 ilk_txx_idx_stat1.u64 = 0; 1264 ilk_txx_idx_stat1.s.index = *pstats->chan_list; 1265 ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd; 1266 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), 1267 ilk_txx_idx_stat1.u64); 1268 ilk_txx_mem_stat1.u64 = cvmx_read_csr 1269 (CVMX_ILK_TXX_MEM_STAT1(interface)); 1270 1271 cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, 1272 *pstats->chan_list, ilk_txx_mem_stat0.s.tx_pkt, 1273 (unsigned int) ilk_txx_mem_stat1.s.tx_bytes); 1274 1275 pstats++; 1276 } 1277 return; 1278 } 1279 1280 /* continuous channels */ 1281 ilk_rxx_idx_stat0.u64 = 0; 1282 ilk_rxx_idx_stat0.s.index = pstats->chan_start; 1283 ilk_rxx_idx_stat0.s.inc = pstats->chan_step; 1284 ilk_rxx_idx_stat0.s.clr = pstats->clr_on_rd; 1285 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT0(interface), ilk_rxx_idx_stat0.u64); 1286 1287 ilk_rxx_idx_stat1.u64 = 0; 1288 ilk_rxx_idx_stat1.s.index = pstats->chan_start; 1289 ilk_rxx_idx_stat1.s.inc = pstats->chan_step; 1290 ilk_rxx_idx_stat1.s.clr = pstats->clr_on_rd; 1291 cvmx_write_csr (CVMX_ILK_RXX_IDX_STAT1(interface), ilk_rxx_idx_stat1.u64); 1292 1293 ilk_txx_idx_stat0.u64 = 0; 1294 ilk_txx_idx_stat0.s.index = pstats->chan_start; 1295 ilk_txx_idx_stat0.s.inc = pstats->chan_step; 1296 ilk_txx_idx_stat0.s.clr = pstats->clr_on_rd; 1297 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT0(interface), ilk_txx_idx_stat0.u64); 1298 1299 ilk_txx_idx_stat1.u64 = 0; 1300 ilk_txx_idx_stat1.s.index = pstats->chan_start; 1301 ilk_txx_idx_stat1.s.inc = pstats->chan_step; 1302 ilk_txx_idx_stat1.s.clr = pstats->clr_on_rd; 1303 cvmx_write_csr (CVMX_ILK_TXX_IDX_STAT1(interface), ilk_txx_idx_stat1.u64); 1304 1305 for (i = pstats->chan_start; i <= pstats->chan_end; i += pstats->chan_step) 1306 { 1307 ilk_rxx_mem_stat0.u64 = cvmx_read_csr 1308 (CVMX_ILK_RXX_MEM_STAT0(interface)); 1309 ilk_rxx_mem_stat1.u64 = cvmx_read_csr 1310 (CVMX_ILK_RXX_MEM_STAT1(interface)); 1311 cvmx_dprintf ("ILK%d Channel%d Rx: %d packets %d bytes\n", interface, i, 1312 ilk_rxx_mem_stat0.s.rx_pkt, 1313 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1314 1315 ilk_txx_mem_stat0.u64 = cvmx_read_csr 1316 (CVMX_ILK_TXX_MEM_STAT0(interface)); 1317 ilk_txx_mem_stat1.u64 = cvmx_read_csr 1318 (CVMX_ILK_TXX_MEM_STAT1(interface)); 1319 cvmx_dprintf ("ILK%d Channel%d Tx: %d packets %d bytes\n", interface, i, 1320 ilk_rxx_mem_stat0.s.rx_pkt, 1321 (unsigned int) ilk_rxx_mem_stat1.s.rx_bytes); 1322 } 1323 1324 return; 1325} 1326 1327/** 1328 * enable or disable loopbacks 1329 * 1330 * @param interface The identifier of the packet interface to disable. cn68xx 1331 * has 2 interfaces: ilk0 and ilk1. 1332 * @param enable Enable or disable loopback 1333 * @param mode Internal or external loopback 1334 * 1335 * @return Zero on success, negative of failure. 1336 */ 1337int cvmx_ilk_lpbk (int interface, cvmx_ilk_lpbk_ena_t enable, 1338 cvmx_ilk_lpbk_mode_t mode) 1339{ 1340 int res = -1; 1341 cvmx_ilk_txx_cfg0_t ilk_txx_cfg0; 1342 cvmx_ilk_rxx_cfg0_t ilk_rxx_cfg0; 1343 1344 if (!(OCTEON_IS_MODEL(OCTEON_CN68XX))) 1345 return res; 1346 1347 if (interface >= CVMX_NUM_ILK_INTF) 1348 return res; 1349 1350 /* internal loopback. only 1 type of loopback can be on at 1 time */ 1351 if (mode == CVMX_ILK_LPBK_INT) 1352 { 1353 if (enable == CVMX_ILK_LPBK_ENA) 1354 { 1355 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1356 ilk_txx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA; 1357 ilk_txx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA; 1358 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1359 1360 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1361 ilk_rxx_cfg0.s.ext_lpbk = CVMX_ILK_LPBK_DISA; 1362 ilk_rxx_cfg0.s.ext_lpbk_fc = CVMX_ILK_LPBK_DISA; 1363 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1364 } 1365 1366 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1367 ilk_txx_cfg0.s.int_lpbk = enable; 1368 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1369 1370 res = 0; 1371 return res; 1372 } 1373 1374 /* external loopback. only 1 type of loopback can be on at 1 time */ 1375 if (enable == CVMX_ILK_LPBK_ENA) 1376 { 1377 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1378 ilk_txx_cfg0.s.int_lpbk = CVMX_ILK_LPBK_DISA; 1379 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1380 } 1381 1382 ilk_txx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_TXX_CFG0(interface)); 1383 ilk_txx_cfg0.s.ext_lpbk = enable; 1384 ilk_txx_cfg0.s.ext_lpbk_fc = enable; 1385 cvmx_write_csr (CVMX_ILK_TXX_CFG0(interface), ilk_txx_cfg0.u64); 1386 1387 ilk_rxx_cfg0.u64 = cvmx_read_csr (CVMX_ILK_RXX_CFG0(interface)); 1388 ilk_rxx_cfg0.s.ext_lpbk = enable; 1389 ilk_rxx_cfg0.s.ext_lpbk_fc = enable; 1390 cvmx_write_csr (CVMX_ILK_RXX_CFG0(interface), ilk_rxx_cfg0.u64); 1391 1392 res = 0; 1393 return res; 1394} 1395 1396#endif /* CVMX_ENABLE_HELPER_FUNCTIONS */ 1397