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