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