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