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