1210284Sjmallett/***********************license start*************** 2215990Sjmallett * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18215990Sjmallett * * Neither the name of Cavium Networks nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29215990Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett/** 45210284Sjmallett * @file 46210284Sjmallett * 47210284Sjmallett * Functions for SPI initialization, configuration, 48210284Sjmallett * and monitoring. 49210284Sjmallett * 50215990Sjmallett * <hr>$Revision: 49448 $<hr> 51210284Sjmallett */ 52215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 53215990Sjmallett#include <asm/octeon/cvmx.h> 54215990Sjmallett#include <asm/octeon/cvmx-config.h> 55215990Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 56215990Sjmallett#include <asm/octeon/cvmx-spi.h> 57215990Sjmallett#include <asm/octeon/cvmx-helper.h> 58215990Sjmallett#endif 59215990Sjmallett#include <asm/octeon/cvmx-pko-defs.h> 60215990Sjmallett#include <asm/octeon/cvmx-pip-defs.h> 61215990Sjmallett#else 62215990Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 63215990Sjmallett#include "executive-config.h" 64215990Sjmallett#include "cvmx-config.h" 65215990Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 66215990Sjmallett 67210284Sjmallett#include "cvmx.h" 68210284Sjmallett#include "cvmx-spi.h" 69210284Sjmallett#include "cvmx-sysinfo.h" 70210284Sjmallett#include "cvmx-helper.h" 71215990Sjmallett#endif 72215990Sjmallett#else 73215990Sjmallett#include "cvmx.h" 74215990Sjmallett#include "cvmx-spi.h" 75215990Sjmallett#include "cvmx-sysinfo.h" 76215990Sjmallett#include "cvmx-helper.h" 77215990Sjmallett#endif 78215990Sjmallett#endif 79210284Sjmallett 80210311Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 81215990Sjmallett 82210284Sjmallett/* CVMX_HELPER_SPI_TIMEOUT is used to determine how long the SPI initialization 83210284Sjmallett routines wait for SPI training. You can override the value using 84210284Sjmallett executive-config.h if necessary */ 85210284Sjmallett#ifndef CVMX_HELPER_SPI_TIMEOUT 86210284Sjmallett#define CVMX_HELPER_SPI_TIMEOUT 10 87210284Sjmallett#endif 88210284Sjmallett 89210284Sjmallett 90210284Sjmallett/** 91210284Sjmallett * @INTERNAL 92210284Sjmallett * Probe a SPI interface and determine the number of ports 93210284Sjmallett * connected to it. The SPI interface should still be down after 94210284Sjmallett * this call. 95210284Sjmallett * 96210284Sjmallett * @param interface Interface to probe 97210284Sjmallett * 98210284Sjmallett * @return Number of ports on the interface. Zero to disable. 99210284Sjmallett */ 100210284Sjmallettint __cvmx_helper_spi_probe(int interface) 101210284Sjmallett{ 102210284Sjmallett int num_ports = 0; 103210284Sjmallett 104210284Sjmallett if ((cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) && 105210284Sjmallett cvmx_spi4000_is_present(interface)) 106210284Sjmallett { 107210284Sjmallett num_ports = 10; 108210284Sjmallett } 109212844Sjmallett#if defined(OCTEON_VENDOR_LANNER) 110212844Sjmallett else if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_CUST_LANNER_MR955) 111212844Sjmallett { 112212844Sjmallett cvmx_pko_reg_crc_enable_t enable; 113212844Sjmallett if (interface == 1) { 114212844Sjmallett num_ports = 12; 115212844Sjmallett } else { 116212844Sjmallett /* XXX This is not entirely true. */ 117212844Sjmallett num_ports = 0; 118212844Sjmallett } 119212844Sjmallett enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); 120212844Sjmallett enable.s.enable &= 0xffff << (16 - (interface*16)); 121212844Sjmallett cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); 122212844Sjmallett } 123212844Sjmallett#endif 124210284Sjmallett else 125210284Sjmallett { 126210284Sjmallett cvmx_pko_reg_crc_enable_t enable; 127210284Sjmallett num_ports = 16; 128210284Sjmallett /* Unlike the SPI4000, most SPI devices don't automatically 129210284Sjmallett put on the L2 CRC. For everything except for the SPI4000 130210284Sjmallett have PKO append the L2 CRC to the packet */ 131210284Sjmallett enable.u64 = cvmx_read_csr(CVMX_PKO_REG_CRC_ENABLE); 132210284Sjmallett enable.s.enable |= 0xffff << (interface*16); 133210284Sjmallett cvmx_write_csr(CVMX_PKO_REG_CRC_ENABLE, enable.u64); 134210284Sjmallett } 135210284Sjmallett __cvmx_helper_setup_gmx(interface, num_ports); 136210284Sjmallett return num_ports; 137210284Sjmallett} 138210284Sjmallett 139210284Sjmallett 140210284Sjmallett/** 141210284Sjmallett * @INTERNAL 142210284Sjmallett * Bringup and enable a SPI interface. After this call packet I/O 143210284Sjmallett * should be fully functional. This is called with IPD enabled but 144210284Sjmallett * PKO disabled. 145210284Sjmallett * 146210284Sjmallett * @param interface Interface to bring up 147210284Sjmallett * 148210284Sjmallett * @return Zero on success, negative on failure 149210284Sjmallett */ 150210284Sjmallettint __cvmx_helper_spi_enable(int interface) 151210284Sjmallett{ 152210284Sjmallett /* Normally the ethernet L2 CRC is checked and stripped in the GMX block. 153210284Sjmallett When you are using SPI, this isn' the case and IPD needs to check 154210284Sjmallett the L2 CRC */ 155210284Sjmallett int num_ports = cvmx_helper_ports_on_interface(interface); 156210284Sjmallett int ipd_port; 157210284Sjmallett for (ipd_port=interface*16; ipd_port<interface*16+num_ports; ipd_port++) 158210284Sjmallett { 159215990Sjmallett cvmx_pip_prt_cfgx_t port_config; 160210284Sjmallett port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 161210284Sjmallett port_config.s.crc_en = 1; 162210284Sjmallett cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64); 163210284Sjmallett } 164210284Sjmallett 165210284Sjmallett if (cvmx_sysinfo_get()->board_type != CVMX_BOARD_TYPE_SIM) 166210284Sjmallett { 167210284Sjmallett cvmx_spi_start_interface(interface, CVMX_SPI_MODE_DUPLEX, CVMX_HELPER_SPI_TIMEOUT, num_ports); 168210284Sjmallett if (cvmx_spi4000_is_present(interface)) 169210284Sjmallett cvmx_spi4000_initialize(interface); 170210284Sjmallett } 171210284Sjmallett return 0; 172210284Sjmallett} 173210284Sjmallett 174210284Sjmallett/** 175210284Sjmallett * @INTERNAL 176210284Sjmallett * Return the link state of an IPD/PKO port as returned by 177210284Sjmallett * auto negotiation. The result of this function may not match 178210284Sjmallett * Octeon's link config if auto negotiation has changed since 179210284Sjmallett * the last call to cvmx_helper_link_set(). 180210284Sjmallett * 181210284Sjmallett * @param ipd_port IPD/PKO port to query 182210284Sjmallett * 183210284Sjmallett * @return Link state 184210284Sjmallett */ 185210284Sjmallettcvmx_helper_link_info_t __cvmx_helper_spi_link_get(int ipd_port) 186210284Sjmallett{ 187210284Sjmallett cvmx_helper_link_info_t result; 188210284Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 189210284Sjmallett int index = cvmx_helper_get_interface_index_num(ipd_port); 190210284Sjmallett result.u64 = 0; 191210284Sjmallett 192210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_SIM) 193210284Sjmallett { 194210284Sjmallett /* The simulator gives you a simulated full duplex link */ 195210284Sjmallett result.s.link_up = 1; 196210284Sjmallett result.s.full_duplex = 1; 197210284Sjmallett result.s.speed = 10000; 198210284Sjmallett } 199210284Sjmallett else if (cvmx_spi4000_is_present(interface)) 200210284Sjmallett { 201210284Sjmallett cvmx_gmxx_rxx_rx_inbnd_t inband = cvmx_spi4000_check_speed(interface, index); 202210284Sjmallett result.s.link_up = inband.s.status; 203210284Sjmallett result.s.full_duplex = inband.s.duplex; 204210284Sjmallett switch (inband.s.speed) 205210284Sjmallett { 206210284Sjmallett case 0: /* 10 Mbps */ 207210284Sjmallett result.s.speed = 10; 208210284Sjmallett break; 209210284Sjmallett case 1: /* 100 Mbps */ 210210284Sjmallett result.s.speed = 100; 211210284Sjmallett break; 212210284Sjmallett case 2: /* 1 Gbps */ 213210284Sjmallett result.s.speed = 1000; 214210284Sjmallett break; 215210284Sjmallett case 3: /* Illegal */ 216210284Sjmallett result.s.speed = 0; 217210284Sjmallett result.s.link_up = 0; 218210284Sjmallett break; 219210284Sjmallett } 220210284Sjmallett } 221210284Sjmallett else 222210284Sjmallett { 223210284Sjmallett /* For generic SPI we can't determine the link, just return some 224210284Sjmallett sane results */ 225210284Sjmallett result.s.link_up = 1; 226210284Sjmallett result.s.full_duplex = 1; 227210284Sjmallett result.s.speed = 10000; 228210284Sjmallett } 229210284Sjmallett return result; 230210284Sjmallett} 231210284Sjmallett 232210284Sjmallett 233210284Sjmallett/** 234210284Sjmallett * @INTERNAL 235210284Sjmallett * Configure an IPD/PKO port for the specified link state. This 236210284Sjmallett * function does not influence auto negotiation at the PHY level. 237210284Sjmallett * The passed link state must always match the link state returned 238210284Sjmallett * by cvmx_helper_link_get(). It is normally best to use 239210284Sjmallett * cvmx_helper_link_autoconf() instead. 240210284Sjmallett * 241210284Sjmallett * @param ipd_port IPD/PKO port to configure 242210284Sjmallett * @param link_info The new link state 243210284Sjmallett * 244210284Sjmallett * @return Zero on success, negative on failure 245210284Sjmallett */ 246210284Sjmallettint __cvmx_helper_spi_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 247210284Sjmallett{ 248210284Sjmallett /* Nothing to do. If we have a SPI4000 then the setup was already performed 249210284Sjmallett by cvmx_spi4000_check_speed(). If not then there isn't any link 250210284Sjmallett info */ 251210284Sjmallett return 0; 252210284Sjmallett} 253210284Sjmallett 254210284Sjmallett#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 255210284Sjmallett 256