1 /***********************license start*************** 2 * Author: Cavium Networks 3 * 4 * Contact: support@caviumnetworks.com 5 * This file is part of the OCTEON SDK 6 * 7 * Copyright (c) 2003-2008 Cavium Networks 8 * 9 * This file is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License, Version 2, as 11 * published by the Free Software Foundation. 12 * 13 * This file is distributed in the hope that it will be useful, but 14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 * NONINFRINGEMENT. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this file; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * or visit http://www.gnu.org/licenses/. 23 * 24 * This file may also be available under a different license from Cavium. 25 * Contact Cavium Networks for more information 26 ***********************license end**************************************/ 27 28 /* 29 * 30 * Helper functions for common, but complicated tasks. 31 * 32 */ 33 #include <asm/octeon/octeon.h> 34 35 #include <asm/octeon/cvmx-config.h> 36 37 #include <asm/octeon/cvmx-fpa.h> 38 #include <asm/octeon/cvmx-pip.h> 39 #include <asm/octeon/cvmx-pko.h> 40 #include <asm/octeon/cvmx-ipd.h> 41 #include <asm/octeon/cvmx-spi.h> 42 #include <asm/octeon/cvmx-helper.h> 43 #include <asm/octeon/cvmx-helper-board.h> 44 45 #include <asm/octeon/cvmx-pip-defs.h> 46 #include <asm/octeon/cvmx-smix-defs.h> 47 #include <asm/octeon/cvmx-asxx-defs.h> 48 49 /** 50 * cvmx_override_pko_queue_priority(int ipd_port, uint64_t 51 * priorities[16]) is a function pointer. It is meant to allow 52 * customization of the PKO queue priorities based on the port 53 * number. Users should set this pointer to a function before 54 * calling any cvmx-helper operations. 55 */ 56 void (*cvmx_override_pko_queue_priority) (int pko_port, 57 uint64_t priorities[16]); 58 59 /** 60 * cvmx_override_ipd_port_setup(int ipd_port) is a function 61 * pointer. It is meant to allow customization of the IPD port 62 * setup before packet input/output comes online. It is called 63 * after cvmx-helper does the default IPD configuration, but 64 * before IPD is enabled. Users should set this pointer to a 65 * function before calling any cvmx-helper operations. 66 */ 67 void (*cvmx_override_ipd_port_setup) (int ipd_port); 68 69 /* Port count per interface */ 70 static int interface_port_count[4] = { 0, 0, 0, 0 }; 71 72 /* Port last configured link info index by IPD/PKO port */ 73 static cvmx_helper_link_info_t 74 port_link_info[CVMX_PIP_NUM_INPUT_PORTS]; 75 76 /** 77 * Return the number of interfaces the chip has. Each interface 78 * may have multiple ports. Most chips support two interfaces, 79 * but the CNX0XX and CNX1XX are exceptions. These only support 80 * one interface. 81 * 82 * Returns Number of interfaces on chip 83 */ 84 int cvmx_helper_get_number_of_interfaces(void) 85 { 86 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) 87 return 4; 88 else 89 return 3; 90 } 91 92 /** 93 * Return the number of ports on an interface. Depending on the 94 * chip and configuration, this can be 1-16. A value of 0 95 * specifies that the interface doesn't exist or isn't usable. 96 * 97 * @interface: Interface to get the port count for 98 * 99 * Returns Number of ports on interface. Can be Zero. 100 */ 101 int cvmx_helper_ports_on_interface(int interface) 102 { 103 return interface_port_count[interface]; 104 } 105 106 /** 107 * Get the operating mode of an interface. Depending on the Octeon 108 * chip and configuration, this function returns an enumeration 109 * of the type of packet I/O supported by an interface. 110 * 111 * @interface: Interface to probe 112 * 113 * Returns Mode of the interface. Unknown or unsupported interfaces return 114 * DISABLED. 115 */ 116 cvmx_helper_interface_mode_t cvmx_helper_interface_get_mode(int interface) 117 { 118 union cvmx_gmxx_inf_mode mode; 119 if (interface == 2) 120 return CVMX_HELPER_INTERFACE_MODE_NPI; 121 122 if (interface == 3) { 123 if (OCTEON_IS_MODEL(OCTEON_CN56XX) 124 || OCTEON_IS_MODEL(OCTEON_CN52XX)) 125 return CVMX_HELPER_INTERFACE_MODE_LOOP; 126 else 127 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 128 } 129 130 if (interface == 0 131 && cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CN3005_EVB_HS5 132 && cvmx_sysinfo_get()->board_rev_major == 1) { 133 /* 134 * Lie about interface type of CN3005 board. This 135 * board has a switch on port 1 like the other 136 * evaluation boards, but it is connected over RGMII 137 * instead of GMII. Report GMII mode so that the 138 * speed is forced to 1 Gbit full duplex. Other than 139 * some initial configuration (which does not use the 140 * output of this function) there is no difference in 141 * setup between GMII and RGMII modes. 142 */ 143 return CVMX_HELPER_INTERFACE_MODE_GMII; 144 } 145 146 /* Interface 1 is always disabled on CN31XX and CN30XX */ 147 if ((interface == 1) 148 && (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) 149 || OCTEON_IS_MODEL(OCTEON_CN50XX) 150 || OCTEON_IS_MODEL(OCTEON_CN52XX))) 151 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 152 153 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 154 155 if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX)) { 156 switch (mode.cn56xx.mode) { 157 case 0: 158 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 159 case 1: 160 return CVMX_HELPER_INTERFACE_MODE_XAUI; 161 case 2: 162 return CVMX_HELPER_INTERFACE_MODE_SGMII; 163 case 3: 164 return CVMX_HELPER_INTERFACE_MODE_PICMG; 165 default: 166 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 167 } 168 } else { 169 if (!mode.s.en) 170 return CVMX_HELPER_INTERFACE_MODE_DISABLED; 171 172 if (mode.s.type) { 173 if (OCTEON_IS_MODEL(OCTEON_CN38XX) 174 || OCTEON_IS_MODEL(OCTEON_CN58XX)) 175 return CVMX_HELPER_INTERFACE_MODE_SPI; 176 else 177 return CVMX_HELPER_INTERFACE_MODE_GMII; 178 } else 179 return CVMX_HELPER_INTERFACE_MODE_RGMII; 180 } 181 } 182 183 /** 184 * Configure the IPD/PIP tagging and QoS options for a specific 185 * port. This function determines the POW work queue entry 186 * contents for a port. The setup performed here is controlled by 187 * the defines in executive-config.h. 188 * 189 * @ipd_port: Port to configure. This follows the IPD numbering, not the 190 * per interface numbering 191 * 192 * Returns Zero on success, negative on failure 193 */ 194 static int __cvmx_helper_port_setup_ipd(int ipd_port) 195 { 196 union cvmx_pip_prt_cfgx port_config; 197 union cvmx_pip_prt_tagx tag_config; 198 199 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 200 tag_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_TAGX(ipd_port)); 201 202 /* Have each port go to a different POW queue */ 203 port_config.s.qos = ipd_port & 0x7; 204 205 /* Process the headers and place the IP header in the work queue */ 206 port_config.s.mode = CVMX_HELPER_INPUT_PORT_SKIP_MODE; 207 208 tag_config.s.ip6_src_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_IP; 209 tag_config.s.ip6_dst_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_IP; 210 tag_config.s.ip6_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_SRC_PORT; 211 tag_config.s.ip6_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV6_DST_PORT; 212 tag_config.s.ip6_nxth_flag = CVMX_HELPER_INPUT_TAG_IPV6_NEXT_HEADER; 213 tag_config.s.ip4_src_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_IP; 214 tag_config.s.ip4_dst_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_IP; 215 tag_config.s.ip4_sprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_SRC_PORT; 216 tag_config.s.ip4_dprt_flag = CVMX_HELPER_INPUT_TAG_IPV4_DST_PORT; 217 tag_config.s.ip4_pctl_flag = CVMX_HELPER_INPUT_TAG_IPV4_PROTOCOL; 218 tag_config.s.inc_prt_flag = CVMX_HELPER_INPUT_TAG_INPUT_PORT; 219 tag_config.s.tcp6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 220 tag_config.s.tcp4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 221 tag_config.s.ip6_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 222 tag_config.s.ip4_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 223 tag_config.s.non_tag_type = CVMX_HELPER_INPUT_TAG_TYPE; 224 /* Put all packets in group 0. Other groups can be used by the app */ 225 tag_config.s.grp = 0; 226 227 cvmx_pip_config_port(ipd_port, port_config, tag_config); 228 229 /* Give the user a chance to override our setting for each port */ 230 if (cvmx_override_ipd_port_setup) 231 cvmx_override_ipd_port_setup(ipd_port); 232 233 return 0; 234 } 235 236 /** 237 * This function sets the interface_port_count[interface] correctly, 238 * without modifying any hardware configuration. Hardware setup of 239 * the ports will be performed later. 240 * 241 * @interface: Interface to probe 242 * 243 * Returns Zero on success, negative on failure 244 */ 245 int cvmx_helper_interface_enumerate(int interface) 246 { 247 switch (cvmx_helper_interface_get_mode(interface)) { 248 /* These types don't support ports to IPD/PKO */ 249 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 250 case CVMX_HELPER_INTERFACE_MODE_PCIE: 251 interface_port_count[interface] = 0; 252 break; 253 /* XAUI is a single high speed port */ 254 case CVMX_HELPER_INTERFACE_MODE_XAUI: 255 interface_port_count[interface] = 256 __cvmx_helper_xaui_enumerate(interface); 257 break; 258 /* 259 * RGMII/GMII/MII are all treated about the same. Most 260 * functions refer to these ports as RGMII. 261 */ 262 case CVMX_HELPER_INTERFACE_MODE_RGMII: 263 case CVMX_HELPER_INTERFACE_MODE_GMII: 264 interface_port_count[interface] = 265 __cvmx_helper_rgmii_enumerate(interface); 266 break; 267 /* 268 * SPI4 can have 1-16 ports depending on the device at 269 * the other end. 270 */ 271 case CVMX_HELPER_INTERFACE_MODE_SPI: 272 interface_port_count[interface] = 273 __cvmx_helper_spi_enumerate(interface); 274 break; 275 /* 276 * SGMII can have 1-4 ports depending on how many are 277 * hooked up. 278 */ 279 case CVMX_HELPER_INTERFACE_MODE_SGMII: 280 case CVMX_HELPER_INTERFACE_MODE_PICMG: 281 interface_port_count[interface] = 282 __cvmx_helper_sgmii_enumerate(interface); 283 break; 284 /* PCI target Network Packet Interface */ 285 case CVMX_HELPER_INTERFACE_MODE_NPI: 286 interface_port_count[interface] = 287 __cvmx_helper_npi_enumerate(interface); 288 break; 289 /* 290 * Special loopback only ports. These are not the same 291 * as other ports in loopback mode. 292 */ 293 case CVMX_HELPER_INTERFACE_MODE_LOOP: 294 interface_port_count[interface] = 295 __cvmx_helper_loop_enumerate(interface); 296 break; 297 } 298 299 interface_port_count[interface] = 300 __cvmx_helper_board_interface_probe(interface, 301 interface_port_count 302 [interface]); 303 304 /* Make sure all global variables propagate to other cores */ 305 CVMX_SYNCWS; 306 307 return 0; 308 } 309 310 /** 311 * This function probes an interface to determine the actual 312 * number of hardware ports connected to it. It doesn't setup the 313 * ports or enable them. The main goal here is to set the global 314 * interface_port_count[interface] correctly. Hardware setup of the 315 * ports will be performed later. 316 * 317 * @interface: Interface to probe 318 * 319 * Returns Zero on success, negative on failure 320 */ 321 int cvmx_helper_interface_probe(int interface) 322 { 323 cvmx_helper_interface_enumerate(interface); 324 /* At this stage in the game we don't want packets to be moving yet. 325 The following probe calls should perform hardware setup 326 needed to determine port counts. Receive must still be disabled */ 327 switch (cvmx_helper_interface_get_mode(interface)) { 328 /* These types don't support ports to IPD/PKO */ 329 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 330 case CVMX_HELPER_INTERFACE_MODE_PCIE: 331 break; 332 /* XAUI is a single high speed port */ 333 case CVMX_HELPER_INTERFACE_MODE_XAUI: 334 __cvmx_helper_xaui_probe(interface); 335 break; 336 /* 337 * RGMII/GMII/MII are all treated about the same. Most 338 * functions refer to these ports as RGMII. 339 */ 340 case CVMX_HELPER_INTERFACE_MODE_RGMII: 341 case CVMX_HELPER_INTERFACE_MODE_GMII: 342 __cvmx_helper_rgmii_probe(interface); 343 break; 344 /* 345 * SPI4 can have 1-16 ports depending on the device at 346 * the other end. 347 */ 348 case CVMX_HELPER_INTERFACE_MODE_SPI: 349 __cvmx_helper_spi_probe(interface); 350 break; 351 /* 352 * SGMII can have 1-4 ports depending on how many are 353 * hooked up. 354 */ 355 case CVMX_HELPER_INTERFACE_MODE_SGMII: 356 case CVMX_HELPER_INTERFACE_MODE_PICMG: 357 __cvmx_helper_sgmii_probe(interface); 358 break; 359 /* PCI target Network Packet Interface */ 360 case CVMX_HELPER_INTERFACE_MODE_NPI: 361 __cvmx_helper_npi_probe(interface); 362 break; 363 /* 364 * Special loopback only ports. These are not the same 365 * as other ports in loopback mode. 366 */ 367 case CVMX_HELPER_INTERFACE_MODE_LOOP: 368 __cvmx_helper_loop_probe(interface); 369 break; 370 } 371 372 /* Make sure all global variables propagate to other cores */ 373 CVMX_SYNCWS; 374 375 return 0; 376 } 377 378 /** 379 * Setup the IPD/PIP for the ports on an interface. Packet 380 * classification and tagging are set for every port on the 381 * interface. The number of ports on the interface must already 382 * have been probed. 383 * 384 * @interface: Interface to setup IPD/PIP for 385 * 386 * Returns Zero on success, negative on failure 387 */ 388 static int __cvmx_helper_interface_setup_ipd(int interface) 389 { 390 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 391 int num_ports = interface_port_count[interface]; 392 393 while (num_ports--) { 394 __cvmx_helper_port_setup_ipd(ipd_port); 395 ipd_port++; 396 } 397 return 0; 398 } 399 400 /** 401 * Setup global setting for IPD/PIP not related to a specific 402 * interface or port. This must be called before IPD is enabled. 403 * 404 * Returns Zero on success, negative on failure. 405 */ 406 static int __cvmx_helper_global_setup_ipd(void) 407 { 408 /* Setup the global packet input options */ 409 cvmx_ipd_config(CVMX_FPA_PACKET_POOL_SIZE / 8, 410 CVMX_HELPER_FIRST_MBUFF_SKIP / 8, 411 CVMX_HELPER_NOT_FIRST_MBUFF_SKIP / 8, 412 /* The +8 is to account for the next ptr */ 413 (CVMX_HELPER_FIRST_MBUFF_SKIP + 8) / 128, 414 /* The +8 is to account for the next ptr */ 415 (CVMX_HELPER_NOT_FIRST_MBUFF_SKIP + 8) / 128, 416 CVMX_FPA_WQE_POOL, 417 CVMX_IPD_OPC_MODE_STT, 418 CVMX_HELPER_ENABLE_BACK_PRESSURE); 419 return 0; 420 } 421 422 /** 423 * Setup the PKO for the ports on an interface. The number of 424 * queues per port and the priority of each PKO output queue 425 * is set here. PKO must be disabled when this function is called. 426 * 427 * @interface: Interface to setup PKO for 428 * 429 * Returns Zero on success, negative on failure 430 */ 431 static int __cvmx_helper_interface_setup_pko(int interface) 432 { 433 /* 434 * Each packet output queue has an associated priority. The 435 * higher the priority, the more often it can send a packet. A 436 * priority of 8 means it can send in all 8 rounds of 437 * contention. We're going to make each queue one less than 438 * the last. The vector of priorities has been extended to 439 * support CN5xxx CPUs, where up to 16 queues can be 440 * associated to a port. To keep backward compatibility we 441 * don't change the initial 8 priorities and replicate them in 442 * the second half. With per-core PKO queues (PKO lockless 443 * operation) all queues have the same priority. 444 */ 445 uint64_t priorities[16] = 446 { 8, 7, 6, 5, 4, 3, 2, 1, 8, 7, 6, 5, 4, 3, 2, 1 }; 447 448 /* 449 * Setup the IPD/PIP and PKO for the ports discovered 450 * above. Here packet classification, tagging and output 451 * priorities are set. 452 */ 453 int ipd_port = cvmx_helper_get_ipd_port(interface, 0); 454 int num_ports = interface_port_count[interface]; 455 while (num_ports--) { 456 /* 457 * Give the user a chance to override the per queue 458 * priorities. 459 */ 460 if (cvmx_override_pko_queue_priority) 461 cvmx_override_pko_queue_priority(ipd_port, priorities); 462 463 cvmx_pko_config_port(ipd_port, 464 cvmx_pko_get_base_queue_per_core(ipd_port, 465 0), 466 cvmx_pko_get_num_queues(ipd_port), 467 priorities); 468 ipd_port++; 469 } 470 return 0; 471 } 472 473 /** 474 * Setup global setting for PKO not related to a specific 475 * interface or port. This must be called before PKO is enabled. 476 * 477 * Returns Zero on success, negative on failure. 478 */ 479 static int __cvmx_helper_global_setup_pko(void) 480 { 481 /* 482 * Disable tagwait FAU timeout. This needs to be done before 483 * anyone might start packet output using tags. 484 */ 485 union cvmx_iob_fau_timeout fau_to; 486 fau_to.u64 = 0; 487 fau_to.s.tout_val = 0xfff; 488 fau_to.s.tout_enb = 0; 489 cvmx_write_csr(CVMX_IOB_FAU_TIMEOUT, fau_to.u64); 490 return 0; 491 } 492 493 /** 494 * Setup global backpressure setting. 495 * 496 * Returns Zero on success, negative on failure 497 */ 498 static int __cvmx_helper_global_setup_backpressure(void) 499 { 500 #if CVMX_HELPER_DISABLE_RGMII_BACKPRESSURE 501 /* Disable backpressure if configured to do so */ 502 /* Disable backpressure (pause frame) generation */ 503 int num_interfaces = cvmx_helper_get_number_of_interfaces(); 504 int interface; 505 for (interface = 0; interface < num_interfaces; interface++) { 506 switch (cvmx_helper_interface_get_mode(interface)) { 507 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 508 case CVMX_HELPER_INTERFACE_MODE_PCIE: 509 case CVMX_HELPER_INTERFACE_MODE_NPI: 510 case CVMX_HELPER_INTERFACE_MODE_LOOP: 511 case CVMX_HELPER_INTERFACE_MODE_XAUI: 512 break; 513 case CVMX_HELPER_INTERFACE_MODE_RGMII: 514 case CVMX_HELPER_INTERFACE_MODE_GMII: 515 case CVMX_HELPER_INTERFACE_MODE_SPI: 516 case CVMX_HELPER_INTERFACE_MODE_SGMII: 517 case CVMX_HELPER_INTERFACE_MODE_PICMG: 518 cvmx_gmx_set_backpressure_override(interface, 0xf); 519 break; 520 } 521 } 522 #endif 523 524 return 0; 525 } 526 527 /** 528 * Enable packet input/output from the hardware. This function is 529 * called after all internal setup is complete and IPD is enabled. 530 * After this function completes, packets will be accepted from the 531 * hardware ports. PKO should still be disabled to make sure packets 532 * aren't sent out partially setup hardware. 533 * 534 * @interface: Interface to enable 535 * 536 * Returns Zero on success, negative on failure 537 */ 538 static int __cvmx_helper_packet_hardware_enable(int interface) 539 { 540 int result = 0; 541 switch (cvmx_helper_interface_get_mode(interface)) { 542 /* These types don't support ports to IPD/PKO */ 543 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 544 case CVMX_HELPER_INTERFACE_MODE_PCIE: 545 /* Nothing to do */ 546 break; 547 /* XAUI is a single high speed port */ 548 case CVMX_HELPER_INTERFACE_MODE_XAUI: 549 result = __cvmx_helper_xaui_enable(interface); 550 break; 551 /* 552 * RGMII/GMII/MII are all treated about the same. Most 553 * functions refer to these ports as RGMII 554 */ 555 case CVMX_HELPER_INTERFACE_MODE_RGMII: 556 case CVMX_HELPER_INTERFACE_MODE_GMII: 557 result = __cvmx_helper_rgmii_enable(interface); 558 break; 559 /* 560 * SPI4 can have 1-16 ports depending on the device at 561 * the other end 562 */ 563 case CVMX_HELPER_INTERFACE_MODE_SPI: 564 result = __cvmx_helper_spi_enable(interface); 565 break; 566 /* 567 * SGMII can have 1-4 ports depending on how many are 568 * hooked up 569 */ 570 case CVMX_HELPER_INTERFACE_MODE_SGMII: 571 case CVMX_HELPER_INTERFACE_MODE_PICMG: 572 result = __cvmx_helper_sgmii_enable(interface); 573 break; 574 /* PCI target Network Packet Interface */ 575 case CVMX_HELPER_INTERFACE_MODE_NPI: 576 result = __cvmx_helper_npi_enable(interface); 577 break; 578 /* 579 * Special loopback only ports. These are not the same 580 * as other ports in loopback mode 581 */ 582 case CVMX_HELPER_INTERFACE_MODE_LOOP: 583 result = __cvmx_helper_loop_enable(interface); 584 break; 585 } 586 result |= __cvmx_helper_board_hardware_enable(interface); 587 return result; 588 } 589 590 /** 591 * Function to adjust internal IPD pointer alignments 592 * 593 * Returns 0 on success 594 * !0 on failure 595 */ 596 int __cvmx_helper_errata_fix_ipd_ptr_alignment(void) 597 { 598 #define FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES \ 599 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_FIRST_MBUFF_SKIP) 600 #define FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES \ 601 (CVMX_FPA_PACKET_POOL_SIZE-8-CVMX_HELPER_NOT_FIRST_MBUFF_SKIP) 602 #define FIX_IPD_OUTPORT 0 603 /* Ports 0-15 are interface 0, 16-31 are interface 1 */ 604 #define INTERFACE(port) (port >> 4) 605 #define INDEX(port) (port & 0xf) 606 uint64_t *p64; 607 cvmx_pko_command_word0_t pko_command; 608 union cvmx_buf_ptr g_buffer, pkt_buffer; 609 cvmx_wqe_t *work; 610 int size, num_segs = 0, wqe_pcnt, pkt_pcnt; 611 union cvmx_gmxx_prtx_cfg gmx_cfg; 612 int retry_cnt; 613 int retry_loop_cnt; 614 int i; 615 cvmx_helper_link_info_t link_info; 616 617 /* Save values for restore at end */ 618 uint64_t prtx_cfg = 619 cvmx_read_csr(CVMX_GMXX_PRTX_CFG 620 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); 621 uint64_t tx_ptr_en = 622 cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); 623 uint64_t rx_ptr_en = 624 cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT))); 625 uint64_t rxx_jabber = 626 cvmx_read_csr(CVMX_GMXX_RXX_JABBER 627 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); 628 uint64_t frame_max = 629 cvmx_read_csr(CVMX_GMXX_RXX_FRM_MAX 630 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT))); 631 632 /* Configure port to gig FDX as required for loopback mode */ 633 cvmx_helper_rgmii_internal_loopback(FIX_IPD_OUTPORT); 634 635 /* 636 * Disable reception on all ports so if traffic is present it 637 * will not interfere. 638 */ 639 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 0); 640 641 cvmx_wait(100000000ull); 642 643 for (retry_loop_cnt = 0; retry_loop_cnt < 10; retry_loop_cnt++) { 644 retry_cnt = 100000; 645 wqe_pcnt = cvmx_read_csr(CVMX_IPD_PTR_COUNT); 646 pkt_pcnt = (wqe_pcnt >> 7) & 0x7f; 647 wqe_pcnt &= 0x7f; 648 649 num_segs = (2 + pkt_pcnt - wqe_pcnt) & 3; 650 651 if (num_segs == 0) 652 goto fix_ipd_exit; 653 654 num_segs += 1; 655 656 size = 657 FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES + 658 ((num_segs - 1) * FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES) - 659 (FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES / 2); 660 661 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 662 1 << INDEX(FIX_IPD_OUTPORT)); 663 CVMX_SYNC; 664 665 g_buffer.u64 = 0; 666 g_buffer.s.addr = 667 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_WQE_POOL)); 668 if (g_buffer.s.addr == 0) { 669 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " 670 "buffer allocation failure.\n"); 671 goto fix_ipd_exit; 672 } 673 674 g_buffer.s.pool = CVMX_FPA_WQE_POOL; 675 g_buffer.s.size = num_segs; 676 677 pkt_buffer.u64 = 0; 678 pkt_buffer.s.addr = 679 cvmx_ptr_to_phys(cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL)); 680 if (pkt_buffer.s.addr == 0) { 681 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " 682 "buffer allocation failure.\n"); 683 goto fix_ipd_exit; 684 } 685 pkt_buffer.s.i = 1; 686 pkt_buffer.s.pool = CVMX_FPA_PACKET_POOL; 687 pkt_buffer.s.size = FIX_IPD_FIRST_BUFF_PAYLOAD_BYTES; 688 689 p64 = (uint64_t *) cvmx_phys_to_ptr(pkt_buffer.s.addr); 690 p64[0] = 0xffffffffffff0000ull; 691 p64[1] = 0x08004510ull; 692 p64[2] = ((uint64_t) (size - 14) << 48) | 0x5ae740004000ull; 693 p64[3] = 0x3a5fc0a81073c0a8ull; 694 695 for (i = 0; i < num_segs; i++) { 696 if (i > 0) 697 pkt_buffer.s.size = 698 FIX_IPD_NON_FIRST_BUFF_PAYLOAD_BYTES; 699 700 if (i == (num_segs - 1)) 701 pkt_buffer.s.i = 0; 702 703 *(uint64_t *) cvmx_phys_to_ptr(g_buffer.s.addr + 704 8 * i) = pkt_buffer.u64; 705 } 706 707 /* Build the PKO command */ 708 pko_command.u64 = 0; 709 pko_command.s.segs = num_segs; 710 pko_command.s.total_bytes = size; 711 pko_command.s.dontfree = 0; 712 pko_command.s.gather = 1; 713 714 gmx_cfg.u64 = 715 cvmx_read_csr(CVMX_GMXX_PRTX_CFG 716 (INDEX(FIX_IPD_OUTPORT), 717 INTERFACE(FIX_IPD_OUTPORT))); 718 gmx_cfg.s.en = 1; 719 cvmx_write_csr(CVMX_GMXX_PRTX_CFG 720 (INDEX(FIX_IPD_OUTPORT), 721 INTERFACE(FIX_IPD_OUTPORT)), gmx_cfg.u64); 722 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 723 1 << INDEX(FIX_IPD_OUTPORT)); 724 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 725 1 << INDEX(FIX_IPD_OUTPORT)); 726 727 cvmx_write_csr(CVMX_GMXX_RXX_JABBER 728 (INDEX(FIX_IPD_OUTPORT), 729 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); 730 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX 731 (INDEX(FIX_IPD_OUTPORT), 732 INTERFACE(FIX_IPD_OUTPORT)), 65392 - 14 - 4); 733 734 cvmx_pko_send_packet_prepare(FIX_IPD_OUTPORT, 735 cvmx_pko_get_base_queue 736 (FIX_IPD_OUTPORT), 737 CVMX_PKO_LOCK_CMD_QUEUE); 738 cvmx_pko_send_packet_finish(FIX_IPD_OUTPORT, 739 cvmx_pko_get_base_queue 740 (FIX_IPD_OUTPORT), pko_command, 741 g_buffer, CVMX_PKO_LOCK_CMD_QUEUE); 742 743 CVMX_SYNC; 744 745 do { 746 work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); 747 retry_cnt--; 748 } while ((work == NULL) && (retry_cnt > 0)); 749 750 if (!retry_cnt) 751 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT " 752 "get_work() timeout occurred.\n"); 753 754 /* Free packet */ 755 if (work) 756 cvmx_helper_free_packet_data(work); 757 } 758 759 fix_ipd_exit: 760 761 /* Return CSR configs to saved values */ 762 cvmx_write_csr(CVMX_GMXX_PRTX_CFG 763 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), 764 prtx_cfg); 765 cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 766 tx_ptr_en); 767 cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(INTERFACE(FIX_IPD_OUTPORT)), 768 rx_ptr_en); 769 cvmx_write_csr(CVMX_GMXX_RXX_JABBER 770 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), 771 rxx_jabber); 772 cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX 773 (INDEX(FIX_IPD_OUTPORT), INTERFACE(FIX_IPD_OUTPORT)), 774 frame_max); 775 cvmx_write_csr(CVMX_ASXX_PRT_LOOP(INTERFACE(FIX_IPD_OUTPORT)), 0); 776 /* Set link to down so autonegotiation will set it up again */ 777 link_info.u64 = 0; 778 cvmx_helper_link_set(FIX_IPD_OUTPORT, link_info); 779 780 /* 781 * Bring the link back up as autonegotiation is not done in 782 * user applications. 783 */ 784 cvmx_helper_link_autoconf(FIX_IPD_OUTPORT); 785 786 CVMX_SYNC; 787 if (num_segs) 788 cvmx_dprintf("WARNING: FIX_IPD_PTR_ALIGNMENT failed.\n"); 789 790 return !!num_segs; 791 792 } 793 794 /** 795 * Called after all internal packet IO paths are setup. This 796 * function enables IPD/PIP and begins packet input and output. 797 * 798 * Returns Zero on success, negative on failure 799 */ 800 int cvmx_helper_ipd_and_packet_input_enable(void) 801 { 802 int num_interfaces; 803 int interface; 804 805 /* Enable IPD */ 806 cvmx_ipd_enable(); 807 808 /* 809 * Time to enable hardware ports packet input and output. Note 810 * that at this point IPD/PIP must be fully functional and PKO 811 * must be disabled 812 */ 813 num_interfaces = cvmx_helper_get_number_of_interfaces(); 814 for (interface = 0; interface < num_interfaces; interface++) { 815 if (cvmx_helper_ports_on_interface(interface) > 0) 816 __cvmx_helper_packet_hardware_enable(interface); 817 } 818 819 /* Finally enable PKO now that the entire path is up and running */ 820 cvmx_pko_enable(); 821 822 if ((OCTEON_IS_MODEL(OCTEON_CN31XX_PASS1) 823 || OCTEON_IS_MODEL(OCTEON_CN30XX_PASS1)) 824 && (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM)) 825 __cvmx_helper_errata_fix_ipd_ptr_alignment(); 826 return 0; 827 } 828 829 /** 830 * Initialize the PIP, IPD, and PKO hardware to support 831 * simple priority based queues for the ethernet ports. Each 832 * port is configured with a number of priority queues based 833 * on CVMX_PKO_QUEUES_PER_PORT_* where each queue is lower 834 * priority than the previous. 835 * 836 * Returns Zero on success, non-zero on failure 837 */ 838 int cvmx_helper_initialize_packet_io_global(void) 839 { 840 int result = 0; 841 int interface; 842 union cvmx_l2c_cfg l2c_cfg; 843 union cvmx_smix_en smix_en; 844 const int num_interfaces = cvmx_helper_get_number_of_interfaces(); 845 846 /* 847 * CN52XX pass 1: Due to a bug in 2nd order CDR, it needs to 848 * be disabled. 849 */ 850 if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 851 __cvmx_helper_errata_qlm_disable_2nd_order_cdr(1); 852 853 /* 854 * Tell L2 to give the IOB statically higher priority compared 855 * to the cores. This avoids conditions where IO blocks might 856 * be starved under very high L2 loads. 857 */ 858 l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG); 859 l2c_cfg.s.lrf_arb_mode = 0; 860 l2c_cfg.s.rfb_arb_mode = 0; 861 cvmx_write_csr(CVMX_L2C_CFG, l2c_cfg.u64); 862 863 /* Make sure SMI/MDIO is enabled so we can query PHYs */ 864 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(0)); 865 if (!smix_en.s.en) { 866 smix_en.s.en = 1; 867 cvmx_write_csr(CVMX_SMIX_EN(0), smix_en.u64); 868 } 869 870 /* Newer chips actually have two SMI/MDIO interfaces */ 871 if (!OCTEON_IS_MODEL(OCTEON_CN3XXX) && 872 !OCTEON_IS_MODEL(OCTEON_CN58XX) && 873 !OCTEON_IS_MODEL(OCTEON_CN50XX)) { 874 smix_en.u64 = cvmx_read_csr(CVMX_SMIX_EN(1)); 875 if (!smix_en.s.en) { 876 smix_en.s.en = 1; 877 cvmx_write_csr(CVMX_SMIX_EN(1), smix_en.u64); 878 } 879 } 880 881 cvmx_pko_initialize_global(); 882 for (interface = 0; interface < num_interfaces; interface++) { 883 result |= cvmx_helper_interface_probe(interface); 884 if (cvmx_helper_ports_on_interface(interface) > 0) 885 cvmx_dprintf("Interface %d has %d ports (%s)\n", 886 interface, 887 cvmx_helper_ports_on_interface(interface), 888 cvmx_helper_interface_mode_to_string 889 (cvmx_helper_interface_get_mode 890 (interface))); 891 result |= __cvmx_helper_interface_setup_ipd(interface); 892 result |= __cvmx_helper_interface_setup_pko(interface); 893 } 894 895 result |= __cvmx_helper_global_setup_ipd(); 896 result |= __cvmx_helper_global_setup_pko(); 897 898 /* Enable any flow control and backpressure */ 899 result |= __cvmx_helper_global_setup_backpressure(); 900 901 #if CVMX_HELPER_ENABLE_IPD 902 result |= cvmx_helper_ipd_and_packet_input_enable(); 903 #endif 904 return result; 905 } 906 907 /** 908 * Does core local initialization for packet io 909 * 910 * Returns Zero on success, non-zero on failure 911 */ 912 int cvmx_helper_initialize_packet_io_local(void) 913 { 914 return cvmx_pko_initialize_local(); 915 } 916 917 /** 918 * Auto configure an IPD/PKO port link state and speed. This 919 * function basically does the equivalent of: 920 * cvmx_helper_link_set(ipd_port, cvmx_helper_link_get(ipd_port)); 921 * 922 * @ipd_port: IPD/PKO port to auto configure 923 * 924 * Returns Link state after configure 925 */ 926 cvmx_helper_link_info_t cvmx_helper_link_autoconf(int ipd_port) 927 { 928 cvmx_helper_link_info_t link_info; 929 int interface = cvmx_helper_get_interface_num(ipd_port); 930 int index = cvmx_helper_get_interface_index_num(ipd_port); 931 932 if (index >= cvmx_helper_ports_on_interface(interface)) { 933 link_info.u64 = 0; 934 return link_info; 935 } 936 937 link_info = cvmx_helper_link_get(ipd_port); 938 if (link_info.u64 == port_link_info[ipd_port].u64) 939 return link_info; 940 941 /* If we fail to set the link speed, port_link_info will not change */ 942 cvmx_helper_link_set(ipd_port, link_info); 943 944 /* 945 * port_link_info should be the current value, which will be 946 * different than expect if cvmx_helper_link_set() failed. 947 */ 948 return port_link_info[ipd_port]; 949 } 950 951 /** 952 * Return the link state of an IPD/PKO port as returned by 953 * auto negotiation. The result of this function may not match 954 * Octeon's link config if auto negotiation has changed since 955 * the last call to cvmx_helper_link_set(). 956 * 957 * @ipd_port: IPD/PKO port to query 958 * 959 * Returns Link state 960 */ 961 cvmx_helper_link_info_t cvmx_helper_link_get(int ipd_port) 962 { 963 cvmx_helper_link_info_t result; 964 int interface = cvmx_helper_get_interface_num(ipd_port); 965 int index = cvmx_helper_get_interface_index_num(ipd_port); 966 967 /* The default result will be a down link unless the code below 968 changes it */ 969 result.u64 = 0; 970 971 if (index >= cvmx_helper_ports_on_interface(interface)) 972 return result; 973 974 switch (cvmx_helper_interface_get_mode(interface)) { 975 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 976 case CVMX_HELPER_INTERFACE_MODE_PCIE: 977 /* Network links are not supported */ 978 break; 979 case CVMX_HELPER_INTERFACE_MODE_XAUI: 980 result = __cvmx_helper_xaui_link_get(ipd_port); 981 break; 982 case CVMX_HELPER_INTERFACE_MODE_GMII: 983 if (index == 0) 984 result = __cvmx_helper_rgmii_link_get(ipd_port); 985 else { 986 result.s.full_duplex = 1; 987 result.s.link_up = 1; 988 result.s.speed = 1000; 989 } 990 break; 991 case CVMX_HELPER_INTERFACE_MODE_RGMII: 992 result = __cvmx_helper_rgmii_link_get(ipd_port); 993 break; 994 case CVMX_HELPER_INTERFACE_MODE_SPI: 995 result = __cvmx_helper_spi_link_get(ipd_port); 996 break; 997 case CVMX_HELPER_INTERFACE_MODE_SGMII: 998 case CVMX_HELPER_INTERFACE_MODE_PICMG: 999 result = __cvmx_helper_sgmii_link_get(ipd_port); 1000 break; 1001 case CVMX_HELPER_INTERFACE_MODE_NPI: 1002 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1003 /* Network links are not supported */ 1004 break; 1005 } 1006 return result; 1007 } 1008 1009 /** 1010 * Configure an IPD/PKO port for the specified link state. This 1011 * function does not influence auto negotiation at the PHY level. 1012 * The passed link state must always match the link state returned 1013 * by cvmx_helper_link_get(). It is normally best to use 1014 * cvmx_helper_link_autoconf() instead. 1015 * 1016 * @ipd_port: IPD/PKO port to configure 1017 * @link_info: The new link state 1018 * 1019 * Returns Zero on success, negative on failure 1020 */ 1021 int cvmx_helper_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 1022 { 1023 int result = -1; 1024 int interface = cvmx_helper_get_interface_num(ipd_port); 1025 int index = cvmx_helper_get_interface_index_num(ipd_port); 1026 1027 if (index >= cvmx_helper_ports_on_interface(interface)) 1028 return -1; 1029 1030 switch (cvmx_helper_interface_get_mode(interface)) { 1031 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1032 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1033 break; 1034 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1035 result = __cvmx_helper_xaui_link_set(ipd_port, link_info); 1036 break; 1037 /* 1038 * RGMII/GMII/MII are all treated about the same. Most 1039 * functions refer to these ports as RGMII. 1040 */ 1041 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1042 case CVMX_HELPER_INTERFACE_MODE_GMII: 1043 result = __cvmx_helper_rgmii_link_set(ipd_port, link_info); 1044 break; 1045 case CVMX_HELPER_INTERFACE_MODE_SPI: 1046 result = __cvmx_helper_spi_link_set(ipd_port, link_info); 1047 break; 1048 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1049 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1050 result = __cvmx_helper_sgmii_link_set(ipd_port, link_info); 1051 break; 1052 case CVMX_HELPER_INTERFACE_MODE_NPI: 1053 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1054 break; 1055 } 1056 /* Set the port_link_info here so that the link status is updated 1057 no matter how cvmx_helper_link_set is called. We don't change 1058 the value if link_set failed */ 1059 if (result == 0) 1060 port_link_info[ipd_port].u64 = link_info.u64; 1061 return result; 1062 } 1063 1064 /** 1065 * Configure a port for internal and/or external loopback. Internal loopback 1066 * causes packets sent by the port to be received by Octeon. External loopback 1067 * causes packets received from the wire to sent out again. 1068 * 1069 * @ipd_port: IPD/PKO port to loopback. 1070 * @enable_internal: 1071 * Non zero if you want internal loopback 1072 * @enable_external: 1073 * Non zero if you want external loopback 1074 * 1075 * Returns Zero on success, negative on failure. 1076 */ 1077 int cvmx_helper_configure_loopback(int ipd_port, int enable_internal, 1078 int enable_external) 1079 { 1080 int result = -1; 1081 int interface = cvmx_helper_get_interface_num(ipd_port); 1082 int index = cvmx_helper_get_interface_index_num(ipd_port); 1083 1084 if (index >= cvmx_helper_ports_on_interface(interface)) 1085 return -1; 1086 1087 switch (cvmx_helper_interface_get_mode(interface)) { 1088 case CVMX_HELPER_INTERFACE_MODE_DISABLED: 1089 case CVMX_HELPER_INTERFACE_MODE_PCIE: 1090 case CVMX_HELPER_INTERFACE_MODE_SPI: 1091 case CVMX_HELPER_INTERFACE_MODE_NPI: 1092 case CVMX_HELPER_INTERFACE_MODE_LOOP: 1093 break; 1094 case CVMX_HELPER_INTERFACE_MODE_XAUI: 1095 result = 1096 __cvmx_helper_xaui_configure_loopback(ipd_port, 1097 enable_internal, 1098 enable_external); 1099 break; 1100 case CVMX_HELPER_INTERFACE_MODE_RGMII: 1101 case CVMX_HELPER_INTERFACE_MODE_GMII: 1102 result = 1103 __cvmx_helper_rgmii_configure_loopback(ipd_port, 1104 enable_internal, 1105 enable_external); 1106 break; 1107 case CVMX_HELPER_INTERFACE_MODE_SGMII: 1108 case CVMX_HELPER_INTERFACE_MODE_PICMG: 1109 result = 1110 __cvmx_helper_sgmii_configure_loopback(ipd_port, 1111 enable_internal, 1112 enable_external); 1113 break; 1114 } 1115 return result; 1116 } 1117