1139749Simp/***********************license start*************** 2119853Scg * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 364064Scg * reserved. 464064Scg * 564064Scg * 664064Scg * Redistribution and use in source and binary forms, with or without 764064Scg * modification, are permitted provided that the following conditions are 864064Scg * met: 964064Scg * 1064064Scg * * Redistributions of source code must retain the above copyright 1164064Scg * notice, this list of conditions and the following disclaimer. 1264064Scg * 1364064Scg * * Redistributions in binary form must reproduce the above 1464064Scg * copyright notice, this list of conditions and the following 1564064Scg * disclaimer in the documentation and/or other materials provided 1664064Scg * with the distribution. 1764064Scg 1864064Scg * * Neither the name of Cavium Inc. nor the names of 1964064Scg * its contributors may be used to endorse or promote products 2064064Scg * derived from this software without specific prior written 2164064Scg * permission. 2264064Scg 2364064Scg * This Software, including technical data, may be subject to U.S. export control 2464064Scg * laws, including the U.S. Export Administration Act and its associated 2564064Scg * regulations, and may be subject to export or import regulations in other 26193640Sariff * countries. 27193640Sariff 28193640Sariff * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29193640Sariff * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 3064064Scg * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 3164064Scg * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32119287Simp * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33119287Simp * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 3464064Scg * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 3564064Scg * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 3664064Scg * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 3764064Scg * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 3870134Scg ***********************license end**************************************/ 3970134Scg 4082180Scg 4182180Scg 4284658Scg 4364064Scg 4464064Scg 4564163Snsayer 46154881Sariff/** 4764064Scg * @file 4864064Scg * 4964064Scg * Functions for XAUI initialization, configuration, 5064064Scg * and monitoring. 51154066Sariff * 52154066Sariff * <hr>$Revision: 70030 $<hr> 53154066Sariff */ 5464881Scg#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 55193640Sariff#include <asm/octeon/cvmx.h> 56193640Sariff#include <asm/octeon/cvmx-config.h> 57193640Sariff#ifdef CVMX_ENABLE_PKO_FUNCTIONS 58193640Sariff#include <asm/octeon/cvmx-qlm.h> 59193640Sariff#include <asm/octeon/cvmx-helper.h> 60193640Sariff#include <asm/octeon/cvmx-helper-cfg.h> 61193640Sariff#endif 62193640Sariff#include <asm/octeon/cvmx-gmxx-defs.h> 6364881Scg#include <asm/octeon/cvmx-pko-defs.h> 6464064Scg#include <asm/octeon/cvmx-pcsx-defs.h> 65154024Sariff#include <asm/octeon/cvmx-pcsxx-defs.h> 6664064Scg#include <asm/octeon/cvmx-ciu-defs.h> 6764163Snsayer#else 6864163Snsayer#if !defined(__FreeBSD__) || !defined(_KERNEL) 6964163Snsayer#include "executive-config.h" 7064881Scg#include "cvmx-config.h" 71193640Sariff 72193640Sariff#ifdef CVMX_ENABLE_PKO_FUNCTIONS 73193640Sariff 74193640Sariff#include "cvmx.h" 75193640Sariff#include "cvmx-helper.h" 76193640Sariff#include "cvmx-helper-cfg.h" 77193640Sariff#include "cvmx-qlm.h" 78193640Sariff#endif 7964881Scg#else 8064064Scg#include "cvmx.h" 81154024Sariff#include "cvmx-helper.h" 8264064Scg#include "cvmx-qlm.h" 8364064Scg#endif 8464064Scg#endif 8564064Scg 8664064Scg#ifdef CVMX_ENABLE_PKO_FUNCTIONS 8774763Scg 8874763Scgint __cvmx_helper_xaui_enumerate(int interface) 8964064Scg{ 9070291Scg union cvmx_gmxx_hg2_control gmx_hg2_control; 9164064Scg 9264064Scg /* If HiGig2 is enabled return 16 ports, otherwise return 1 port */ 9364064Scg gmx_hg2_control.u64 = cvmx_read_csr(CVMX_GMXX_HG2_CONTROL(interface)); 9464064Scg if (gmx_hg2_control.s.hg2tx_en) 9564064Scg return 16; 9665644Scg else 9764064Scg return 1; 9864064Scg} 99170032Sariff 100170032Sariff/** 10184658Scg * @INTERNAL 10284658Scg * Probe a XAUI interface and determine the number of ports 10364064Scg * connected to it. The XAUI interface should still be down 104154066Sariff * after this call. 105154066Sariff * 106154066Sariff * @param interface Interface to probe 10764064Scg * 10864064Scg * @return Number of ports on the interface. Zero to disable. 109154066Sariff */ 110154066Sariffint __cvmx_helper_xaui_probe(int interface) 111154066Sariff{ 112154066Sariff int i; 113154066Sariff cvmx_gmxx_inf_mode_t mode; 114154066Sariff 115154066Sariff /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ 116154066Sariff if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 117154066Sariff { 118154066Sariff cvmx_ciu_qlm2_t ciu_qlm; 11964064Scg ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM2); 12064064Scg ciu_qlm.s.txbypass = 1; 12164064Scg ciu_qlm.s.txdeemph = 0x5; 12264064Scg ciu_qlm.s.txmargin = 0x1a; 12364064Scg cvmx_write_csr(CVMX_CIU_QLM2, ciu_qlm.u64); 12464064Scg } 12564064Scg 12664064Scg /* CN63XX Pass 2.0 and 2.1 errata G-15273 requires the QLM De-emphasis be 12764064Scg programmed when using a 156.25Mhz ref clock */ 12864064Scg if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || 12964064Scg OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1)) 13064064Scg { 13164064Scg /* Read the QLM speed pins */ 13264064Scg cvmx_mio_rst_boot_t mio_rst_boot; 13364064Scg mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); 13464064Scg 13564064Scg if (mio_rst_boot.cn63xx.qlm2_spd == 0xb) 13664064Scg { 13764064Scg cvmx_ciu_qlm2_t ciu_qlm; 13864064Scg ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM2); 13964064Scg ciu_qlm.s.txbypass = 1; 14064064Scg ciu_qlm.s.txdeemph = 0xa; 14164064Scg ciu_qlm.s.txmargin = 0x1f; 14264064Scg cvmx_write_csr(CVMX_CIU_QLM2, ciu_qlm.u64); 14364064Scg } 14464064Scg } 14564064Scg 14664064Scg /* Check if QLM is configured correct for XAUI/RXAUI, verify the 14764064Scg speed as well as mode */ 14864064Scg if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 14964064Scg { 15064064Scg int qlm, status; 15164064Scg 15264064Scg qlm = cvmx_qlm_interface(interface); 15364064Scg status = cvmx_qlm_get_status(qlm); 15464064Scg if (status != 2 && status != 10) 15564064Scg return 0; 15664064Scg } 15764064Scg 15864064Scg /* Due to errata GMX-700 on CN56XXp1.x and CN52XXp1.x, the interface 15964064Scg needs to be enabled before IPD otherwise per port backpressure 16064064Scg may not work properly */ 16164064Scg mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); 16264064Scg mode.s.en = 1; 16364064Scg cvmx_write_csr(CVMX_GMXX_INF_MODE(interface), mode.u64); 16464064Scg 16564064Scg __cvmx_helper_setup_gmx(interface, 1); 16664064Scg 16764064Scg if (!OCTEON_IS_MODEL(OCTEON_CN68XX)) 16864064Scg { 16964064Scg /* Setup PKO to support 16 ports for HiGig2 virtual ports. We're pointing 17064064Scg all of the PKO packet ports for this interface to the XAUI. This allows 17164064Scg us to use HiGig2 backpressure per port */ 17264064Scg for (i=0; i<16; i++) 17364064Scg { 17464064Scg cvmx_pko_mem_port_ptrs_t pko_mem_port_ptrs; 17564064Scg pko_mem_port_ptrs.u64 = 0; 17664064Scg /* We set each PKO port to have equal priority in a round robin 17764064Scg fashion */ 17864064Scg pko_mem_port_ptrs.s.static_p = 0; 17964064Scg pko_mem_port_ptrs.s.qos_mask = 0xff; 18064064Scg /* All PKO ports map to the same XAUI hardware port */ 18164064Scg pko_mem_port_ptrs.s.eid = interface*4; 18264064Scg pko_mem_port_ptrs.s.pid = interface*16 + i; 18364064Scg cvmx_write_csr(CVMX_PKO_MEM_PORT_PTRS, pko_mem_port_ptrs.u64); 18464064Scg } 18564064Scg } 18664064Scg 18764064Scg return __cvmx_helper_xaui_enumerate(interface); 18864064Scg} 18964064Scg 19064064Scg/** 19164064Scg * @INTERNAL 19264064Scg * Bringup XAUI interface. After this call packet I/O should be 19364064Scg * fully functional. 19464064Scg * 19564064Scg * @param interface Interface to bring up 19664064Scg * 19764064Scg * @return Zero on success, negative on failure 19864064Scg */ 19964064Scgstatic int __cvmx_helper_xaui_link_init(int interface) 20064064Scg{ 20164064Scg cvmx_gmxx_prtx_cfg_t gmx_cfg; 20264064Scg cvmx_pcsxx_control1_reg_t xauiCtl; 20364064Scg cvmx_pcsxx_misc_ctl_reg_t xauiMiscCtl; 20464064Scg cvmx_gmxx_tx_xaui_ctl_t gmxXauiTxCtl; 20564064Scg 20664064Scg /* (1) Interface has already been enabled. */ 20764064Scg 20864064Scg /* (2) Disable GMX. */ 20964064Scg xauiMiscCtl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface)); 21064064Scg xauiMiscCtl.s.gmxeno = 1; 21164064Scg cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); 21264064Scg 21364064Scg /* (3) Disable GMX and PCSX interrupts. */ 21464064Scg cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(0,interface), 0x0); 21564064Scg cvmx_write_csr(CVMX_GMXX_TX_INT_EN(interface), 0x0); 21664064Scg cvmx_write_csr(CVMX_PCSXX_INT_EN_REG(interface), 0x0); 21764064Scg 21864064Scg /* (4) Bring up the PCSX and GMX reconciliation layer. */ 21964064Scg /* (4)a Set polarity and lane swapping. */ 22064064Scg /* (4)b */ 22164064Scg gmxXauiTxCtl.u64 = cvmx_read_csr (CVMX_GMXX_TX_XAUI_CTL(interface)); 22264064Scg gmxXauiTxCtl.s.dic_en = 1; /* Enable better IFG packing and improves performance */ 22364064Scg gmxXauiTxCtl.s.uni_en = 0; 22464064Scg cvmx_write_csr (CVMX_GMXX_TX_XAUI_CTL(interface), gmxXauiTxCtl.u64); 22564064Scg 22664064Scg /* (4)c Aply reset sequence */ 22764140Snsayer xauiCtl.u64 = cvmx_read_csr (CVMX_PCSXX_CONTROL1_REG(interface)); 22864064Scg xauiCtl.s.lo_pwr = 0; 22964064Scg 23064064Scg /* Errata G-15618 requires disabling PCS soft reset in some OCTEON II models. */ 23164064Scg if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X) 23264064Scg && !OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) 23364064Scg && !OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1) 23464140Snsayer && !OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X) 23564064Scg && !OCTEON_IS_MODEL(OCTEON_CN68XX)) 23664064Scg xauiCtl.s.reset = 1; 23764064Scg cvmx_write_csr (CVMX_PCSXX_CONTROL1_REG(interface), xauiCtl.u64); 23864064Scg 23964064Scg /* Wait for PCS to come out of reset */ 24064064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_CONTROL1_REG(interface), cvmx_pcsxx_control1_reg_t, reset, ==, 0, 10000)) 24164064Scg return -1; 24264064Scg /* Wait for PCS to be aligned */ 24364064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_10GBX_STATUS_REG(interface), cvmx_pcsxx_10gbx_status_reg_t, alignd, ==, 1, 10000)) 24464064Scg return -1; 24564064Scg /* Wait for RX to be ready */ 24664064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_RX_XAUI_CTL(interface), cvmx_gmxx_rx_xaui_ctl_t, status, ==, 0, 10000)) 24764064Scg return -1; 24864064Scg 24964064Scg /* (6) Configure GMX */ 25064064Scg 25164064Scg /* Wait for GMX RX to be idle */ 25264064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, rx_idle, ==, 1, 10000)) 25364064Scg return -1; 25464064Scg /* Wait for GMX TX to be idle */ 25564064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_GMXX_PRTX_CFG(0, interface), cvmx_gmxx_prtx_cfg_t, tx_idle, ==, 1, 10000)) 25664064Scg return -1; 25764064Scg 25864064Scg /* GMX configure */ 25964064Scg gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 26064064Scg gmx_cfg.s.speed = 1; 26164064Scg gmx_cfg.s.speed_msb = 0; 26264064Scg gmx_cfg.s.slottime = 1; 26364064Scg cvmx_write_csr(CVMX_GMXX_TX_PRTS(interface), 1); 26464064Scg cvmx_write_csr(CVMX_GMXX_TXX_SLOT(0, interface), 512); 26564064Scg cvmx_write_csr(CVMX_GMXX_TXX_BURST(0, interface), 8192); 26664064Scg cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); 26764064Scg 26864064Scg /* Wait for receive link */ 26964447Snsayer if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS1_REG(interface), cvmx_pcsxx_status1_reg_t, rcv_lnk, ==, 1, 10000)) 27064064Scg return -1; 27164064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, xmtflt, ==, 0, 10000)) 27264064Scg return -1; 27364064Scg if (CVMX_WAIT_FOR_FIELD64(CVMX_PCSXX_STATUS2_REG(interface), cvmx_pcsxx_status2_reg_t, rcvflt, ==, 0, 10000)) 27464064Scg return -1; 27564064Scg 27664064Scg /* (8) Enable packet reception */ 27764064Scg xauiMiscCtl.s.gmxeno = 0; 27864064Scg cvmx_write_csr (CVMX_PCSXX_MISC_CTL_REG(interface), xauiMiscCtl.u64); 27964064Scg 28064064Scg /* Clear all error interrupts before enabling the interface. */ 28164064Scg cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(0,interface), ~0x0ull); 28264064Scg cvmx_write_csr(CVMX_GMXX_TX_INT_REG(interface), ~0x0ull); 28364064Scg cvmx_write_csr(CVMX_PCSXX_INT_REG(interface), ~0x0ull); 28464064Scg 28564064Scg /* Enable GMX */ 28664064Scg gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 28764064Scg gmx_cfg.s.en = 1; 28864064Scg cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmx_cfg.u64); 28964064Scg 29064064Scg return 0; 29164064Scg} 29264140Snsayer 29364064Scg/** 29464064Scg * @INTERNAL 29564064Scg * Bringup and enable a XAUI interface. After this call packet 29664064Scg * I/O should be fully functional. This is called with IPD 29764140Snsayer * enabled but PKO disabled. 29864140Snsayer * 29964064Scg * @param interface Interface to bring up 30064140Snsayer * 30164064Scg * @return Zero on success, negative on failure 30264064Scg */ 30364064Scgint __cvmx_helper_xaui_enable(int interface) 30464064Scg{ 30564064Scg /* Setup PKND and BPID */ 30664064Scg if (octeon_has_feature(OCTEON_FEATURE_PKND)) 30764064Scg { 30864064Scg cvmx_gmxx_bpid_msk_t bpid_msk; 30964064Scg cvmx_gmxx_bpid_mapx_t bpid_map; 31064064Scg cvmx_gmxx_prtx_cfg_t gmxx_prtx_cfg; 31164163Snsayer cvmx_gmxx_txx_append_t gmxx_txx_append_cfg; 31264064Scg 313154066Sariff /* Setup PKIND */ 31464064Scg gmxx_prtx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(0, interface)); 31564064Scg gmxx_prtx_cfg.s.pknd = cvmx_helper_get_pknd(interface, 0); 31664064Scg cvmx_write_csr(CVMX_GMXX_PRTX_CFG(0, interface), gmxx_prtx_cfg.u64); 31764064Scg 31864064Scg /* Setup BPID */ 31964064Scg bpid_map.u64 = cvmx_read_csr(CVMX_GMXX_BPID_MAPX(0, interface)); 320160127Syongari bpid_map.s.val = 1; 321160127Syongari bpid_map.s.bpid = cvmx_helper_get_bpid(interface, 0); 32264846Scg cvmx_write_csr(CVMX_GMXX_BPID_MAPX(0, interface), bpid_map.u64); 323160127Syongari 32464846Scg bpid_msk.u64 = cvmx_read_csr(CVMX_GMXX_BPID_MSK(interface)); 32564163Snsayer bpid_msk.s.msk_or |= 1; 32664163Snsayer bpid_msk.s.msk_and &= ~1; 32764163Snsayer cvmx_write_csr(CVMX_GMXX_BPID_MSK(interface), bpid_msk.u64); 32864163Snsayer 32964163Snsayer /* CN68XX adds the padding and FCS in PKO, not GMX */ 33064163Snsayer gmxx_txx_append_cfg.u64 = cvmx_read_csr(CVMX_GMXX_TXX_APPEND(0, interface)); 33164163Snsayer gmxx_txx_append_cfg.s.fcs = 0; 33264163Snsayer gmxx_txx_append_cfg.s.pad = 0; 33364163Snsayer cvmx_write_csr(CVMX_GMXX_TXX_APPEND(0, interface), gmxx_txx_append_cfg.u64); 33464163Snsayer } 33564163Snsayer 33664064Scg __cvmx_helper_xaui_link_init(interface); 33764140Snsayer 33864140Snsayer return 0; 33964064Scg} 34064064Scg 34164064Scg/** 34264064Scg * @INTERNAL 34364064Scg * Return the link state of an IPD/PKO port as returned by 34464064Scg * auto negotiation. The result of this function may not match 34564064Scg * Octeon's link config if auto negotiation has changed since 34664064Scg * the last call to cvmx_helper_link_set(). 34764064Scg * 348154066Sariff * @param ipd_port IPD/PKO port to query 34964064Scg * 350154066Sariff * @return Link state 35164064Scg */ 35264064Scgcvmx_helper_link_info_t __cvmx_helper_xaui_link_get(int ipd_port) 35364064Scg{ 35464064Scg int interface = cvmx_helper_get_interface_num(ipd_port); 35564064Scg cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl; 35664064Scg cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl; 35764064Scg cvmx_pcsxx_status1_reg_t pcsxx_status1_reg; 35864064Scg cvmx_helper_link_info_t result; 35964064Scg 360154066Sariff gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); 36164064Scg gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); 362154066Sariff pcsxx_status1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_STATUS1_REG(interface)); 36364064Scg result.u64 = 0; 36464064Scg 36564064Scg /* Only return a link if both RX and TX are happy */ 36664064Scg if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0) && 36764064Scg (pcsxx_status1_reg.s.rcv_lnk == 1)) 36864064Scg { 369154066Sariff cvmx_pcsxx_misc_ctl_reg_t misc_ctl; 370154066Sariff result.s.link_up = 1; 37164064Scg result.s.full_duplex = 1; 37264064Scg if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 37364064Scg { 37464064Scg cvmx_mio_qlmx_cfg_t qlm_cfg; 37564064Scg int lanes; 37664064Scg int qlm = (interface == 1) ? 0 : interface; 37764064Scg 37864064Scg qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(qlm)); 37964064Scg result.s.speed = cvmx_qlm_get_gbaud_mhz(qlm) * 8 / 10; 38064064Scg lanes = (qlm_cfg.s.qlm_cfg == 7) ? 2 : 4; 38164064Scg result.s.speed *= lanes; 38264064Scg } 38364064Scg else if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 38464064Scg { 38564064Scg int qlm = cvmx_qlm_interface(interface); 38664064Scg result.s.speed = cvmx_qlm_get_gbaud_mhz(qlm) * 8 / 10; 38764064Scg result.s.speed *= 4; 38864064Scg } 38964064Scg else 39064064Scg result.s.speed = 10000; 39164064Scg misc_ctl.u64 = cvmx_read_csr(CVMX_PCSXX_MISC_CTL_REG(interface)); 39264064Scg if (misc_ctl.s.gmxeno) 39364064Scg __cvmx_helper_xaui_link_init(interface); 39464064Scg } 39564064Scg else 39664064Scg { 39764064Scg /* Disable GMX and PCSX interrupts. */ 39864064Scg cvmx_write_csr (CVMX_GMXX_RXX_INT_EN(0,interface), 0x0); 39964064Scg cvmx_write_csr (CVMX_GMXX_TX_INT_EN(interface), 0x0); 40064064Scg cvmx_write_csr (CVMX_PCSXX_INT_EN_REG(interface), 0x0); 40164064Scg } 40264064Scg return result; 40364064Scg} 40464064Scg 40564064Scg 40664064Scg/** 40764064Scg * @INTERNAL 40864064Scg * Configure an IPD/PKO port for the specified link state. This 40964064Scg * function does not influence auto negotiation at the PHY level. 41064064Scg * The passed link state must always match the link state returned 41164064Scg * by cvmx_helper_link_get(). It is normally best to use 41264064Scg * cvmx_helper_link_autoconf() instead. 41364064Scg * 41464064Scg * @param ipd_port IPD/PKO port to configure 41564064Scg * @param link_info The new link state 41664064Scg * 41764064Scg * @return Zero on success, negative on failure 41864064Scg */ 41964064Scgint __cvmx_helper_xaui_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 42064064Scg{ 42164064Scg int interface = cvmx_helper_get_interface_num(ipd_port); 42264064Scg cvmx_gmxx_tx_xaui_ctl_t gmxx_tx_xaui_ctl; 42364064Scg cvmx_gmxx_rx_xaui_ctl_t gmxx_rx_xaui_ctl; 42464064Scg 42564064Scg gmxx_tx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_TX_XAUI_CTL(interface)); 42664064Scg gmxx_rx_xaui_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RX_XAUI_CTL(interface)); 42764064Scg 42864064Scg /* If the link shouldn't be up, then just return */ 42964064Scg if (!link_info.s.link_up) 43064064Scg return 0; 431193640Sariff 432193640Sariff /* Do nothing if both RX and TX are happy */ 43364064Scg if ((gmxx_tx_xaui_ctl.s.ls == 0) && (gmxx_rx_xaui_ctl.s.status == 0)) 43464064Scg return 0; 43564140Snsayer 43664064Scg /* Bring the link up */ 43764064Scg return __cvmx_helper_xaui_link_init(interface); 43864163Snsayer} 43964163Snsayer 44064064Scg 44164064Scg/** 44264064Scg * @INTERNAL 44364064Scg * Configure a port for internal and/or external loopback. Internal loopback 44464064Scg * causes packets sent by the port to be received by Octeon. External loopback 44564064Scg * causes packets received from the wire to sent out again. 44664064Scg * 44764064Scg * @param ipd_port IPD/PKO port to loopback. 44864140Snsayer * @param enable_internal 44964064Scg * Non zero if you want internal loopback 45064064Scg * @param enable_external 45164064Scg * Non zero if you want external loopback 45264064Scg * 45364064Scg * @return Zero on success, negative on failure. 45464064Scg */ 45564064Scgextern int __cvmx_helper_xaui_configure_loopback(int ipd_port, int enable_internal, int enable_external) 45664064Scg{ 45764064Scg int interface = cvmx_helper_get_interface_num(ipd_port); 45864064Scg cvmx_pcsxx_control1_reg_t pcsxx_control1_reg; 45964064Scg cvmx_gmxx_xaui_ext_loopback_t gmxx_xaui_ext_loopback; 46064064Scg 46164064Scg /* Set the internal loop */ 46264064Scg pcsxx_control1_reg.u64 = cvmx_read_csr(CVMX_PCSXX_CONTROL1_REG(interface)); 46364064Scg pcsxx_control1_reg.s.loopbck1 = enable_internal; 46464064Scg cvmx_write_csr(CVMX_PCSXX_CONTROL1_REG(interface), pcsxx_control1_reg.u64); 46564064Scg 46664064Scg /* Set the external loop */ 46764140Snsayer gmxx_xaui_ext_loopback.u64 = cvmx_read_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface)); 46864064Scg gmxx_xaui_ext_loopback.s.en = enable_external; 46964064Scg cvmx_write_csr(CVMX_GMXX_XAUI_EXT_LOOPBACK(interface), gmxx_xaui_ext_loopback.u64); 47064064Scg 47164064Scg /* Take the link through a reset */ 47264064Scg return __cvmx_helper_xaui_link_init(interface); 47364064Scg} 47464064Scg 47564064Scg#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 47664064Scg 47764064Scg