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