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