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