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