1215976Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett 41215976Sjmallett 42215976Sjmallett 43215976Sjmallett 44215976Sjmallett 45215976Sjmallett 46215976Sjmallett/** 47215976Sjmallett * @file 48215976Sjmallett * 49215976Sjmallett * Functions for SRIO initialization, configuration, 50215976Sjmallett * and monitoring. 51215976Sjmallett * 52215976Sjmallett * <hr>$Revision: 41586 $<hr> 53215976Sjmallett */ 54215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 55215976Sjmallett#include <asm/octeon/cvmx.h> 56215976Sjmallett#include <asm/octeon/cvmx-config.h> 57215976Sjmallett#include <asm/octeon/cvmx-clock.h> 58215976Sjmallett#include <asm/octeon/cvmx-helper.h> 59232812Sjmallett#include <asm/octeon/cvmx-qlm.h> 60215976Sjmallett#include <asm/octeon/cvmx-srio.h> 61215976Sjmallett#include <asm/octeon/cvmx-pip-defs.h> 62215976Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 63215976Sjmallett#include <asm/octeon/cvmx-sriomaintx-defs.h> 64215976Sjmallett#include <asm/octeon/cvmx-dpi-defs.h> 65215976Sjmallett#else 66215990Sjmallett#if !defined(__FreeBSD__) || !defined(_KERNEL) 67215976Sjmallett#include "executive-config.h" 68215976Sjmallett#include "cvmx-config.h" 69215976Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 70215976Sjmallett 71215976Sjmallett#include "cvmx.h" 72215976Sjmallett#include "cvmx-helper.h" 73215976Sjmallett#include "cvmx-srio.h" 74215976Sjmallett#endif 75232812Sjmallett#include "cvmx-qlm.h" 76215990Sjmallett#else 77215990Sjmallett#include "cvmx.h" 78215990Sjmallett#include "cvmx-helper.h" 79232812Sjmallett#include "cvmx-qlm.h" 80215990Sjmallett#include "cvmx-srio.h" 81215976Sjmallett#endif 82215990Sjmallett#endif 83215976Sjmallett 84215976Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 85215976Sjmallett 86215976Sjmallett/** 87215976Sjmallett * @INTERNAL 88215976Sjmallett * Probe a SRIO interface and determine the number of ports 89215976Sjmallett * connected to it. The SRIO interface should still be down 90215976Sjmallett * after this call. 91215976Sjmallett * 92215976Sjmallett * @param interface Interface to probe 93215976Sjmallett * 94215976Sjmallett * @return Number of ports on the interface. Zero to disable. 95215976Sjmallett */ 96215976Sjmallettint __cvmx_helper_srio_probe(int interface) 97215976Sjmallett{ 98215976Sjmallett cvmx_sriox_status_reg_t srio0_status_reg; 99215976Sjmallett cvmx_sriox_status_reg_t srio1_status_reg; 100215976Sjmallett 101232812Sjmallett if (!octeon_has_feature(OCTEON_FEATURE_SRIO)) 102215976Sjmallett return 0; 103215976Sjmallett 104232812Sjmallett /* Read MIO_QLMX_CFG CSRs to find SRIO status. */ 105232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 106232812Sjmallett { 107232812Sjmallett int status = cvmx_qlm_get_status(0); 108232812Sjmallett int srio_port = interface - 4; 109232812Sjmallett switch(srio_port) 110232812Sjmallett { 111232812Sjmallett case 0: /* 1x4 lane */ 112232812Sjmallett if (status == 4) 113232812Sjmallett return 2; 114232812Sjmallett break; 115232812Sjmallett case 2: /* 2x2 lane */ 116232812Sjmallett if (status == 5) 117232812Sjmallett return 2; 118232812Sjmallett break; 119232812Sjmallett case 1: /* 4x1 long/short */ 120232812Sjmallett case 3: /* 4x1 long/short */ 121232812Sjmallett if (status == 6) 122232812Sjmallett return 2; 123232812Sjmallett break; 124232812Sjmallett } 125232812Sjmallett return 0; 126232812Sjmallett } 127232812Sjmallett 128215976Sjmallett srio0_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(0)); 129215976Sjmallett srio1_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(1)); 130215976Sjmallett if (srio0_status_reg.s.srio || srio1_status_reg.s.srio) 131215976Sjmallett return 2; 132215976Sjmallett else 133215976Sjmallett return 0; 134215976Sjmallett} 135215976Sjmallett 136215976Sjmallett 137215976Sjmallett/** 138215976Sjmallett * @INTERNAL 139215976Sjmallett * Bringup and enable SRIO interface. After this call packet 140215976Sjmallett * I/O should be fully functional. This is called with IPD 141215976Sjmallett * enabled but PKO disabled. 142215976Sjmallett * 143215976Sjmallett * @param interface Interface to bring up 144215976Sjmallett * 145215976Sjmallett * @return Zero on success, negative on failure 146215976Sjmallett */ 147215976Sjmallettint __cvmx_helper_srio_enable(int interface) 148215976Sjmallett{ 149215976Sjmallett int num_ports = cvmx_helper_ports_on_interface(interface); 150215976Sjmallett int index; 151215976Sjmallett cvmx_sriomaintx_core_enables_t sriomaintx_core_enables; 152215976Sjmallett cvmx_sriox_imsg_ctrl_t sriox_imsg_ctrl; 153232812Sjmallett cvmx_sriox_status_reg_t srio_status_reg; 154215976Sjmallett cvmx_dpi_ctl_t dpi_ctl; 155232812Sjmallett int srio_port = interface - 4; 156215976Sjmallett 157215976Sjmallett /* All SRIO ports have a cvmx_srio_rx_message_header_t header 158215976Sjmallett on them that must be skipped by IPD */ 159215976Sjmallett for (index=0; index<num_ports; index++) 160215976Sjmallett { 161215976Sjmallett cvmx_pip_prt_cfgx_t port_config; 162215976Sjmallett cvmx_sriox_omsg_portx_t sriox_omsg_portx; 163215976Sjmallett cvmx_sriox_omsg_sp_mrx_t sriox_omsg_sp_mrx; 164215976Sjmallett cvmx_sriox_omsg_fmp_mrx_t sriox_omsg_fmp_mrx; 165215976Sjmallett cvmx_sriox_omsg_nmp_mrx_t sriox_omsg_nmp_mrx; 166215976Sjmallett int ipd_port = cvmx_helper_get_ipd_port(interface, index); 167215976Sjmallett port_config.u64 = cvmx_read_csr(CVMX_PIP_PRT_CFGX(ipd_port)); 168215976Sjmallett /* Only change the skip if the user hasn't already set it */ 169215976Sjmallett if (!port_config.s.skip) 170215976Sjmallett { 171215976Sjmallett port_config.s.skip = sizeof(cvmx_srio_rx_message_header_t); 172215976Sjmallett cvmx_write_csr(CVMX_PIP_PRT_CFGX(ipd_port), port_config.u64); 173215976Sjmallett } 174215976Sjmallett 175215976Sjmallett /* Enable TX with PKO */ 176232812Sjmallett sriox_omsg_portx.u64 = cvmx_read_csr(CVMX_SRIOX_OMSG_PORTX(index, srio_port)); 177232812Sjmallett sriox_omsg_portx.s.port = (srio_port) * 2 + index; 178215976Sjmallett sriox_omsg_portx.s.enable = 1; 179232812Sjmallett cvmx_write_csr(CVMX_SRIOX_OMSG_PORTX(index, srio_port), sriox_omsg_portx.u64); 180215976Sjmallett 181215976Sjmallett /* Allow OMSG controller to send regardless of the state of any other 182215976Sjmallett controller. Allow messages to different IDs and MBOXes to go in 183215976Sjmallett parallel */ 184215976Sjmallett sriox_omsg_sp_mrx.u64 = 0; 185215976Sjmallett sriox_omsg_sp_mrx.s.xmbox_sp = 1; 186215976Sjmallett sriox_omsg_sp_mrx.s.ctlr_sp = 1; 187215976Sjmallett sriox_omsg_sp_mrx.s.ctlr_fmp = 1; 188215976Sjmallett sriox_omsg_sp_mrx.s.ctlr_nmp = 1; 189215976Sjmallett sriox_omsg_sp_mrx.s.id_sp = 1; 190215976Sjmallett sriox_omsg_sp_mrx.s.id_fmp = 1; 191215976Sjmallett sriox_omsg_sp_mrx.s.id_nmp = 1; 192215976Sjmallett sriox_omsg_sp_mrx.s.mbox_sp = 1; 193215976Sjmallett sriox_omsg_sp_mrx.s.mbox_fmp = 1; 194215976Sjmallett sriox_omsg_sp_mrx.s.mbox_nmp = 1; 195215976Sjmallett sriox_omsg_sp_mrx.s.all_psd = 1; 196232812Sjmallett cvmx_write_csr(CVMX_SRIOX_OMSG_SP_MRX(index, srio_port), sriox_omsg_sp_mrx.u64); 197215976Sjmallett 198215976Sjmallett /* Allow OMSG controller to send regardless of the state of any other 199215976Sjmallett controller. Allow messages to different IDs and MBOXes to go in 200215976Sjmallett parallel */ 201215976Sjmallett sriox_omsg_fmp_mrx.u64 = 0; 202215976Sjmallett sriox_omsg_fmp_mrx.s.ctlr_sp = 1; 203215976Sjmallett sriox_omsg_fmp_mrx.s.ctlr_fmp = 1; 204215976Sjmallett sriox_omsg_fmp_mrx.s.ctlr_nmp = 1; 205215976Sjmallett sriox_omsg_fmp_mrx.s.id_sp = 1; 206215976Sjmallett sriox_omsg_fmp_mrx.s.id_fmp = 1; 207215976Sjmallett sriox_omsg_fmp_mrx.s.id_nmp = 1; 208215976Sjmallett sriox_omsg_fmp_mrx.s.mbox_sp = 1; 209215976Sjmallett sriox_omsg_fmp_mrx.s.mbox_fmp = 1; 210215976Sjmallett sriox_omsg_fmp_mrx.s.mbox_nmp = 1; 211215976Sjmallett sriox_omsg_fmp_mrx.s.all_psd = 1; 212232812Sjmallett cvmx_write_csr(CVMX_SRIOX_OMSG_FMP_MRX(index, srio_port), sriox_omsg_fmp_mrx.u64); 213215976Sjmallett 214215976Sjmallett /* Once the first part of a message is accepted, always acept the rest 215215976Sjmallett of the message */ 216215976Sjmallett sriox_omsg_nmp_mrx.u64 = 0; 217215976Sjmallett sriox_omsg_nmp_mrx.s.all_sp = 1; 218215976Sjmallett sriox_omsg_nmp_mrx.s.all_fmp = 1; 219215976Sjmallett sriox_omsg_nmp_mrx.s.all_nmp = 1; 220232812Sjmallett cvmx_write_csr(CVMX_SRIOX_OMSG_NMP_MRX(index, srio_port), sriox_omsg_nmp_mrx.u64); 221215976Sjmallett 222215976Sjmallett } 223215976Sjmallett 224215976Sjmallett /* Choose the receive controller based on the mailbox */ 225232812Sjmallett sriox_imsg_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_CTRL(srio_port)); 226215976Sjmallett sriox_imsg_ctrl.s.prt_sel = 0; 227215976Sjmallett sriox_imsg_ctrl.s.mbox = 0xa; 228232812Sjmallett cvmx_write_csr(CVMX_SRIOX_IMSG_CTRL(srio_port), sriox_imsg_ctrl.u64); 229215976Sjmallett 230215976Sjmallett /* DPI must be enabled for us to RX messages */ 231215976Sjmallett dpi_ctl.u64 = cvmx_read_csr(CVMX_DPI_CTL); 232215976Sjmallett dpi_ctl.s.clk = 1; 233215976Sjmallett dpi_ctl.s.en = 1; 234215976Sjmallett cvmx_write_csr(CVMX_DPI_CTL, dpi_ctl.u64); 235215976Sjmallett 236232812Sjmallett /* Make sure register access is allowed */ 237232812Sjmallett srio_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port)); 238232812Sjmallett if (!srio_status_reg.s.access) 239232812Sjmallett return 0; 240232812Sjmallett 241215976Sjmallett /* Enable RX */ 242232812Sjmallett if (!cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 243232812Sjmallett CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &sriomaintx_core_enables.u32)) 244215976Sjmallett { 245215976Sjmallett sriomaintx_core_enables.s.imsg0 = 1; 246215976Sjmallett sriomaintx_core_enables.s.imsg1 = 1; 247232812Sjmallett cvmx_srio_config_write32(srio_port, 0, -1, 0, 0, 248232812Sjmallett CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), sriomaintx_core_enables.u32); 249215976Sjmallett } 250215976Sjmallett 251215976Sjmallett return 0; 252215976Sjmallett} 253215976Sjmallett 254215976Sjmallett/** 255215976Sjmallett * @INTERNAL 256215976Sjmallett * Return the link state of an IPD/PKO port as returned by SRIO link status. 257215976Sjmallett * 258215976Sjmallett * @param ipd_port IPD/PKO port to query 259215976Sjmallett * 260215976Sjmallett * @return Link state 261215976Sjmallett */ 262215976Sjmallettcvmx_helper_link_info_t __cvmx_helper_srio_link_get(int ipd_port) 263215976Sjmallett{ 264215976Sjmallett int interface = cvmx_helper_get_interface_num(ipd_port); 265215976Sjmallett int srio_port = interface - 4; 266215976Sjmallett cvmx_helper_link_info_t result; 267215976Sjmallett cvmx_sriox_status_reg_t srio_status_reg; 268215976Sjmallett cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat; 269215976Sjmallett cvmx_sriomaintx_port_0_ctl_t sriomaintx_port_0_ctl; 270215976Sjmallett cvmx_sriomaintx_port_0_ctl2_t sriomaintx_port_0_ctl2; 271215976Sjmallett 272215976Sjmallett result.u64 = 0; 273215976Sjmallett 274215976Sjmallett /* Make sure register access is allowed */ 275215976Sjmallett srio_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port)); 276215976Sjmallett if (!srio_status_reg.s.access) 277215976Sjmallett return result; 278215976Sjmallett 279215976Sjmallett /* Read the port link status */ 280215976Sjmallett if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 281215976Sjmallett CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port), 282215976Sjmallett &sriomaintx_port_0_err_stat.u32)) 283215976Sjmallett return result; 284215976Sjmallett 285215976Sjmallett /* Return if link is down */ 286215976Sjmallett if (!sriomaintx_port_0_err_stat.s.pt_ok) 287215976Sjmallett return result; 288215976Sjmallett 289215976Sjmallett /* Read the port link width and speed */ 290215976Sjmallett if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 291215976Sjmallett CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), 292215976Sjmallett &sriomaintx_port_0_ctl.u32)) 293215976Sjmallett return result; 294215976Sjmallett if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 295215976Sjmallett CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), 296215976Sjmallett &sriomaintx_port_0_ctl2.u32)) 297215976Sjmallett return result; 298215976Sjmallett 299215976Sjmallett /* Link is up */ 300215976Sjmallett result.s.full_duplex = 1; 301215976Sjmallett result.s.link_up = 1; 302215976Sjmallett switch (sriomaintx_port_0_ctl2.s.sel_baud) 303215976Sjmallett { 304215976Sjmallett case 1: 305215976Sjmallett result.s.speed = 1250; 306215976Sjmallett break; 307215976Sjmallett case 2: 308215976Sjmallett result.s.speed = 2500; 309215976Sjmallett break; 310215976Sjmallett case 3: 311215976Sjmallett result.s.speed = 3125; 312215976Sjmallett break; 313215976Sjmallett case 4: 314215976Sjmallett result.s.speed = 5000; 315215976Sjmallett break; 316215976Sjmallett case 5: 317215976Sjmallett result.s.speed = 6250; 318215976Sjmallett break; 319215976Sjmallett default: 320215976Sjmallett result.s.speed = 0; 321215976Sjmallett break; 322215976Sjmallett } 323215976Sjmallett switch (sriomaintx_port_0_ctl.s.it_width) 324215976Sjmallett { 325215976Sjmallett case 2: /* Four lanes */ 326215976Sjmallett result.s.speed += 40000; 327215976Sjmallett break; 328215976Sjmallett case 3: /* Two lanes */ 329215976Sjmallett result.s.speed += 20000; 330215976Sjmallett break; 331215976Sjmallett default: /* One lane */ 332215976Sjmallett result.s.speed += 10000; 333215976Sjmallett break; 334215976Sjmallett } 335215976Sjmallett return result; 336215976Sjmallett} 337215976Sjmallett 338215976Sjmallett/** 339215976Sjmallett * @INTERNAL 340215976Sjmallett * Configure an IPD/PKO port for the specified link state. This 341215976Sjmallett * function does not influence auto negotiation at the PHY level. 342215976Sjmallett * The passed link state must always match the link state returned 343215976Sjmallett * by cvmx_helper_link_get(). It is normally best to use 344215976Sjmallett * cvmx_helper_link_autoconf() instead. 345215976Sjmallett * 346215976Sjmallett * @param ipd_port IPD/PKO port to configure 347215976Sjmallett * @param link_info The new link state 348215976Sjmallett * 349215976Sjmallett * @return Zero on success, negative on failure 350215976Sjmallett */ 351215976Sjmallettint __cvmx_helper_srio_link_set(int ipd_port, cvmx_helper_link_info_t link_info) 352215976Sjmallett{ 353215976Sjmallett return 0; 354215976Sjmallett} 355215976Sjmallett 356215976Sjmallett#endif /* CVMX_ENABLE_PKO_FUNCTIONS */ 357215976Sjmallett 358