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