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