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