/***********************license start*************** * Copyright (c) 2003-2008 Cavium Networks (support@cavium.com). All rights * reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of Cavium Networks nor the names of * its contributors may be used to endorse or promote products * derived from this software without specific prior written * permission. * * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS * OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH * RESPECT TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET * POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT * OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. * * * For any questions regarding licensing please contact marketing@caviumnetworks.com * ***********************license end**************************************/ /** * @file * * Functions for RGMII/GMII/MII initialization, configuration, * and monitoring. * *
$Revision: 42417 $
*/ #include "cvmx.h" #include "cvmx-sysinfo.h" #include "cvmx-mdio.h" #include "cvmx-pko.h" #include "cvmx-helper.h" #include "cvmx-helper-board.h" #ifdef CVMX_ENABLE_PKO_FUNCTIONS /** * @INTERNAL * Probe RGMII ports and determine the number present * * @param interface Interface to probe * * @return Number of RGMII/GMII/MII ports (0-4). */ int __cvmx_helper_rgmii_probe(int interface) { int num_ports = 0; cvmx_gmxx_inf_mode_t mode; mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); if (mode.s.type) { if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { cvmx_dprintf("ERROR: RGMII initialize called in SPI interface\n"); } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { /* On these chips "type" says we're in GMII/MII mode. This limits us to 2 ports */ num_ports = 2; } else { cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", __FUNCTION__); } } else { if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { num_ports = 4; } else if (OCTEON_IS_MODEL(OCTEON_CN31XX) || OCTEON_IS_MODEL(OCTEON_CN30XX) || OCTEON_IS_MODEL(OCTEON_CN50XX)) { num_ports = 3; } else { cvmx_dprintf("ERROR: Unsupported Octeon model in %s\n", __FUNCTION__); } } return num_ports; } /** * Put an RGMII interface in loopback mode. Internal packets sent * out will be received back again on the same port. Externally * received packets will echo back out. * * @param port IPD port number to loop. */ void cvmx_helper_rgmii_internal_loopback(int port) { int interface = (port >> 4) & 1; int index = port & 0xf; uint64_t tmp; cvmx_gmxx_prtx_cfg_t gmx_cfg; gmx_cfg.u64 = 0; gmx_cfg.s.duplex = 1; gmx_cfg.s.slottime = 1; gmx_cfg.s.speed = 1; cvmx_write_csr(CVMX_GMXX_TXX_CLK(index, interface), 1); cvmx_write_csr(CVMX_GMXX_TXX_SLOT(index, interface), 0x200); cvmx_write_csr(CVMX_GMXX_TXX_BURST(index, interface), 0x2000); cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); tmp = cvmx_read_csr(CVMX_ASXX_PRT_LOOP(interface)); cvmx_write_csr(CVMX_ASXX_PRT_LOOP(interface), (1 << index) | tmp); tmp = cvmx_read_csr(CVMX_ASXX_TX_PRT_EN(interface)); cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), (1 << index) | tmp); tmp = cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)); cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), (1 << index) | tmp); gmx_cfg.s.en = 1; cvmx_write_csr(CVMX_GMXX_PRTX_CFG(index, interface), gmx_cfg.u64); } /** * @INTERNAL * Configure all of the ASX, GMX, and PKO regsiters required * to get RGMII to function on the supplied interface. * * @param interface PKO Interface to configure (0 or 1) * * @return Zero on success */ int __cvmx_helper_rgmii_enable(int interface) { int num_ports = cvmx_helper_ports_on_interface(interface); int port; cvmx_sysinfo_t *sys_info_ptr = cvmx_sysinfo_get(); cvmx_gmxx_inf_mode_t mode; cvmx_asxx_tx_prt_en_t asx_tx; cvmx_asxx_rx_prt_en_t asx_rx; mode.u64 = cvmx_read_csr(CVMX_GMXX_INF_MODE(interface)); if (mode.s.en == 0) return -1; if ((OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) && mode.s.type == 1) /* Ignore SPI interfaces */ return -1; /* Configure the ASX registers needed to use the RGMII ports */ asx_tx.u64 = 0; asx_tx.s.prt_en = cvmx_build_mask(num_ports); cvmx_write_csr(CVMX_ASXX_TX_PRT_EN(interface), asx_tx.u64); asx_rx.u64 = 0; asx_rx.s.prt_en = cvmx_build_mask(num_ports); cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), asx_rx.u64); /* Configure the GMX registers needed to use the RGMII ports */ for (port=0; portcpu_clock_hz); else { /* Configure more flexible RGMII preamble checking. Pass 1 doesn't support this feature. */ cvmx_gmxx_rxx_frm_ctl_t frm_ctl; frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface)); frm_ctl.s.pre_free = 1; /* New field, so must be compile time */ cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(port, interface), frm_ctl.u64); } /* Each pause frame transmitted will ask for about 10M bit times before resume. If buffer space comes available before that time has expired, an XON pause frame (0 time) will be transmitted to restart the flow. */ cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_TIME(port, interface), 20000); cvmx_write_csr(CVMX_GMXX_TXX_PAUSE_PKT_INTERVAL(port, interface), 19000); /* * Board types we have to know at compile-time. */ #if defined(OCTEON_BOARD_CAPK_0100ND) cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 26); cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 26); #else /* * Vendor-defined board types. */ #if defined(OCTEON_VENDOR_LANNER) switch (cvmx_sysinfo_get()->board_type) { case CVMX_BOARD_TYPE_CUST_LANNER_MR320: if (port == 0) { cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 4); } else { cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 7); } cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 0); break; } #else /* * For board types we can determine at runtime. */ if (OCTEON_IS_MODEL(OCTEON_CN50XX)) { cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 16); cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 16); } else { cvmx_write_csr(CVMX_ASXX_TX_CLK_SETX(port, interface), 24); cvmx_write_csr(CVMX_ASXX_RX_CLK_SETX(port, interface), 24); } #endif #endif } __cvmx_helper_setup_gmx(interface, num_ports); /* enable the ports now */ for (port=0; portboard_type == CVMX_BOARD_TYPE_SIM) return 0; /* Read the current settings so we know the current enable state */ original_gmx_cfg.u64 = cvmx_read_csr(CVMX_GMXX_PRTX_CFG(index, interface)); new_gmx_cfg = original_gmx_cfg; /* Disable the lowest level RX */ cvmx_write_csr(CVMX_ASXX_RX_PRT_EN(interface), cvmx_read_csr(CVMX_ASXX_RX_PRT_EN(interface)) & ~(1<