1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (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 Inc. 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 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40 41 42 43 44/** 45 * @file 46 * 47 * Functions for SPI initialization, configuration, 48 * and monitoring. 49 * 50 * <hr>$Revision: 70030 $<hr> 51 */ 52#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 53#include <asm/octeon/cvmx.h> 54#include <asm/octeon/cvmx-config.h> 55#ifdef CVMX_ENABLE_PKO_FUNCTIONS 56#include <asm/octeon/cvmx-spi.h> 57#include <asm/octeon/cvmx-helper.h> 58#endif 59#include <asm/octeon/cvmx-pko-defs.h> 60#include <asm/octeon/cvmx-pip-defs.h> 61#else 62#if !defined(__FreeBSD__) || !defined(_KERNEL) 63#include "executive-config.h" 64#include "cvmx-config.h" 65#ifdef CVMX_ENABLE_PKO_FUNCTIONS 66 67#include "cvmx.h" 68#include "cvmx-spi.h" 69#include "cvmx-sysinfo.h" 70#include "cvmx-helper.h" 71#endif 72#else 73#include "cvmx.h" 74#include "cvmx-spi.h" 75#include "cvmx-sysinfo.h" 76#include "cvmx-helper.h" 77#endif 78#endif 79 80#ifdef CVMX_ENABLE_PKO_FUNCTIONS 81 82/* CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI initialization 83 routines wait for SPI training. You can override the value using 84 executive-config.h if necessary */ 85#ifndef CVMX_HELPER_SPI_TIMEOUT 86#define CVMX_HELPER_SPI_TIMEOUT 10 87#endif 88 89int __cvmx_helper_spi_enumerate(int interface) 90{ 91#if defined(OCTEON_VENDOR_LANNER) 92 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_LANNER_MR955) 93 { 94 cvmx_pko_reg_crc_enable_t enable; 95 96 enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); 97 enable.s.enable &= 0xffff << (16 - (interface*16)); 98 cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); 99 100 if (interface == 1) 101 return 12; 102 /* XXX This is not entirely true. */ 103 return 0; 104 } 105#endif 106 107#if defined(OCTEON_VENDOR_RADISYS) 108 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE) { 109 if (interface == 0) 110 return 13; 111 if (interface == 1) 112 return 8; 113 return 0; 114 } 115#endif 116 117 if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && 118 cvmx_spi4000_is_present(interface)) 119 return 10; 120 else 121 return 16; 122} 123 124/** 125 * @INTERNAL 126 * Probe a SPI interface and determine the number of ports 127 * connected to it. The SPI interface should still be down after 128 * this call. 129 * 130 * @param interface Interface to probe 131 * 132 * @return Number of ports on the interface. Zero to disable. 133 */ 134int __cvmx_helper_spi_probe(int interface) 135{ 136 int num_ports = __cvmx_helper_spi_enumerate(interface); 137 138 if (num_ports == 16) { 139 cvmx_pko_reg_crc_enable_t enable; 140 /* 141 * Unlike the SPI4000, most SPI devices don't 142 * automatically put on the L2 CRC. For everything 143 * except for the SPI4000 have PKO append the L2 CRC 144 * to the packet 145 */ 146 enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); 147 enable.s.enable |= 0xffff << (interface*16); 148 cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); 149 } 150 __cvmx_helper_setup_gmx(interface, num_ports); 151 return num_ports; 152} 153 154 155/** 156 * @INTERNAL 157 * Bringup and enable a SPI interface. After this call packet I/O 158 * should be fully functional. This is called with IPD enabled but 159 * PKO disabled. 160 * 161 * @param interface Interface to bring up 162 * 163 * @return Zero on success, negative on failure 164 */ 165int __cvmx_helper_spi_enable(int interface) 166{ 167 /* Normally the ethernet L2 CRC is checked and stripped in the GMX block. 168 When you are using SPI, this isn' the case and IPD needs to check 169 the L2 CRC */ 170 int num_ports = cvmx_helper_ports_on_interface(interface); 171 int ipd_port; 172 for (ipd_port=interface*16; ipd_port<interface*16+num_ports; ipd_port++) 173 { 174 cvmx_pip_prt_cfgx_t port_config; 175 port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 176 port_config.s.crc_en = 1; 177#ifdef OCTEON_VENDOR_RADISYS 178 /* 179 * Incoming packets on the RSYS4GBE have the FCS stripped. 180 */ 181 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_RADISYS_RSYS4GBE) 182 port_config.s.crc_en = 0; 183#endif 184 cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64); 185 } 186 187 if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 188 { 189 cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX, CVMX_HELPER_SPI_TIMEOUT, num_ports); 190 if (cvmx_spi4000_is_present(interface)) 191 cvmx_spi4000_initialize(interface); 192 } 193 return 0; 194} 195 196/** 197 * @INTERNAL 198 * Return the link state of an IPD/PKO port as returned by 199 * auto negotiation. The result of this function may not match 200 * Octeon's link config if auto negotiation has changed since 201 * the last call to cvmx_helper_link_set(). 202 * 203 * @param ipd_port IPD/PKO port to query 204 * 205 * @return Link state 206 */ 207cvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port) 208{ 209 cvmx_helper_link_info_t result; 210 int interface = cvmx_helper_get_interface_num(ipd_port); 211 int index = cvmx_helper_get_interface_index_num(ipd_port); 212 result.u64 = 0; 213 214 if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 215 { 216 /* The simulator gives you a simulated full duplex link */ 217 result.s.link_up = 1; 218 result.s.full_duplex = 1; 219 result.s.speed = 10000; 220 } 221 else if (cvmx_spi4000_is_present(interface)) 222 { 223 cvmx_gmxx_rxx_rx_inbnd_t inband = cvmx_spi4000_check_speed(interface, index); 224 result.s.link_up = inband.s.status; 225 result.s.full_duplex = inband.s.duplex; 226 switch (inband.s.speed) 227 { 228 case 0: /* 10 Mbps */ 229 result.s.speed = 10; 230 break; 231 case 1: /* 100 Mbps */ 232 result.s.speed = 100; 233 break; 234 case 2: /* 1 Gbps */ 235 result.s.speed = 1000; 236 break; 237 case 3: /* Illegal */ 238 result.s.speed = 0; 239 result.s.link_up = 0; 240 break; 241 } 242 } 243 else 244 { 245 /* For generic SPI we can't determine the link, just return some 246 sane results */ 247 result.s.link_up = 1; 248 result.s.full_duplex = 1; 249 result.s.speed = 10000; 250 } 251 return result; 252} 253 254 255/** 256 * @INTERNAL 257 * Configure an IPD/PKO port for the specified link state. This 258 * function does not influence auto negotiation at the PHY level. 259 * The passed link state must always match the link state returned 260 * by cvmx_helper_link_get(). It is normally best to use 261 * cvmx_helper_link_autoconf() instead. 262 * 263 * @param ipd_port IPD/PKO port to configure 264 * @param link_info The new link state 265 * 266 * @return Zero on success, negative on failure 267 */ 268int __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 269{ 270 /* Nothing to do. If we have a SPI4000 then the setup was already performed 271 by cvmx_spi4000_check_speed(). If not then there isn't any link 272 info */ 273 return 0; 274} 275 276#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 277 278