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