cvmx-helper-xaui.c revision 210284
1/***********************license start*************** 2 * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * * Neither the name of Cavium Networks nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 * 23 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 24 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS 25 * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH 26 * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY 27 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT 28 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES 29 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR 30 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET 31 * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT 32 * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 33 * 34 * 35 * For any questions regarding licensing please contact marketing@caviumnetworks.com 36 * 37 ***********************license end**************************************/ 38 39 40 41 42 43 44/** 45 * @file 46 * 47 * Functions for XAUI initialization, configuration, 48 * and monitoring. 49 * 50 * <hr>$Revision: 42417 $<hr> 51 */ 52#include "executive-config.h" 53#include "cvmx-config.h" 54#ifdef CVMX_ENABLE_PKO_FUNCTIONS 55 56#include "cvmx.h" 57#include "cvmx-helper.h" 58 59 60/** 61 * @INTERNAL 62 * Probe a XAUI interface and determine the number of ports 63 * connected to it. The XAUI interface should still be down 64 * after this call. 65 * 66 * @param interface Interface to probe 67 * 68 * @return Number of ports on the interface. Zero to disable. 69 */ 70int __cvmx_helper_xaui_probe(int interface) 71{ 72 int i; 73 cvmx_gmxx_hg2_control_t gmx_hg2_control; 74 cvmx_gmxx_inf_mode_t mode; 75 76 /* Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the interface 77 needs to be enabled before IPD otherwise per port backpressure 78 may not work properly */ 79 mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 80 mode.s.en = 1; 81 cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); 82 83 __cvmx_helper_setup_gmx(interface, 1); 84 85 /* Setup PKO to support 16 ports for HiGig2 virtual ports. We're pointing 86 all of the PKO packet ports for this interface to the XAUI. This allows 87 us to use HiGig2 backpressure per port */ 88 for (i=0; i<16; i++) 89 { 90 cvmx_pko_mem_port_ptrs_t pko_mem_port_ptrs; 91 pko_mem_port_ptrs.u64 = 0; 92 /* We set each PKO port to have equal priority in a round robin 93 fashion */ 94 pko_mem_port_ptrs.s.static_p = 0; 95 pko_mem_port_ptrs.s.qos_mask = 0xff; 96 /* All PKO ports map to the same XAUI hardware port */ 97 pko_mem_port_ptrs.s.eid = interface*4; 98 pko_mem_port_ptrs.s.pid = interface*16 + i; 99 cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64); 100 } 101 102 /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */ 103 gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface)); 104 if (gmx_hg2_control.s.hg2tx_en) 105 return 16; 106 else 107 return 1; 108} 109 110 111/** 112 * @INTERNAL 113 * Bringup and enable a XAUI interface. After this call packet 114 * I/O should be fully functional. This is called with IPD 115 * enabled but PKO disabled. 116 * 117 * @param interface Interface to bring up 118 * 119 * @return Zero on success, negative on failure 120 */ 121int __cvmx_helper_xaui_enable(int interface) 122{ 123 cvmx_gmxx_prtx_cfg_t gmx_cfg; 124 cvmx_pcsxx_control1_reg_t xauiCtl; 125 cvmx_pcsxx_misc_ctl_reg_t xauiMiscCtl; 126 cvmx_gmxx_tx_xaui_ctl_t gmxXauiTxCtl; 127 cvmx_gmxx_rxx_int_en_t gmx_rx_int_en; 128 cvmx_gmxx_tx_int_en_t gmx_tx_int_en; 129 cvmx_pcsxx_int_en_reg_t pcsx_int_en_reg; 130 131 /* (1) Interface has already been enabled. */ 132 133 /* (2) Disable GMX. */ 134 xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface)); 135 xauiMiscCtl.s.gmxeno = 1; 136 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); 137 138 /* (3) Disable GMX and PCSX interrupts. */ 139 gmx_rx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_EN(0,interface)); 140 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), 0x0); 141 gmx_tx_int_en.u64 = cvmx_read_csr(CVMX_GMXX_TX_INT_EN(interface)); 142 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); 143 pcsx_int_en_reg.u64 = cvmx_read_csr(CVMX_PCSXX_INT_EN_REG(interface)); 144 cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); 145 146 /* (4) Bring up the PCSX and GMX reconciliation layer. */ 147 /* (4)a Set polarity and lane swapping. */ 148 /* (4)b */ 149 gmxXauiTxCtl.u64 = cvmx_read_csr (CVMX_GMXX_TX_XAUI_CTL(interface)); 150 gmxXauiTxCtl.s.dic_en = 1; /* Enable better IFG packing and improves performance */ 151 gmxXauiTxCtl.s.uni_en = 0; 152 cvmx_write_csr (CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64); 153 154 /* (4)c Aply reset sequence */ 155 xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface)); 156 xauiCtl.s.lo_pwr = 0; 157 xauiCtl.s.reset = 1; 158 cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64); 159 160 /* Wait for PCS to come out of reset */ 161 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_CONTROL1_REG(interface), cvmx_pcsxx_control1_reg_t, reset, ==, 0, 10000)) 162 return -1; 163 /* Wait for PCS to be aligned */ 164 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_10GBX_STATUS_REG(interface), cvmx_pcsxx_10gbx_status_reg_t, alignd, ==, 1, 10000)) 165 return -1; 166 /* Wait for RX to be ready */ 167 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_RX_XAUI_CTL(interface), cvmx_gmxx_rx_xaui_ctl_t, status, ==, 0, 10000)) 168 return -1; 169 170 /* (6) Configure GMX */ 171 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 172 gmx_cfg.s.en = 0; 173 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); 174 175 /* Wait for GMX RX to be idle */ 176 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, 10000)) 177 return -1; 178 /* Wait for GMX TX to be idle */ 179 if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, 10000)) 180 return -1; 181 182 /* GMX configure */ 183 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 184 gmx_cfg.s.speed = 1; 185 gmx_cfg.s.speed_msb = 0; 186 gmx_cfg.s.slottime = 1; 187 cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1); 188 cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512); 189 cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192); 190 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); 191 192 /* (7) Clear out any error state */ 193 cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0,interface), cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(0,interface))); 194 cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), cvmx_read_csr(CVMX_GMXX_TX_INT_REG(interface))); 195 cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), cvmx_read_csr(CVMX_PCSXX_INT_REG(interface))); 196 197 /* Wait for receive link */ 198 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS1_REG(interface), cvmx_pcsxx_status1_reg_t, rcv_lnk, ==, 1, 10000)) 199 return -1; 200 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000)) 201 return -1; 202 if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000)) 203 return -1; 204 205 cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), gmx_rx_int_en.u64); 206 cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), gmx_tx_int_en.u64); 207 cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), pcsx_int_en_reg.u64); 208 209 cvmx_helper_link_autoconf(cvmx_helper_get_ipd_port(interface, 0)); 210 211 /* (8) Enable packet reception */ 212 xauiMiscCtl.s.gmxeno = 0; 213 cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); 214 215 gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 216 gmx_cfg.s.en = 1; 217 cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); 218 return 0; 219} 220 221/** 222 * @INTERNAL 223 * Return the link state of an IPD/PKO port as returned by 224 * auto negotiation. The result of this function may not match 225 * Octeon's link config if auto negotiation has changed since 226 * the last call to cvmx_helper_link_set(). 227 * 228 * @param ipd_port IPD/PKO port to query 229 * 230 * @return Link state 231 */ 232cvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port) 233{ 234 int interface = cvmx_helper_get_interface_num(ipd_port); 235 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl; 236 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl; 237 cvmx_pcsxx_status1_reg_t pcsxx_status1_reg; 238 cvmx_helper_link_info_t result; 239 240 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); 241 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); 242 pcsxx_status1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface)); 243 result.u64 = 0; 244 245 /* Only return a link if both RX and TX are happy */ 246 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) && 247 (pcsxx_status1_reg.s.rcv_lnk == 1)) 248 { 249 result.s.link_up = 1; 250 result.s.full_duplex = 1; 251 result.s.speed = 10000; 252 } 253 else 254 { 255 /* Disable GMX and PCSX interrupts. */ 256 cvmx_write_csr (CVMX_GMXX_RXX_INT_EN(0,interface), 0x0); 257 cvmx_write_csr (CVMX_GMXX_TX_INT_EN(interface), 0x0); 258 cvmx_write_csr (CVMX_PCSXX_INT_EN_REG(interface), 0x0); 259 } 260 return result; 261} 262 263 264/** 265 * @INTERNAL 266 * Configure an IPD/PKO port for the specified link state. This 267 * function does not influence auto negotiation at the PHY level. 268 * The passed link state must always match the link state returned 269 * by cvmx_helper_link_get(). It is normally best to use 270 * cvmx_helper_link_autoconf() instead. 271 * 272 * @param ipd_port IPD/PKO port to configure 273 * @param link_info The new link state 274 * 275 * @return Zero on success, negative on failure 276 */ 277int __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 278{ 279 int interface = cvmx_helper_get_interface_num(ipd_port); 280 cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl; 281 cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl; 282 283 gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); 284 gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); 285 286 /* If the link shouldn't be up, then just return */ 287 if (!link_info.s.link_up) 288 return 0; 289 290 /* Do nothing if both RX and TX are happy */ 291 if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0)) 292 return 0; 293 294 /* Bring the link up */ 295 return __cvmx_helper_xaui_enable(interface); 296} 297 298 299/** 300 * @INTERNAL 301 * Configure a port for internal and/or external loopback. Internal loopback 302 * causes packets sent by the port to be received by Octeon. External loopback 303 * causes packets received from the wire to sent out again. 304 * 305 * @param ipd_port IPD/PKO port to loopback. 306 * @param enable_internal 307 * Non zero if you want internal loopback 308 * @param enable_external 309 * Non zero if you want external loopback 310 * 311 * @return Zero on success, negative on failure. 312 */ 313extern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external) 314{ 315 int interface = cvmx_helper_get_interface_num(ipd_port); 316 cvmx_pcsxx_control1_reg_t pcsxx_control1_reg; 317 cvmx_gmxx_xaui_ext_loopback_t gmxx_xaui_ext_loopback; 318 319 /* Set the internal loop */ 320 pcsxx_control1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); 321 pcsxx_control1_reg.s.loopbck1 = enable_internal; 322 cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), pcsxx_control1_reg.u64); 323 324 /* Set the external loop */ 325 gmxx_xaui_ext_loopback.u64 = cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface)); 326 gmxx_xaui_ext_loopback.s.en = enable_external; 327 cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), gmxx_xaui_ext_loopback.u64); 328 329 /* Take the link through a reset */ 330 return __cvmx_helper_xaui_enable(interface); 331} 332 333#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 334 335