cvmx-helper.c revision 215014
1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (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 Networks 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 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * Helper functions for common, but complicated tasks. 48 * 49 * <hr>$Revision: 42150 $<hr> 50 */ 51#include "cvmx.h" 52#include "cvmx-bootmem.h" 53#include "cvmx-fpa.h" 54#include "cvmx-pip.h" 55#include "cvmx-pko.h" 56#include "cvmx-ipd.h" 57#include "cvmx-asx.h" 58#include "cvmx-gmx.h" 59#include "cvmx-spi.h" 60#include "cvmx-sysinfo.h" 61#include "cvmx-helper.h" 62#include "cvmx-version.h" 63#include "cvmx-helper-check-defines.h" 64#include "cvmx-helper-board.h" 65#include "cvmx-helper-errata.h" 66 67#ifdef CVMX_ENABLE_PKO_FUNCTIONS 68 69/** 70 * cvmx_override_pko_queue_priority(int ipd_port, uint64_t 71 * priorities[16]) is a function pointer. It is meant to allow 72 * customization of the PKO queue priorities based on the port 73 * number. Users should set this pointer to a function before 74 * calling any cvmx-helper operations. 75 */ 76CVMX_SHARED void (*cvmx_override_pko_queue_priority)(int pko_port, uint64_t priorities[16]) = NULL; 77 78/** 79 * cvmx_override_ipd_port_setup(int ipd_port) is a function 80 * pointer. It is meant to allow customization of the IPD port 81 * setup before packet input/output comes online. It is called 82 * after cvmx-helper does the default IPD configuration, but 83 * before IPD is enabled. Users should set this pointer to a 84 * function before calling any cvmx-helper operations. 85 */ 86CVMX_SHARED void (*cvmx_override_ipd_port_setup)(int ipd_port) = NULL; 87 88/* Port count per interface */ 89static CVMX_SHARED int interface_port_count[4] = {0,0,0,0}; 90/* Port last configured link info index by IPD/PKO port */ 91static CVMX_SHARED cvmx_helper_link_info_t port_link_info[CVMX_PIP_NUM_INPUT_PORTS]; 92 93 94/** 95 * Return the number of interfaces the chip has. Each interface 96 * may have multiple ports. Most chips support two interfaces, 97 * but the CNX0XX and CNX1XX are exceptions. These only support 98 * one interface. 99 * 100 * @return Number of interfaces on chip 101 */ 102int cvmx_helper_get_number_of_interfaces(void) 103{ 104 switch (cvmx_sysinfo_get()->board_type) { 105#if defined(OCTEON_VENDOR_LANNER) 106 case CVMX_BOARD_TYPE_CUST_LANNER_MR955: 107 return 2; 108 case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 109 return 1; 110#endif 111 default: 112 break; 113 } 114 115 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 116 return 4; 117 else 118 return 3; 119} 120 121 122/** 123 * Return the number of ports on an interface. Depending on the 124 * chip and configuration, this can be 1-16. A value of 0 125 * specifies that the interface doesn't exist or isn't usable. 126 * 127 * @param interface Interface to get the port count for 128 * 129 * @return Number of ports on interface. Can be Zero. 130 */ 131int cvmx_helper_ports_on_interface(int interface) 132{ 133 return interface_port_count[interface]; 134} 135 136 137/** 138 * Get the operating mode of an interface. Depending on the Octeon 139 * chip and configuration, this function returns an enumeration 140 * of the type of packet I/O supported by an interface. 141 * 142 * @param interface Interface to probe 143 * 144 * @return Mode of the interface. Unknown or unsupported interfaces return 145 * DISABLED. 146 */ 147cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) 148{ 149 cvmx_gmxx_inf_mode_t mode; 150 if (interface == 2) 151 return CVMX_HELPER_INTERFACE_MODE_NPI; 152 153 if (interface == 3) 154 { 155 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 156 return CVMX_HELPER_INTERFACE_MODE_LOOP; 157 else 158 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 159 } 160 161 if (interface == 0 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 && cvmx_sysinfo_get()->board_rev_major == 1) 162 { 163 /* Lie about interface type of CN3005 board. This board has a switch on port 1 like 164 ** the other evaluation boards, but it is connected over RGMII instead of GMII. Report 165 ** GMII mode so that the speed is forced to 1 Gbit full duplex. Other than some initial configuration 166 ** (which does not use the output of this function) there is no difference in setup between GMII and RGMII modes. 167 */ 168 return CVMX_HELPER_INTERFACE_MODE_GMII; 169 } 170 171 /* Interface 1 is always disabled on CN31XX and CN30XX */ 172 if ((interface == 1) && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))) 173 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 174 175 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 176 177 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 178 { 179 switch(mode.cn56xx.mode) 180 { 181 case 0: return CVMX_HELPER_INTERFACE_MODE_DISABLED; 182 case 1: return CVMX_HELPER_INTERFACE_MODE_XAUI; 183 case 2: return CVMX_HELPER_INTERFACE_MODE_SGMII; 184 case 3: return CVMX_HELPER_INTERFACE_MODE_PICMG; 185 default:return CVMX_HELPER_INTERFACE_MODE_DISABLED; 186 } 187 } 188 else 189 { 190 if (!mode.s.en) 191 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 192 193 if (mode.s.type) 194 { 195 if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) 196 return CVMX_HELPER_INTERFACE_MODE_SPI; 197 else 198 return CVMX_HELPER_INTERFACE_MODE_GMII; 199 } 200 else 201 return CVMX_HELPER_INTERFACE_MODE_RGMII; 202 } 203} 204 205 206/** 207 * @INTERNAL 208 * Configure the IPD/PIP tagging and QoS options for a specific 209 * port. This function determines the POW work queue entry 210 * contents for a port. The setup performed here is controlled by 211 * the defines in executive-config.h. 212 * 213 * @param ipd_port Port to configure. This follows the IPD numbering, not the 214 * per interface numbering 215 * 216 * @return Zero on success, negative on failure 217 */ 218static int __cvmx_helper_port_setup_ipd(int ipd_port) 219{ 220 cvmx_pip_port_cfg_t port_config; 221 cvmx_pip_port_tag_cfg_t tag_config; 222 223 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 224 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); 225 226 /* Have each port go to a different POW queue */ 227 port_config.s.qos = ipd_port & 0x7; 228 229 /* Process the headers and place the IP header in the work queue */ 230 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; 231 232 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; 233 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; 234 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; 235 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; 236 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; 237 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; 238 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; 239 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; 240 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; 241 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; 242 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; 243 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 244 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 245 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 246 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 247 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 248 /* Put all packets in group 0. Other groups can be used by the app */ 249 tag_config.s.grp = 0; 250 251 cvmx_pip_config_port(ipd_port, port_config, tag_config); 252 253 /* Give the user a chance to override our setting for each port */ 254 if (cvmx_override_ipd_port_setup) 255 cvmx_override_ipd_port_setup(ipd_port); 256 257 return 0; 258} 259 260 261/** 262 * This function probes an interface to determine the actual 263 * number of hardware ports connected to it. It doesn't setup the 264 * ports or enable them. The main goal here is to set the global 265 * interface_port_count[interface] correctly. Hardware setup of the 266 * ports will be performed later. 267 * 268 * @param interface Interface to probe 269 * 270 * @return Zero on success, negative on failure 271 */ 272int cvmx_helper_interface_probe(int interface) 273{ 274 /* At this stage in the game we don't want packets to be moving yet. 275 The following probe calls should perform hardware setup 276 needed to determine port counts. Receive must still be disabled */ 277 switch (cvmx_helper_interface_get_mode(interface)) 278 { 279 /* These types don't support ports to IPD/PKO */ 280 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 281 case CVMX_HELPER_INTERFACE_MODE_PCIE: 282 interface_port_count[interface] = 0; 283 break; 284 /* XAUI is a single high speed port */ 285 case CVMX_HELPER_INTERFACE_MODE_XAUI: 286 interface_port_count[interface] = __cvmx_helper_xaui_probe(interface); 287 break; 288 /* RGMII/GMII/MII are all treated about the same. Most functions 289 refer to these ports as RGMII */ 290 case CVMX_HELPER_INTERFACE_MODE_RGMII: 291 case CVMX_HELPER_INTERFACE_MODE_GMII: 292 interface_port_count[interface] = __cvmx_helper_rgmii_probe(interface); 293 break; 294 /* SPI4 can have 1-16 ports depending on the device at the other end */ 295 case CVMX_HELPER_INTERFACE_MODE_SPI: 296 interface_port_count[interface] = __cvmx_helper_spi_probe(interface); 297 break; 298 /* SGMII can have 1-4 ports depending on how many are hooked up */ 299 case CVMX_HELPER_INTERFACE_MODE_SGMII: 300 case CVMX_HELPER_INTERFACE_MODE_PICMG: 301 interface_port_count[interface] = __cvmx_helper_sgmii_probe(interface); 302 break; 303 /* PCI target Network Packet Interface */ 304 case CVMX_HELPER_INTERFACE_MODE_NPI: 305 interface_port_count[interface] = __cvmx_helper_npi_probe(interface); 306 break; 307 /* Special loopback only ports. These are not the same as other ports 308 in loopback mode */ 309 case CVMX_HELPER_INTERFACE_MODE_LOOP: 310 interface_port_count[interface] = __cvmx_helper_loop_probe(interface); 311 break; 312 } 313 314 interface_port_count[interface] = __cvmx_helper_board_interface_probe(interface, interface_port_count[interface]); 315 316 /* Make sure all global variables propagate to other cores */ 317 CVMX_SYNCWS; 318 319 return 0; 320} 321 322 323/** 324 * @INTERNAL 325 * Setup the IPD/PIP for the ports on an interface. Packet 326 * classification and tagging are set for every port on the 327 * interface. The number of ports on the interface must already 328 * have been probed. 329 * 330 * @param interface Interface to setup IPD/PIP for 331 * 332 * @return Zero on success, negative on failure 333 */ 334static int __cvmx_helper_interface_setup_ipd(int interface) 335{ 336 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 337 int num_ports = interface_port_count[interface]; 338 339 while (num_ports--) 340 { 341 __cvmx_helper_port_setup_ipd(ipd_port); 342 ipd_port++; 343 } 344 return 0; 345} 346 347 348/** 349 * @INTERNAL 350 * Setup global setting for IPD/PIP not related to a specific 351 * interface or port. This must be called before IPD is enabled. 352 * 353 * @return Zero on success, negative on failure. 354 */ 355static int __cvmx_helper_global_setup_ipd(void) 356{ 357 /* Setup the global packet input options */ 358 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE/8, 359 CVMX_HELPER_FIRST_MBUFF_SKIP/8, 360 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP/8, 361 (CVMX_HELPER_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 362 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP+8) / 128, /* The +8 is to account for the next ptr */ 363 CVMX_FPA_WQE_POOL, 364 CVMX_IPD_OPC_MODE_STT, 365 CVMX_HELPER_ENABLE_BACK_PRESSURE); 366 return 0; 367} 368 369 370/** 371 * @INTERNAL 372 * Setup the PKO for the ports on an interface. The number of 373 * queues per port and the priority of each PKO output queue 374 * is set here. PKO must be disabled when this function is called. 375 * 376 * @param interface Interface to setup PKO for 377 * 378 * @return Zero on success, negative on failure 379 */ 380static int __cvmx_helper_interface_setup_pko(int interface) 381{ 382 /* Each packet output queue has an associated priority. The higher the 383 priority, the more often it can send a packet. A priority of 8 means 384 it can send in all 8 rounds of contention. We're going to make each 385 queue one less than the last. 386 The vector of priorities has been extended to support CN5xxx CPUs, 387 where up to 16 queues can be associated to a port. 388 To keep backward compatibility we don't change the initial 8 389 priorities and replicate them in the second half. 390 With per-core PKO queues (PKO lockless operation) all queues have 391 the same priority. */ 392 uint64_t priorities[16] = {8,7,6,5,4,3,2,1,8,7,6,5,4,3,2,1}; 393 394 /* Setup the IPD/PIP and PKO for the ports discovered above. Here packet 395 classification, tagging and output priorities are set */ 396 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 397 int num_ports = interface_port_count[interface]; 398 while (num_ports--) 399 { 400 /* Give the user a chance to override the per queue priorities */ 401 if (cvmx_override_pko_queue_priority) 402 cvmx_override_pko_queue_priority(ipd_port, priorities); 403 404 cvmx_pko_config_port(ipd_port, cvmx_pko_get_base_queue_per_core(ipd_port, 0), 405 cvmx_pko_get_num_queues(ipd_port), priorities); 406 ipd_port++; 407 } 408 return 0; 409} 410 411 412/** 413 * @INTERNAL 414 * Setup global setting for PKO not related to a specific 415 * interface or port. This must be called before PKO is enabled. 416 * 417 * @return Zero on success, negative on failure. 418 */ 419static int __cvmx_helper_global_setup_pko(void) 420{ 421 /* Disable tagwait FAU timeout. This needs to be done before anyone might 422 start packet output using tags */ 423 cvmx_iob_fau_timeout_t fau_to; 424 fau_to.u64 = 0; 425 fau_to.s.tout_val = 0xfff; 426 fau_to.s.tout_enb = 0; 427 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 428 return 0; 429} 430 431 432/** 433 * @INTERNAL 434 * Setup global backpressure setting. 435 * 436 * @return Zero on success, negative on failure 437 */ 438static int __cvmx_helper_global_setup_backpressure(void) 439{ 440#if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 441 /* Disable backpressure if configured to do so */ 442 /* Disable backpressure (pause frame) generation */ 443 int num_interfaces = cvmx_helper_get_number_of_interfaces(); 444 int interface; 445 for (interface=0; interface<num_interfaces; interface++) 446 { 447 switch (cvmx_helper_interface_get_mode(interface)) 448 { 449 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 450 case CVMX_HELPER_INTERFACE_MODE_PCIE: 451 case CVMX_HELPER_INTERFACE_MODE_NPI: 452 case CVMX_HELPER_INTERFACE_MODE_LOOP: 453 case CVMX_HELPER_INTERFACE_MODE_XAUI: 454 break; 455 case CVMX_HELPER_INTERFACE_MODE_RGMII: 456 case CVMX_HELPER_INTERFACE_MODE_GMII: 457 case CVMX_HELPER_INTERFACE_MODE_SPI: 458 case CVMX_HELPER_INTERFACE_MODE_SGMII: 459 case CVMX_HELPER_INTERFACE_MODE_PICMG: 460 cvmx_gmx_set_backpressure_override(interface, 0xf); 461 break; 462 } 463 } 464 //cvmx_dprintf("Disabling backpressure\n"); 465#endif 466 467 return 0; 468} 469 470 471/** 472 * @INTERNAL 473 * Enable packet input/output from the hardware. This function is 474 * called after all internal setup is complete and IPD is enabled. 475 * After this function completes, packets will be accepted from the 476 * hardware ports. PKO should still be disabled to make sure packets 477 * aren't sent out partially setup hardware. 478 * 479 * @param interface Interface to enable 480 * 481 * @return Zero on success, negative on failure 482 */ 483static int __cvmx_helper_packet_hardware_enable(int interface) 484{ 485 int result = 0; 486 switch (cvmx_helper_interface_get_mode(interface)) 487 { 488 /* These types don't support ports to IPD/PKO */ 489 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 490 case CVMX_HELPER_INTERFACE_MODE_PCIE: 491 /* Nothing to do */ 492 break; 493 /* XAUI is a single high speed port */ 494 case CVMX_HELPER_INTERFACE_MODE_XAUI: 495 result = __cvmx_helper_xaui_enable(interface); 496 break; 497 /* RGMII/GMII/MII are all treated about the same. Most functions 498 refer to these ports as RGMII */ 499 case CVMX_HELPER_INTERFACE_MODE_RGMII: 500 case CVMX_HELPER_INTERFACE_MODE_GMII: 501 result = __cvmx_helper_rgmii_enable(interface); 502 break; 503 /* SPI4 can have 1-16 ports depending on the device at the other end */ 504 case CVMX_HELPER_INTERFACE_MODE_SPI: 505 result = __cvmx_helper_spi_enable(interface); 506 break; 507 /* SGMII can have 1-4 ports depending on how many are hooked up */ 508 case CVMX_HELPER_INTERFACE_MODE_SGMII: 509 case CVMX_HELPER_INTERFACE_MODE_PICMG: 510 result = __cvmx_helper_sgmii_enable(interface); 511 break; 512 /* PCI target Network Packet Interface */ 513 case CVMX_HELPER_INTERFACE_MODE_NPI: 514 result = __cvmx_helper_npi_enable(interface); 515 break; 516 /* Special loopback only ports. These are not the same as other ports 517 in loopback mode */ 518 case CVMX_HELPER_INTERFACE_MODE_LOOP: 519 result = __cvmx_helper_loop_enable(interface); 520 break; 521 } 522 result |= __cvmx_helper_board_hardware_enable(interface); 523 return result; 524} 525 526 527/** 528 * Called after all internal packet IO paths are setup. This 529 * function enables IPD/PIP and begins packet input and output. 530 * 531 * @return Zero on success, negative on failure 532 */ 533int cvmx_helper_ipd_and_packet_input_enable(void) 534{ 535 int num_interfaces; 536 int interface; 537 538 /* Enable IPD */ 539 cvmx_ipd_enable(); 540 541 /* Time to enable hardware ports packet input and output. Note that at this 542 point IPD/PIP must be fully functional and PKO must be disabled */ 543 num_interfaces = cvmx_helper_get_number_of_interfaces(); 544 for (interface=0; interface<num_interfaces; interface++) 545 { 546 if (cvmx_helper_ports_on_interface(interface) > 0) 547 { 548 //cvmx_dprintf("Enabling packet I/O on interface %d\n", interface); 549 __cvmx_helper_packet_hardware_enable(interface); 550 } 551 } 552 553 /* Finally enable PKO now that the entire path is up and running */ 554 cvmx_pko_enable(); 555 556 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) && 557 (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) 558 __cvmx_helper_errata_fix_ipd_ptr_alignment(); 559 return 0; 560} 561 562 563/** 564 * Initialize the PIP, IPD, and PKO hardware to support 565 * simple priority based queues for the ethernet ports. Each 566 * port is configured with a number of priority queues based 567 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower 568 * priority than the previous. 569 * 570 * @return Zero on success, non-zero on failure 571 */ 572int cvmx_helper_initialize_packet_io_global(void) 573{ 574 int result = 0; 575 int interface; 576 cvmx_l2c_cfg_t l2c_cfg; 577 cvmx_smix_en_t smix_en; 578 const int num_interfaces = cvmx_helper_get_number_of_interfaces(); 579 580 /* CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to be disabled */ 581 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 582 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); 583 584 /* Tell L2 to give the IOB statically higher priority compared to the 585 cores. This avoids conditions where IO blocks might be starved under 586 very high L2 loads */ 587 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 588 l2c_cfg.s.lrf_arb_mode = 0; 589 l2c_cfg.s.rfb_arb_mode = 0; 590 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); 591 592 /* Make sure SMI/MDIO is enabled so we can query PHYs */ 593 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0)); 594 if (!smix_en.s.en) 595 { 596 smix_en.s.en = 1; 597 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64); 598 } 599 600 /* Newer chips actually have two SMI/MDIO interfaces */ 601 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && 602 !OCTEON_IS_MODEL(OCTEON_CN58XX) && 603 !OCTEON_IS_MODEL(OCTEON_CN50XX)) 604 { 605 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1)); 606 if (!smix_en.s.en) 607 { 608 smix_en.s.en = 1; 609 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64); 610 } 611 } 612 613 cvmx_pko_initialize_global(); 614 for (interface=0; interface<num_interfaces; interface++) 615 { 616 result |= cvmx_helper_interface_probe(interface); 617 if (cvmx_helper_ports_on_interface(interface) > 0) 618 cvmx_dprintf("Interface %d has %d ports (%s)\n", 619 interface, cvmx_helper_ports_on_interface(interface), 620 cvmx_helper_interface_mode_to_string(cvmx_helper_interface_get_mode(interface))); 621 result |= __cvmx_helper_interface_setup_ipd(interface); 622 result |= __cvmx_helper_interface_setup_pko(interface); 623 } 624 625 result |= __cvmx_helper_global_setup_ipd(); 626 result |= __cvmx_helper_global_setup_pko(); 627 628 /* Enable any flow control and backpressure */ 629 result |= __cvmx_helper_global_setup_backpressure(); 630 631#if CVMX_HELPER_ENABLE_IPD 632 result |= cvmx_helper_ipd_and_packet_input_enable(); 633#endif 634 return result; 635} 636 637 638/** 639 * Does core local initialization for packet io 640 * 641 * @return Zero on success, non-zero on failure 642 */ 643int cvmx_helper_initialize_packet_io_local(void) 644{ 645 return cvmx_pko_initialize_local(); 646} 647 648 649/** 650 * Auto configure an IPD/PKO port link state and speed. This 651 * function basically does the equivalent of: 652 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); 653 * 654 * @param ipd_port IPD/PKO port to auto configure 655 * 656 * @return Link state after configure 657 */ 658cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) 659{ 660 cvmx_helper_link_info_t link_info; 661 int interface = cvmx_helper_get_interface_num(ipd_port); 662 int index = cvmx_helper_get_interface_index_num(ipd_port); 663 664 if (index >= cvmx_helper_ports_on_interface(interface)) 665 { 666 link_info.u64 = 0; 667 return link_info; 668 } 669 670 link_info = cvmx_helper_link_get(ipd_port); 671 if (link_info.u64 == port_link_info[ipd_port].u64) 672 return link_info; 673 674 /* If we fail to set the link speed, port_link_info will not change */ 675 cvmx_helper_link_set(ipd_port, link_info); 676 677 /* port_link_info should be the current value, which will be different 678 than expect if cvmx_helper_link_set() failed */ 679 return port_link_info[ipd_port]; 680} 681 682 683/** 684 * Return the link state of an IPD/PKO port as returned by 685 * auto negotiation. The result of this function may not match 686 * Octeon's link config if auto negotiation has changed since 687 * the last call to cvmx_helper_link_set(). 688 * 689 * @param ipd_port IPD/PKO port to query 690 * 691 * @return Link state 692 */ 693cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) 694{ 695 cvmx_helper_link_info_t result; 696 int interface = cvmx_helper_get_interface_num(ipd_port); 697 int index = cvmx_helper_get_interface_index_num(ipd_port); 698 699 /* The default result will be a down link unless the code below 700 changes it */ 701 result.u64 = 0; 702 703 if (index >= cvmx_helper_ports_on_interface(interface)) 704 return result; 705 706 switch (cvmx_helper_interface_get_mode(interface)) 707 { 708 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 709 case CVMX_HELPER_INTERFACE_MODE_PCIE: 710 /* Network links are not supported */ 711 break; 712 case CVMX_HELPER_INTERFACE_MODE_XAUI: 713 result = __cvmx_helper_xaui_link_get(ipd_port); 714 break; 715 case CVMX_HELPER_INTERFACE_MODE_GMII: 716 if (index == 0) 717 result = __cvmx_helper_rgmii_link_get(ipd_port); 718 else 719 { 720 result.s.full_duplex = 1; 721 result.s.link_up = 1; 722 result.s.speed = 1000; 723 } 724 break; 725 case CVMX_HELPER_INTERFACE_MODE_RGMII: 726 result = __cvmx_helper_rgmii_link_get(ipd_port); 727 break; 728 case CVMX_HELPER_INTERFACE_MODE_SPI: 729 result = __cvmx_helper_spi_link_get(ipd_port); 730 break; 731 case CVMX_HELPER_INTERFACE_MODE_SGMII: 732 case CVMX_HELPER_INTERFACE_MODE_PICMG: 733 result = __cvmx_helper_sgmii_link_get(ipd_port); 734 break; 735 case CVMX_HELPER_INTERFACE_MODE_NPI: 736 case CVMX_HELPER_INTERFACE_MODE_LOOP: 737 /* Network links are not supported */ 738 break; 739 } 740 return result; 741} 742 743 744/** 745 * Configure an IPD/PKO port for the specified link state. This 746 * function does not influence auto negotiation at the PHY level. 747 * The passed link state must always match the link state returned 748 * by cvmx_helper_link_get(). It is normally best to use 749 * cvmx_helper_link_autoconf() instead. 750 * 751 * @param ipd_port IPD/PKO port to configure 752 * @param link_info The new link state 753 * 754 * @return Zero on success, negative on failure 755 */ 756int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 757{ 758 int result = -1; 759 int interface = cvmx_helper_get_interface_num(ipd_port); 760 int index = cvmx_helper_get_interface_index_num(ipd_port); 761 762 if (index >= cvmx_helper_ports_on_interface(interface)) 763 return -1; 764 765 switch (cvmx_helper_interface_get_mode(interface)) 766 { 767 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 768 case CVMX_HELPER_INTERFACE_MODE_PCIE: 769 break; 770 case CVMX_HELPER_INTERFACE_MODE_XAUI: 771 result = __cvmx_helper_xaui_link_set(ipd_port, link_info); 772 break; 773 /* RGMII/GMII/MII are all treated about the same. Most functions 774 refer to these ports as RGMII */ 775 case CVMX_HELPER_INTERFACE_MODE_RGMII: 776 case CVMX_HELPER_INTERFACE_MODE_GMII: 777 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); 778 break; 779 case CVMX_HELPER_INTERFACE_MODE_SPI: 780 result = __cvmx_helper_spi_link_set(ipd_port, link_info); 781 break; 782 case CVMX_HELPER_INTERFACE_MODE_SGMII: 783 case CVMX_HELPER_INTERFACE_MODE_PICMG: 784 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); 785 break; 786 case CVMX_HELPER_INTERFACE_MODE_NPI: 787 case CVMX_HELPER_INTERFACE_MODE_LOOP: 788 break; 789 } 790 /* Set the port_link_info here so that the link status is updated 791 no matter how cvmx_helper_link_set is called. We don't change 792 the value if link_set failed */ 793 if (result == 0) 794 port_link_info[ipd_port].u64 = link_info.u64; 795 return result; 796} 797 798 799/** 800 * Configure a port for internal and/or external loopback. Internal loopback 801 * causes packets sent by the port to be received by Octeon. External loopback 802 * causes packets received from the wire to sent out again. 803 * 804 * @param ipd_port IPD/PKO port to loopback. 805 * @param enable_internal 806 * Non zero if you want internal loopback 807 * @param enable_external 808 * Non zero if you want external loopback 809 * 810 * @return Zero on success, negative on failure. 811 */ 812int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, int enable_external) 813{ 814 int result = -1; 815 int interface = cvmx_helper_get_interface_num(ipd_port); 816 int index = cvmx_helper_get_interface_index_num(ipd_port); 817 818 if (index >= cvmx_helper_ports_on_interface(interface)) 819 return -1; 820 821 switch (cvmx_helper_interface_get_mode(interface)) 822 { 823 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 824 case CVMX_HELPER_INTERFACE_MODE_PCIE: 825 case CVMX_HELPER_INTERFACE_MODE_SPI: 826 case CVMX_HELPER_INTERFACE_MODE_NPI: 827 case CVMX_HELPER_INTERFACE_MODE_LOOP: 828 break; 829 case CVMX_HELPER_INTERFACE_MODE_XAUI: 830 result = __cvmx_helper_xaui_configure_loopback(ipd_port, enable_internal, enable_external); 831 break; 832 case CVMX_HELPER_INTERFACE_MODE_RGMII: 833 case CVMX_HELPER_INTERFACE_MODE_GMII: 834 result = __cvmx_helper_rgmii_configure_loopback(ipd_port, enable_internal, enable_external); 835 break; 836 case CVMX_HELPER_INTERFACE_MODE_SGMII: 837 case CVMX_HELPER_INTERFACE_MODE_PICMG: 838 result = __cvmx_helper_sgmii_configure_loopback(ipd_port, enable_internal, enable_external); 839 break; 840 } 841 return result; 842} 843 844#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 845