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 * @file 44215976Sjmallett * 45215976Sjmallett * Interface to SRIO 46215976Sjmallett * 47215976Sjmallett * <hr>$Revision: 41586 $<hr> 48215976Sjmallett */ 49215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 50215976Sjmallett#include <asm/octeon/cvmx.h> 51215976Sjmallett#include <asm/octeon/cvmx-srio.h> 52215976Sjmallett#include <asm/octeon/cvmx-clock.h> 53215976Sjmallett#include <asm/octeon/cvmx-atomic.h> 54215976Sjmallett#ifdef CONFIG_CAVIUM_DECODE_RSL 55215976Sjmallett#include <asm/octeon/cvmx-error.h> 56215976Sjmallett#endif 57215976Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 58215976Sjmallett#include <asm/octeon/cvmx-sriomaintx-defs.h> 59215976Sjmallett#include <asm/octeon/cvmx-sli-defs.h> 60215976Sjmallett#include <asm/octeon/cvmx-dpi-defs.h> 61215976Sjmallett#include <asm/octeon/cvmx-pexp-defs.h> 62215976Sjmallett#include <asm/octeon/cvmx-helper.h> 63232812Sjmallett#include <asm/octeon/cvmx-qlm.h> 64215976Sjmallett#else 65215976Sjmallett#include "cvmx.h" 66215976Sjmallett#include "cvmx-srio.h" 67215976Sjmallett#include "cvmx-clock.h" 68215976Sjmallett#include "cvmx-helper.h" 69215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 70215976Sjmallett#include "cvmx-atomic.h" 71232816Sjmallett#if !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 72215976Sjmallett#include "cvmx-error.h" 73232816Sjmallett#endif 74215976Sjmallett#include "cvmx-helper-errata.h" 75215976Sjmallett#endif 76232812Sjmallett#include "cvmx-qlm.h" 77232812Sjmallett#include "cvmx-helper.h" 78215976Sjmallett#endif 79215976Sjmallett 80215976Sjmallett#define CVMX_SRIO_CONFIG_TIMEOUT 10000 /* 10ms */ 81215976Sjmallett#define CVMX_SRIO_DOORBELL_TIMEOUT 10000 /* 10ms */ 82215976Sjmallett#define CVMX_SRIO_CONFIG_PRIORITY 0 83215976Sjmallett#define ULL unsigned long long 84215976Sjmallett 85215976Sjmalletttypedef union 86215976Sjmallett{ 87215976Sjmallett uint64_t u64; 88215976Sjmallett struct 89215976Sjmallett { 90232812Sjmallett#ifdef __BIG_ENDIAN_BITFIELD 91215976Sjmallett uint64_t upper : 2; /* Normally 2 for XKPHYS */ 92215976Sjmallett uint64_t reserved_49_61 : 13; /* Must be zero */ 93215976Sjmallett uint64_t io : 1; /* 1 for IO space access */ 94215976Sjmallett uint64_t did : 5; /* DID = 3 */ 95215976Sjmallett uint64_t subdid : 3; /* SubDID = 3-6 */ 96215976Sjmallett uint64_t reserved_36_39 : 4; /* Must be zero */ 97215976Sjmallett uint64_t se : 2; /* SubDID extender */ 98215976Sjmallett uint64_t reserved_32_33 : 2; /* Must be zero */ 99215976Sjmallett uint64_t hopcount : 8; /* Hopcount */ 100215976Sjmallett uint64_t address : 24; /* Mem address */ 101215976Sjmallett#else 102215976Sjmallett uint64_t address : 24; 103215976Sjmallett uint64_t hopcount : 8; 104215976Sjmallett uint64_t reserved_32_33 : 2; 105215976Sjmallett uint64_t se : 2; 106215976Sjmallett uint64_t reserved_36_39 : 4; 107215976Sjmallett uint64_t subdid : 3; 108215976Sjmallett uint64_t did : 5; 109215976Sjmallett uint64_t io : 1; 110215976Sjmallett uint64_t reserved_49_61 : 13; 111215976Sjmallett uint64_t upper : 2; 112215976Sjmallett#endif 113215976Sjmallett } config; 114215976Sjmallett struct 115215976Sjmallett { 116232812Sjmallett#ifdef __BIG_ENDIAN_BITFIELD 117215976Sjmallett uint64_t upper : 2; /* Normally 2 for XKPHYS */ 118215976Sjmallett uint64_t reserved_49_61 : 13; /* Must be zero */ 119215976Sjmallett uint64_t io : 1; /* 1 for IO space access */ 120215976Sjmallett uint64_t did : 5; /* DID = 3 */ 121215976Sjmallett uint64_t subdid : 3; /* SubDID = 3-6 */ 122215976Sjmallett uint64_t reserved_36_39 : 4; /* Must be zero */ 123215976Sjmallett uint64_t se : 2; /* SubDID extender */ 124215976Sjmallett uint64_t address : 34; /* Mem address */ 125215976Sjmallett#else 126215976Sjmallett uint64_t address : 34; 127215976Sjmallett uint64_t se : 2; 128215976Sjmallett uint64_t reserved_36_39 : 4; 129215976Sjmallett uint64_t subdid : 3; 130215976Sjmallett uint64_t did : 5; 131215976Sjmallett uint64_t io : 1; 132215976Sjmallett uint64_t reserved_49_61 : 13; 133215976Sjmallett uint64_t upper : 2; 134215976Sjmallett#endif 135215976Sjmallett } mem; 136215976Sjmallett} cvmx_sli_address_t; 137215976Sjmallett 138215976Sjmalletttypedef struct 139215976Sjmallett{ 140215976Sjmallett cvmx_srio_initialize_flags_t flags; 141215976Sjmallett int32_t subidx_ref_count[16]; /* Reference count for SLI_MEM_ACCESS_SUBID[12-27]. Index=X-12 */ 142215976Sjmallett int32_t s2m_ref_count[16]; /* Reference count for SRIOX_S2M_TYPE[0-15]. */ 143215976Sjmallett} __cvmx_srio_state_t; 144215976Sjmallett 145232812Sjmallettstatic CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[4]; 146215976Sjmallett 147215976Sjmallett 148215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 149215976Sjmallett/** 150215976Sjmallett * @INTERNAL 151215976Sjmallett * Allocate a SRIOX_S2M_TYPEX register for mapping a remote SRIO 152215976Sjmallett * device's address range into Octeons SLI address space. Reference 153215976Sjmallett * counting is used to allow sharing of duplicate setups. The current 154215976Sjmallett * implementation treats reads and writes as paired, but this could be 155215976Sjmallett * changed if we have trouble running out of indexes. 156215976Sjmallett * 157215976Sjmallett * @param srio_port SRIO port device is on 158215976Sjmallett * @param s2m SRIOX_S2M_TYPEX setup required 159215976Sjmallett * 160215976Sjmallett * @return Index of CSR, or negative on failure 161215976Sjmallett */ 162215976Sjmallettstatic int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m) 163215976Sjmallett{ 164215976Sjmallett int s2m_index; 165215976Sjmallett /* Search through the S2M_TYPE registers looking for an unsed one or one 166215976Sjmallett setup the way we need it */ 167215976Sjmallett for (s2m_index=0; s2m_index<16; s2m_index++) 168215976Sjmallett { 169215976Sjmallett /* Increment ref count by 2 since we count read and write 170215976Sjmallett independently. We might need a more complicated search in the 171215976Sjmallett future */ 172215976Sjmallett int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], 2); 173215976Sjmallett if (ref_count == 0) 174215976Sjmallett { 175215976Sjmallett /* Unused location. Write our value */ 176215976Sjmallett cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64); 177232812Sjmallett /* Read back to make sure the update is complete */ 178232812Sjmallett cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)); 179215976Sjmallett return s2m_index; 180215976Sjmallett } 181215976Sjmallett else 182215976Sjmallett { 183215976Sjmallett /* In use, see if we can use it */ 184215976Sjmallett if (cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)) == s2m.u64) 185215976Sjmallett return s2m_index; 186215976Sjmallett else 187215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], -2); 188215976Sjmallett } 189215976Sjmallett } 190215976Sjmallett cvmx_dprintf("SRIO%d: Unable to find free SRIOX_S2M_TYPEX\n", srio_port); 191215976Sjmallett return -1; 192215976Sjmallett} 193215976Sjmallett 194215976Sjmallett 195215976Sjmallett/** 196215976Sjmallett * @INTERNAL 197215976Sjmallett * Free a handle allocated by __cvmx_srio_alloc_s2m 198215976Sjmallett * 199215976Sjmallett * @param srio_port SRIO port 200215976Sjmallett * @param index Index to free 201215976Sjmallett */ 202215976Sjmallettstatic void __cvmx_srio_free_s2m(int srio_port, int index) 203215976Sjmallett{ 204215976Sjmallett /* Read to force pending transactions to complete */ 205215976Sjmallett cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(index, srio_port)); 206215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[index], -2); 207215976Sjmallett} 208215976Sjmallett 209215976Sjmallett 210215976Sjmallett/** 211215976Sjmallett * @INTERNAL 212215976Sjmallett * Allocate a SLI SubID to map a region of memory. Reference 213215976Sjmallett * counting is used to allow sharing of duplicate setups. 214215976Sjmallett * 215215976Sjmallett * @param subid SLI_MEM_ACCESS_SUBIDX we need an index for 216215976Sjmallett * 217215976Sjmallett * @return Index of CSR, or negative on failure 218215976Sjmallett */ 219215976Sjmallettstatic int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid) 220215976Sjmallett{ 221215976Sjmallett int mem_index; 222215976Sjmallett /* Search through the mem access subid registers looking for an unsed one 223215976Sjmallett or one setup the way we need it. PCIe uses the low indexes, so search 224215976Sjmallett backwards */ 225215976Sjmallett for (mem_index=27; mem_index>=12; mem_index--) 226215976Sjmallett { 227215976Sjmallett int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], 1); 228215976Sjmallett if (ref_count == 0) 229215976Sjmallett { 230215976Sjmallett /* Unused location. Write our value */ 231215976Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64); 232232812Sjmallett /* Read back the value to make sure the update is complete */ 233232812Sjmallett cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)); 234215976Sjmallett return mem_index; 235215976Sjmallett } 236215976Sjmallett else 237215976Sjmallett { 238215976Sjmallett /* In use, see if we can use it */ 239215976Sjmallett if (cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)) == subid.u64) 240215976Sjmallett return mem_index; 241215976Sjmallett else 242215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], -1); 243215976Sjmallett } 244215976Sjmallett } 245215976Sjmallett cvmx_dprintf("SRIO: Unable to find free SLI_MEM_ACCESS_SUBIDX\n"); 246215976Sjmallett return -1; 247215976Sjmallett} 248215976Sjmallett 249215976Sjmallett 250215976Sjmallett/** 251215976Sjmallett * @INTERNAL 252215976Sjmallett * Free a handle allocated by __cvmx_srio_alloc_subid 253215976Sjmallett * 254215976Sjmallett * @param index Index to free 255215976Sjmallett */ 256215976Sjmallettstatic void __cvmx_srio_free_subid(int index) 257215976Sjmallett{ 258215976Sjmallett /* Read to force pending transactions to complete */ 259215976Sjmallett cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(index)); 260215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[index-12], -1); 261215976Sjmallett} 262215976Sjmallett#endif 263215976Sjmallett 264215976Sjmallett 265215976Sjmallett/** 266215976Sjmallett * @INTERNAL 267215976Sjmallett * Read 32bits from a local port 268215976Sjmallett * 269215976Sjmallett * @param srio_port SRIO port the device is on 270215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 271215976Sjmallett * @param result Result of the read. This will be unmodified on failure. 272215976Sjmallett * 273215976Sjmallett * @return Zero on success, negative on failure. 274215976Sjmallett */ 275215976Sjmallettstatic int __cvmx_srio_local_read32(int srio_port, uint32_t offset, uint32_t *result) 276215976Sjmallett{ 277215976Sjmallett cvmx_sriox_maint_op_t maint_op; 278215976Sjmallett cvmx_sriox_maint_rd_data_t maint_rd_data; 279215976Sjmallett maint_op.u64 = 0; 280215976Sjmallett maint_op.s.op = 0; /* Read */ 281215976Sjmallett maint_op.s.addr = offset; 282215976Sjmallett 283215976Sjmallett /* Make sure SRIO isn't already busy */ 284215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 285215976Sjmallett { 286215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before config read\n", srio_port); 287215976Sjmallett return -1; 288215976Sjmallett } 289215976Sjmallett 290215976Sjmallett /* Issue the read to the hardware */ 291215976Sjmallett cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64); 292215976Sjmallett 293215976Sjmallett /* Wait for the hardware to complete the operation */ 294215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 295215976Sjmallett { 296215976Sjmallett cvmx_dprintf("SRIO%d: Config read timeout\n", srio_port); 297215976Sjmallett return -1; 298215976Sjmallett } 299215976Sjmallett 300215976Sjmallett /* Display and error and return if the operation failed to issue */ 301215976Sjmallett maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port)); 302215976Sjmallett if (maint_op.s.fail) 303215976Sjmallett { 304215976Sjmallett cvmx_dprintf("SRIO%d: Config read addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset); 305215976Sjmallett return -1; 306215976Sjmallett } 307215976Sjmallett 308215976Sjmallett /* Wait for the read data to become valid */ 309215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_RD_DATA(srio_port), cvmx_sriox_maint_rd_data_t, valid, ==, 1, CVMX_SRIO_CONFIG_TIMEOUT)) 310215976Sjmallett { 311215976Sjmallett cvmx_dprintf("SRIO%d: Config read data timeout\n", srio_port); 312215976Sjmallett return -1; 313215976Sjmallett } 314215976Sjmallett 315215976Sjmallett /* Get the read data */ 316215976Sjmallett maint_rd_data.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_RD_DATA(srio_port)); 317215976Sjmallett *result = maint_rd_data.s.rd_data; 318215976Sjmallett return 0; 319215976Sjmallett} 320215976Sjmallett 321215976Sjmallett 322215976Sjmallett/** 323215976Sjmallett * @INTERNAL 324215976Sjmallett * Write 32bits to a local port 325215976Sjmallett * @param srio_port SRIO port the device is on 326215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 327215976Sjmallett * @param data Data to write. 328215976Sjmallett * 329215976Sjmallett * @return Zero on success, negative on failure. 330215976Sjmallett */ 331215976Sjmallettstatic int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t data) 332215976Sjmallett{ 333215976Sjmallett cvmx_sriox_maint_op_t maint_op; 334215976Sjmallett maint_op.u64 = 0; 335215976Sjmallett maint_op.s.wr_data = data; 336215976Sjmallett maint_op.s.op = 1; /* Write */ 337215976Sjmallett maint_op.s.addr = offset; 338215976Sjmallett 339215976Sjmallett /* Make sure SRIO isn't already busy */ 340215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 341215976Sjmallett { 342215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before config write\n", srio_port); 343215976Sjmallett return -1; 344215976Sjmallett } 345215976Sjmallett 346215976Sjmallett /* Issue the write to the hardware */ 347215976Sjmallett cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64); 348215976Sjmallett 349215976Sjmallett /* Wait for the hardware to complete the operation */ 350215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 351215976Sjmallett { 352215976Sjmallett cvmx_dprintf("SRIO%d: Config write timeout\n", srio_port); 353215976Sjmallett return -1; 354215976Sjmallett } 355215976Sjmallett 356215976Sjmallett /* Display and error and return if the operation failed to issue */ 357215976Sjmallett maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port)); 358215976Sjmallett if (maint_op.s.fail) 359215976Sjmallett { 360215976Sjmallett cvmx_dprintf("SRIO%d: Config write addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset); 361215976Sjmallett return -1; 362215976Sjmallett } 363215976Sjmallett return 0; 364215976Sjmallett} 365215976Sjmallett 366215976Sjmallett 367215976Sjmallett/** 368232812Sjmallett * Reset SRIO to link partner 369232812Sjmallett * 370232812Sjmallett * @param srio_port SRIO port to initialize 371232812Sjmallett * 372232812Sjmallett * @return Zero on success 373232812Sjmallett */ 374232812Sjmallettint cvmx_srio_link_rst(int srio_port) 375232812Sjmallett{ 376232812Sjmallett cvmx_sriomaintx_port_0_link_resp_t link_resp; 377232812Sjmallett 378232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 379232812Sjmallett return -1; 380232812Sjmallett 381232812Sjmallett /* Generate a symbol reset to the link partner by writing 0x3. */ 382232812Sjmallett if (cvmx_srio_config_write32(srio_port, 0, -1, 0, 0, 383232812Sjmallett CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), 3)) 384232812Sjmallett return -1; 385232812Sjmallett 386232812Sjmallett if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 387232812Sjmallett CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) 388232812Sjmallett return -1; 389232812Sjmallett 390232812Sjmallett /* Poll until link partner has received the reset. */ 391232812Sjmallett while (link_resp.s.valid == 0) 392232812Sjmallett { 393232812Sjmallett //cvmx_dprintf("Waiting for Link Response\n"); 394232812Sjmallett if (cvmx_srio_config_read32(srio_port, 0, -1, 0, 0, 395232812Sjmallett CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) 396232812Sjmallett return -1; 397232812Sjmallett } 398232812Sjmallett 399232812Sjmallett /* Valid response, Asserting MAC reset */ 400232812Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x1); 401232812Sjmallett 402232812Sjmallett cvmx_wait(10); 403232812Sjmallett 404232812Sjmallett /* De-asserting MAC Reset */ 405232812Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, 0x0); 406232812Sjmallett 407232812Sjmallett return 0; 408232812Sjmallett} 409232812Sjmallett 410232812Sjmallett/** 411215976Sjmallett * Initialize a SRIO port for use. 412215976Sjmallett * 413215976Sjmallett * @param srio_port SRIO port to initialize 414215976Sjmallett * @param flags Optional flags 415215976Sjmallett * 416215976Sjmallett * @return Zero on success 417215976Sjmallett */ 418215976Sjmallettint cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) 419215976Sjmallett{ 420215976Sjmallett cvmx_sriomaintx_port_lt_ctl_t port_lt_ctl; 421215976Sjmallett cvmx_sriomaintx_port_rt_ctl_t port_rt_ctl; 422215976Sjmallett cvmx_sriomaintx_port_0_ctl_t port_0_ctl; 423215976Sjmallett cvmx_sriomaintx_core_enables_t core_enables; 424215976Sjmallett cvmx_sriomaintx_port_gen_ctl_t port_gen_ctl; 425215976Sjmallett cvmx_sriox_status_reg_t sriox_status_reg; 426215976Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 427215976Sjmallett cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr; 428215976Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 429215976Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 430232812Sjmallett cvmx_sli_mem_access_ctl_t sli_mem_access_ctl; 431232812Sjmallett cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2; 432215976Sjmallett 433215976Sjmallett sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port)); 434232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 435215976Sjmallett { 436232812Sjmallett /* All SRIO ports are connected to QLM0 */ 437232812Sjmallett int status = cvmx_qlm_get_status(0); 438232812Sjmallett if (status < 4 || status > 6) 439232812Sjmallett { 440232812Sjmallett cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port); 441232812Sjmallett return -1; 442232812Sjmallett } 443232812Sjmallett } 444232812Sjmallett else if (!sriox_status_reg.s.srio) 445232812Sjmallett { 446215976Sjmallett cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port); 447215976Sjmallett return -1; 448215976Sjmallett } 449215976Sjmallett 450215976Sjmallett __cvmx_srio_state[srio_port].flags = flags; 451215976Sjmallett 452215976Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be 453215976Sjmallett programmed */ 454215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 455215976Sjmallett { 456215976Sjmallett if (srio_port) 457215976Sjmallett { 458215976Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 459215976Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 460215976Sjmallett ciu_qlm.s.txbypass = 1; 461215976Sjmallett ciu_qlm.s.txdeemph = 5; 462215976Sjmallett ciu_qlm.s.txmargin = 0x17; 463215976Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 464215976Sjmallett } 465215976Sjmallett else 466215976Sjmallett { 467215976Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 468215976Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 469215976Sjmallett ciu_qlm.s.txbypass = 1; 470215976Sjmallett ciu_qlm.s.txdeemph = 5; 471215976Sjmallett ciu_qlm.s.txmargin = 0x17; 472215976Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 473215976Sjmallett } 474215976Sjmallett } 475215976Sjmallett 476232812Sjmallett /* Don't receive or drive reset signals for the SRIO QLM */ 477232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 478232812Sjmallett { 479232812Sjmallett /* The reset signals are available only for srio_port == 0. */ 480232812Sjmallett if (srio_port == 0 || (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_2) && srio_port == 1)) 481232812Sjmallett { 482232812Sjmallett cvmx_mio_rst_cntlx_t mio_rst_cntl; 483232812Sjmallett mio_rst_cntl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port)); 484232812Sjmallett mio_rst_cntl.s.rst_drv = 0; 485232812Sjmallett mio_rst_cntl.s.rst_rcv = 0; 486232812Sjmallett mio_rst_cntl.s.rst_chip = 0; 487232812Sjmallett cvmx_write_csr(CVMX_MIO_RST_CNTLX(srio_port), mio_rst_cntl.u64); 488232812Sjmallett } 489232812Sjmallett /* MIO_RST_CNTL2<prtmode> is initialized to 0 on cold reset */ 490232812Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CNTLX(srio_port)); 491232812Sjmallett } 492232812Sjmallett else 493232812Sjmallett { 494232812Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); 495232812Sjmallett mio_rst_ctl.s.rst_drv = 0; 496232812Sjmallett mio_rst_ctl.s.rst_rcv = 0; 497232812Sjmallett mio_rst_ctl.s.rst_chip = 0; 498232812Sjmallett cvmx_write_csr(CVMX_MIO_RST_CTLX(srio_port), mio_rst_ctl.u64); 499232812Sjmallett 500232812Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); 501232812Sjmallett } 502232812Sjmallett 503215976Sjmallett cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port, 504215976Sjmallett (mio_rst_ctl.s.prtmode) ? "host" : "endpoint"); 505215976Sjmallett 506215976Sjmallett /* Bring the port out of reset if necessary */ 507232812Sjmallett switch (srio_port) 508215976Sjmallett { 509232812Sjmallett case 0: 510215976Sjmallett { 511232812Sjmallett cvmx_ciu_soft_prst_t prst; 512232812Sjmallett prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 513232812Sjmallett if (prst.s.soft_prst) 514232812Sjmallett { 515232812Sjmallett prst.s.soft_prst = 0; 516232812Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64); 517232812Sjmallett /* Wait up to 250ms for the port to come out of reset */ 518232812Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) 519232812Sjmallett return -1; 520232812Sjmallett } 521232812Sjmallett break; 522215976Sjmallett } 523232812Sjmallett case 1: 524215976Sjmallett { 525232812Sjmallett cvmx_ciu_soft_prst1_t prst; 526232812Sjmallett prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 527232812Sjmallett if (prst.s.soft_prst) 528232812Sjmallett { 529232812Sjmallett prst.s.soft_prst = 0; 530232812Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64); 531232812Sjmallett /* Wait up to 250ms for the port to come out of reset */ 532232812Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) 533232812Sjmallett return -1; 534232812Sjmallett } 535232812Sjmallett break; 536215976Sjmallett } 537232812Sjmallett case 2: 538232812Sjmallett { 539232812Sjmallett cvmx_ciu_soft_prst2_t prst; 540232812Sjmallett prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST2); 541232812Sjmallett if (prst.s.soft_prst) 542232812Sjmallett { 543232812Sjmallett prst.s.soft_prst = 0; 544232812Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST2, prst.u64); 545232812Sjmallett /* Wait up to 250ms for the port to come out of reset */ 546232812Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_STATUS_REG(srio_port), cvmx_sriox_status_reg_t, access, ==, 1, 250000)) 547232812Sjmallett return -1; 548232812Sjmallett } 549232812Sjmallett break; 550232812Sjmallett } 551215976Sjmallett } 552215976Sjmallett 553215976Sjmallett /* Disable the link while we make changes */ 554215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32)) 555215976Sjmallett return -1; 556232812Sjmallett port_0_ctl.s.o_enable = 0; 557232812Sjmallett port_0_ctl.s.i_enable = 0; 558232812Sjmallett port_0_ctl.s.prt_lock = 1; 559232812Sjmallett port_0_ctl.s.disable = 0; 560215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) 561215976Sjmallett return -1; 562215976Sjmallett 563232812Sjmallett /* CN63XX Pass 2.0 and 2.1 errata G-15273 requires the QLM De-emphasis be 564232812Sjmallett programmed when using a 156.25Mhz ref clock */ 565232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || 566232812Sjmallett OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1)) 567232812Sjmallett { 568232812Sjmallett cvmx_mio_rst_boot_t mio_rst_boot; 569232812Sjmallett cvmx_sriomaintx_lane_x_status_0_t lane_x_status; 570232812Sjmallett 571232812Sjmallett /* Read the QLM config and speed pins */ 572232812Sjmallett mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); 573232812Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_LANE_X_STATUS_0(0, srio_port), &lane_x_status.u32)) 574232812Sjmallett return -1; 575232812Sjmallett 576232812Sjmallett if (srio_port) 577232812Sjmallett { 578232812Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 579232812Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 580232812Sjmallett switch (mio_rst_boot.cn63xx.qlm1_spd) 581232812Sjmallett { 582232812Sjmallett case 0x4: /* 1.25 Gbaud, 156.25MHz */ 583232812Sjmallett ciu_qlm.s.txbypass = 1; 584232812Sjmallett ciu_qlm.s.txdeemph = 0x0; 585232812Sjmallett ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */ 586232812Sjmallett break; 587232812Sjmallett case 0xb: /* 5.0 Gbaud, 156.25MHz */ 588232812Sjmallett ciu_qlm.s.txbypass = 1; 589232812Sjmallett ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */ 590232812Sjmallett ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */ 591232812Sjmallett break; 592232812Sjmallett } 593232812Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 594232812Sjmallett } 595232812Sjmallett else 596232812Sjmallett { 597232812Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 598232812Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 599232812Sjmallett switch (mio_rst_boot.cn63xx.qlm0_spd) 600232812Sjmallett { 601232812Sjmallett case 0x4: /* 1.25 Gbaud, 156.25MHz */ 602232812Sjmallett ciu_qlm.s.txbypass = 1; 603232812Sjmallett ciu_qlm.s.txdeemph = 0x0; 604232812Sjmallett ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0x11 : 0x1c; /* short or med/long */ 605232812Sjmallett break; 606232812Sjmallett case 0xb: /* 5.0 Gbaud, 156.25MHz */ 607232812Sjmallett ciu_qlm.s.txbypass = 1; 608232812Sjmallett ciu_qlm.s.txdeemph = (lane_x_status.s.rx_type == 0) ? 0xa : 0xf; /* short or med/long */ 609232812Sjmallett ciu_qlm.s.txmargin = (lane_x_status.s.rx_type == 0) ? 0xf : 0x1a; /* short or med/long */ 610232812Sjmallett break; 611232812Sjmallett } 612232812Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 613232812Sjmallett } 614232812Sjmallett } 615232812Sjmallett 616215976Sjmallett /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX 617215976Sjmallett pass 1.x */ 618215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 619215976Sjmallett { 620215976Sjmallett cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2; 621215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32)) 622215976Sjmallett return -1; 623215976Sjmallett if (port_0_ctl2.s.enb_500g) 624215976Sjmallett { 625215976Sjmallett port_0_ctl2.u32 = 0; 626215976Sjmallett port_0_ctl2.s.enb_625g = 1; 627215976Sjmallett } 628215976Sjmallett else if (port_0_ctl2.s.enb_312g) 629215976Sjmallett { 630215976Sjmallett port_0_ctl2.u32 = 0; 631215976Sjmallett port_0_ctl2.s.enb_500g = 1; 632215976Sjmallett } 633215976Sjmallett else if (port_0_ctl2.s.enb_250g) 634215976Sjmallett { 635215976Sjmallett port_0_ctl2.u32 = 0; 636215976Sjmallett port_0_ctl2.s.enb_312g = 1; 637215976Sjmallett } 638215976Sjmallett else if (port_0_ctl2.s.enb_125g) 639215976Sjmallett { 640215976Sjmallett port_0_ctl2.u32 = 0; 641215976Sjmallett port_0_ctl2.s.enb_250g = 1; 642215976Sjmallett } 643215976Sjmallett else 644215976Sjmallett { 645215976Sjmallett port_0_ctl2.u32 = 0; 646215976Sjmallett port_0_ctl2.s.enb_125g = 1; 647215976Sjmallett } 648215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32)) 649215976Sjmallett return -1; 650215976Sjmallett } 651215976Sjmallett 652232812Sjmallett /* Errata SRIO-15351: Turn off SRIOMAINTX_MAC_CTRL[TYPE_MRG] as it may 653232812Sjmallett cause packet ACCEPT to be lost */ 654232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_0) || OCTEON_IS_MODEL(OCTEON_CN63XX_PASS2_1)) 655232812Sjmallett { 656232812Sjmallett cvmx_sriomaintx_mac_ctrl_t mac_ctrl; 657232812Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), &mac_ctrl.u32)) 658232812Sjmallett return -1; 659232812Sjmallett mac_ctrl.s.type_mrg = 0; 660232812Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_MAC_CTRL(srio_port), mac_ctrl.u32)) 661232812Sjmallett return -1; 662232812Sjmallett } 663232812Sjmallett 664232812Sjmallett /* Set the link layer timeout to 1ms. The default is too high and causes 665215976Sjmallett core bus errors */ 666215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32)) 667215976Sjmallett return -1; 668232812Sjmallett port_lt_ctl.s.timeout = 1000000 / 200; /* 1ms = 1000000ns / 200ns */ 669215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32)) 670215976Sjmallett return -1; 671215976Sjmallett 672232812Sjmallett /* Set the logical layer timeout to 100ms. The default is too high and causes 673215976Sjmallett core bus errors */ 674215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32)) 675215976Sjmallett return -1; 676232812Sjmallett port_rt_ctl.s.timeout = 100000000 / 200; /* 100ms = 100000000ns / 200ns */ 677215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32)) 678215976Sjmallett return -1; 679215976Sjmallett 680215976Sjmallett /* Allow memory and doorbells. Messaging is enabled later */ 681215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &core_enables.u32)) 682215976Sjmallett return -1; 683215976Sjmallett core_enables.s.doorbell = 1; 684215976Sjmallett core_enables.s.memory = 1; 685215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), core_enables.u32)) 686215976Sjmallett return -1; 687215976Sjmallett 688215976Sjmallett /* Allow us to master transactions */ 689215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), &port_gen_ctl.u32)) 690215976Sjmallett return -1; 691215976Sjmallett port_gen_ctl.s.menable = 1; 692215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), port_gen_ctl.u32)) 693215976Sjmallett return -1; 694215976Sjmallett 695215976Sjmallett /* Set the MRRS and MPS for optimal SRIO performance */ 696215976Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port)); 697215976Sjmallett prt_cfg.s.mps = 1; 698215976Sjmallett prt_cfg.s.mrrs = 1; 699232812Sjmallett prt_cfg.s.molr = 32; 700232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 701232812Sjmallett prt_cfg.s.molr = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 8 702232812Sjmallett : (prt_cfg.s.qlm_cfg == 4 || prt_cfg.s.qlm_cfg == 6) ? 16 703232812Sjmallett : 32); 704215976Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64); 705215976Sjmallett 706215976Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port)); 707215976Sjmallett sli_s2m_portx_ctl.s.mrrs = 1; 708215976Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port), sli_s2m_portx_ctl.u64); 709215976Sjmallett 710215976Sjmallett /* Setup RX messaging thresholds */ 711215976Sjmallett sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port)); 712232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 713232812Sjmallett sriox_imsg_vport_thr.s.max_tot = ((prt_cfg.s.qlm_cfg == 1 || prt_cfg.s.qlm_cfg == 3) ? 44 : 46); 714232812Sjmallett else 715232812Sjmallett sriox_imsg_vport_thr.s.max_tot = 48; 716215976Sjmallett sriox_imsg_vport_thr.s.max_s1 = 24; 717215976Sjmallett sriox_imsg_vport_thr.s.max_s0 = 24; 718215976Sjmallett sriox_imsg_vport_thr.s.sp_vport = 1; 719215976Sjmallett sriox_imsg_vport_thr.s.buf_thr = 4; 720215976Sjmallett sriox_imsg_vport_thr.s.max_p1 = 12; 721215976Sjmallett sriox_imsg_vport_thr.s.max_p0 = 12; 722215976Sjmallett cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64); 723215976Sjmallett 724232812Sjmallett /* Setup RX messaging thresholds for other virtual ports. */ 725232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX)) 726232812Sjmallett { 727232812Sjmallett cvmx_sriox_imsg_vport_thr2_t sriox_imsg_vport_thr2; 728232812Sjmallett sriox_imsg_vport_thr2.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port)); 729232812Sjmallett sriox_imsg_vport_thr2.s.max_s2 = 24; 730232812Sjmallett sriox_imsg_vport_thr2.s.max_s3 = 24; 731232812Sjmallett cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR2(srio_port), sriox_imsg_vport_thr2.u64); 732232812Sjmallett } 733232812Sjmallett 734215976Sjmallett /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */ 735215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 736215976Sjmallett { 737215976Sjmallett cvmx_sriox_tx_ctrl_t sriox_tx_ctrl; 738215976Sjmallett sriox_tx_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_TX_CTRL(srio_port)); 739215976Sjmallett sriox_tx_ctrl.s.tag_th2 = 2; 740215976Sjmallett sriox_tx_ctrl.s.tag_th1 = 3; 741215976Sjmallett sriox_tx_ctrl.s.tag_th0 = 4; 742215976Sjmallett cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64); 743215976Sjmallett } 744215976Sjmallett 745232812Sjmallett /* Errata SLI-15954: SLI relaxed order issues */ 746232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN66XX_PASS1_X)) 747232812Sjmallett { 748232812Sjmallett cvmx_sli_ctl_portx_t sli_ctl_portx; 749232812Sjmallett sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port)); 750232812Sjmallett sli_ctl_portx.s.ptlp_ro = 1; /* Set to same value for all MACs. */ 751232812Sjmallett sli_ctl_portx.s.ctlp_ro = 1; /* Set to same value for all MACs. */ 752232812Sjmallett sli_ctl_portx.s.wait_com = 0; /* So that no inbound stores wait for a commit */ 753232812Sjmallett sli_ctl_portx.s.waitl_com = 0; 754232812Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), sli_ctl_portx.u64); 755232812Sjmallett } 756232812Sjmallett 757232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 758232812Sjmallett { 759232812Sjmallett /* Clear the ACK state */ 760232812Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), 0)) 761232812Sjmallett return -1; 762232812Sjmallett } 763232812Sjmallett 764232812Sjmallett /* Bring the link down, then up, by writing to the SRIO port's 765232812Sjmallett PORT_0_CTL2 CSR. */ 766232812Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32)) 767232812Sjmallett return -1; 768232812Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32)) 769232812Sjmallett return -1; 770232812Sjmallett 771215976Sjmallett /* Clear any pending interrupts */ 772215976Sjmallett cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port))); 773215976Sjmallett 774215976Sjmallett /* Enable error reporting */ 775232816Sjmallett#if (!defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL) 776215976Sjmallett cvmx_error_enable_group(CVMX_ERROR_GROUP_SRIO, srio_port); 777215976Sjmallett#endif 778215976Sjmallett 779215976Sjmallett /* Finally enable the link */ 780215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32)) 781215976Sjmallett return -1; 782215976Sjmallett port_0_ctl.s.o_enable = 1; 783215976Sjmallett port_0_ctl.s.i_enable = 1; 784215976Sjmallett port_0_ctl.s.disable = 0; 785215976Sjmallett port_0_ctl.s.prt_lock = 0; 786215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) 787215976Sjmallett return -1; 788215976Sjmallett 789232812Sjmallett /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ 790232812Sjmallett sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL); 791232812Sjmallett sli_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ 792232812Sjmallett sli_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ 793232812Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64); 794232812Sjmallett 795232812Sjmallett /* FIXME: Disable sending a link request when the SRIO link is 796232812Sjmallett brought up. For unknown reasons this code causes issues with some SRIO 797232812Sjmallett devices. As we currently don't support hotplug in software, this code 798232812Sjmallett should never be needed. Without link down/up events, the ACKs should 799232812Sjmallett start off and stay synchronized */ 800232812Sjmallett#if 0 801232812Sjmallett /* Ask for a link and align our ACK state. CN63XXp1 didn't support this */ 802232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 803232812Sjmallett { 804232812Sjmallett uint64_t stop_cycle; 805232812Sjmallett cvmx_sriomaintx_port_0_err_stat_t sriomaintx_port_0_err_stat; 806232812Sjmallett 807232812Sjmallett /* Clear the SLI_CTL_PORTX[DIS_PORT[ bit to re-enable traffic-flow 808232812Sjmallett to the SRIO MACs. */ 809232812Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port), cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(srio_port))); 810232812Sjmallett 811232812Sjmallett /* Wait a little to see if the link comes up */ 812232812Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/4 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 813232812Sjmallett do 814232812Sjmallett { 815232812Sjmallett /* Read the port link status */ 816232812Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_ERR_STAT(srio_port), &sriomaintx_port_0_err_stat.u32)) 817232812Sjmallett return -1; 818232812Sjmallett } while (!sriomaintx_port_0_err_stat.s.pt_ok && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle)); 819232812Sjmallett 820232812Sjmallett /* Send link request if link is up */ 821232812Sjmallett if (sriomaintx_port_0_err_stat.s.pt_ok) 822232812Sjmallett { 823232812Sjmallett cvmx_sriomaintx_port_0_link_req_t link_req; 824232812Sjmallett cvmx_sriomaintx_port_0_link_resp_t link_resp; 825232812Sjmallett link_req.u32 = 0; 826232812Sjmallett link_req.s.cmd = 4; 827232812Sjmallett 828232812Sjmallett /* Send the request */ 829232812Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_REQ(srio_port), link_req.u32)) 830232812Sjmallett return -1; 831232812Sjmallett 832232812Sjmallett /* Wait for the response */ 833232812Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/8 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 834232812Sjmallett do 835232812Sjmallett { 836232812Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_LINK_RESP(srio_port), &link_resp.u32)) 837232812Sjmallett return -1; 838232812Sjmallett } while (!link_resp.s.valid && (cvmx_clock_get_count(CVMX_CLOCK_CORE) < stop_cycle)); 839232812Sjmallett 840232812Sjmallett /* Set our ACK state if we got a response */ 841232812Sjmallett if (link_resp.s.valid) 842232812Sjmallett { 843232812Sjmallett cvmx_sriomaintx_port_0_local_ackid_t local_ackid; 844232812Sjmallett local_ackid.u32 = 0; 845232812Sjmallett local_ackid.s.i_ackid = 0; 846232812Sjmallett local_ackid.s.e_ackid = link_resp.s.ackid; 847232812Sjmallett local_ackid.s.o_ackid = link_resp.s.ackid; 848232812Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_LOCAL_ACKID(srio_port), local_ackid.u32)) 849232812Sjmallett return -1; 850232812Sjmallett } 851232812Sjmallett else 852232812Sjmallett return -1; 853232812Sjmallett } 854232812Sjmallett } 855232812Sjmallett#endif 856232812Sjmallett 857215976Sjmallett return 0; 858215976Sjmallett} 859215976Sjmallett 860215976Sjmallett 861215976Sjmallett/** 862215976Sjmallett * Read 32bits from a Device's config space 863215976Sjmallett * 864215976Sjmallett * @param srio_port SRIO port the device is on 865215976Sjmallett * @param srcid_index 866215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 867215976Sjmallett * @param destid RapidIO device ID, or -1 for the local Octeon. 868215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 869215976Sjmallett * if transactions should use 8bit device IDs. 870215976Sjmallett * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon. 871215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 872215976Sjmallett * @param result Result of the read. This will be unmodified on failure. 873215976Sjmallett * 874215976Sjmallett * @return Zero on success, negative on failure. 875215976Sjmallett */ 876215976Sjmallettint cvmx_srio_config_read32(int srio_port, int srcid_index, int destid, 877215976Sjmallett int is16bit, uint8_t hopcount, uint32_t offset, 878215976Sjmallett uint32_t *result) 879215976Sjmallett{ 880215976Sjmallett if (destid == -1) 881215976Sjmallett { 882215976Sjmallett int status = __cvmx_srio_local_read32(srio_port, offset, result); 883215976Sjmallett 884215976Sjmallett if ((status == 0) && (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)) 885215976Sjmallett cvmx_dprintf("SRIO%d: Local read [0x%06x] <= 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)*result); 886215976Sjmallett 887215976Sjmallett return status; 888215976Sjmallett } 889215976Sjmallett else 890215976Sjmallett { 891232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 892232812Sjmallett { 893232812Sjmallett int return_code; 894232812Sjmallett uint32_t pkt = 0; 895232812Sjmallett uint32_t sourceid; 896232812Sjmallett uint64_t stop_cycle; 897232812Sjmallett char rx_buffer[64]; 898215976Sjmallett 899232812Sjmallett /* Tell the user */ 900232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 901232812Sjmallett cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); 902215976Sjmallett 903232812Sjmallett /* Read the proper source ID */ 904232812Sjmallett if (srcid_index) 905232812Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); 906232812Sjmallett else 907232812Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); 908215976Sjmallett 909232812Sjmallett if (is16bit) 910232812Sjmallett { 911232812Sjmallett /* Use the 16bit source ID */ 912232812Sjmallett sourceid &= 0xffff; 913215976Sjmallett 914232812Sjmallett /* MAINT Reads are 11 bytes */ 915232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16); 916215976Sjmallett 917232812Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 918232812Sjmallett pkt |= 1 << 28; /* tt [29:28] */ 919232812Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 920232812Sjmallett pkt |= destid << 8; /* destID [23:8] */ 921232812Sjmallett pkt |= sourceid >> 8; /* sourceID [7:0] */ 922232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 923232812Sjmallett pkt = 0; 924232812Sjmallett pkt |= sourceid << 24; /* sourceID [31:24] */ 925232812Sjmallett pkt |= 0 << 20; /* transaction [23:20] */ 926232812Sjmallett pkt |= 8 << 16; /* rdsize [19:16] */ 927232812Sjmallett pkt |= 0xc0 << 8; /* srcTID [15:8] */ 928232812Sjmallett pkt |= hopcount; /* hopcount [7:0] */ 929232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 930232812Sjmallett pkt = 0; 931232812Sjmallett pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ 932232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 933232812Sjmallett } 934232812Sjmallett else 935232812Sjmallett { 936232812Sjmallett /* Use the 8bit source ID */ 937232812Sjmallett sourceid = (sourceid >> 16) & 0xff; 938215976Sjmallett 939232812Sjmallett /* MAINT Reads are 9 bytes */ 940232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16); 941215976Sjmallett 942232812Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 943232812Sjmallett pkt |= 0 << 28; /* tt [29:28] */ 944232812Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 945232812Sjmallett pkt |= destid << 16; /* destID [23:16] */ 946232812Sjmallett pkt |= sourceid << 8; /* sourceID [15:8] */ 947232812Sjmallett pkt |= 0 << 4; /* transaction [7:4] */ 948232812Sjmallett pkt |= 8 << 0; /* rdsize [3:0] */ 949232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 950232812Sjmallett pkt = 0; 951232812Sjmallett pkt |= 0xc0 << 24; /* srcTID [31:24] */ 952232812Sjmallett pkt |= hopcount << 16; /* hopcount [23:16] */ 953232812Sjmallett pkt |= offset >> 8; /* offset [15:0] */ 954232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 955232812Sjmallett pkt = 0; 956232812Sjmallett pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ 957232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 958232812Sjmallett } 959215976Sjmallett 960232812Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 961232812Sjmallett do 962215976Sjmallett { 963232812Sjmallett return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); 964232812Sjmallett if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) 965232812Sjmallett { 966232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 967232812Sjmallett cvmx_dprintf("timeout\n"); 968232812Sjmallett return_code = -1; 969232812Sjmallett } 970232812Sjmallett } while (return_code == 0); 971215976Sjmallett 972232812Sjmallett if (return_code == ((is16bit) ? 23 : 19)) 973215976Sjmallett { 974232812Sjmallett if (is16bit) 975232812Sjmallett { 976232812Sjmallett if (offset & 4) 977232812Sjmallett *result = *(uint32_t*)(rx_buffer + 15); 978232812Sjmallett else 979232812Sjmallett *result = *(uint32_t*)(rx_buffer + 11); 980232812Sjmallett } 981215976Sjmallett else 982232812Sjmallett { 983232812Sjmallett if (offset & 4) 984232812Sjmallett *result = *(uint32_t*)(rx_buffer + 13); 985232812Sjmallett else 986232812Sjmallett *result = *(uint32_t*)(rx_buffer + 9); 987232812Sjmallett } 988232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 989232812Sjmallett cvmx_dprintf("0x%08x\n", (unsigned int)*result); 990232812Sjmallett return_code = 0; 991215976Sjmallett } 992215976Sjmallett else 993215976Sjmallett { 994232812Sjmallett *result = 0xffffffff; 995232812Sjmallett return_code = -1; 996215976Sjmallett } 997232812Sjmallett 998232812Sjmallett return return_code; 999215976Sjmallett } 1000215976Sjmallett else 1001215976Sjmallett { 1002232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_HOST) 1003232812Sjmallett uint64_t physical; 1004232812Sjmallett physical = cvmx_srio_physical_map(srio_port, 1005232812Sjmallett CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 1006232812Sjmallett CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 1007232812Sjmallett srcid_index, destid, is16bit, offset + (hopcount<<24), 4); 1008232812Sjmallett if (!physical) 1009232812Sjmallett return -1; 1010215976Sjmallett 1011232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1012232812Sjmallett cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); 1013215976Sjmallett 1014232812Sjmallett /* Finally do the maintenance read to complete the config request */ 1015232812Sjmallett *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical)); 1016232812Sjmallett cvmx_srio_physical_unmap(physical, 4); 1017215976Sjmallett 1018232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1019232812Sjmallett cvmx_dprintf("0x%08x\n", (unsigned int)*result); 1020215976Sjmallett 1021232812Sjmallett return 0; 1022215976Sjmallett#else 1023232812Sjmallett return -1; 1024215976Sjmallett#endif 1025232812Sjmallett } 1026215976Sjmallett } 1027215976Sjmallett} 1028232812Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1029232812SjmallettEXPORT_SYMBOL(cvmx_srio_config_read32); 1030232812Sjmallett#endif 1031215976Sjmallett 1032215976Sjmallett 1033215976Sjmallett/** 1034215976Sjmallett * Write 32bits to a Device's config space 1035215976Sjmallett * 1036215976Sjmallett * @param srio_port SRIO port the device is on 1037215976Sjmallett * @param srcid_index 1038215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 1039215976Sjmallett * @param destid RapidIO device ID, or -1 for the local Octeon. 1040215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1041215976Sjmallett * if transactions should use 8bit device IDs. 1042215976Sjmallett * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon. 1043215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 1044215976Sjmallett * @param data Data to write. 1045215976Sjmallett * 1046215976Sjmallett * @return Zero on success, negative on failure. 1047215976Sjmallett */ 1048215976Sjmallettint cvmx_srio_config_write32(int srio_port, int srcid_index, int destid, 1049215976Sjmallett int is16bit, uint8_t hopcount, uint32_t offset, 1050215976Sjmallett uint32_t data) 1051215976Sjmallett{ 1052215976Sjmallett if (destid == -1) 1053215976Sjmallett { 1054215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1055215976Sjmallett cvmx_dprintf("SRIO%d: Local write[0x%06x] => 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)data); 1056215976Sjmallett 1057215976Sjmallett return __cvmx_srio_local_write32(srio_port, offset, data); 1058215976Sjmallett } 1059215976Sjmallett else 1060215976Sjmallett { 1061232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 1062215976Sjmallett { 1063232812Sjmallett int return_code; 1064232812Sjmallett uint32_t pkt = 0; 1065232812Sjmallett uint32_t sourceid; 1066232812Sjmallett uint64_t stop_cycle; 1067232812Sjmallett char rx_buffer[64]; 1068215976Sjmallett 1069232812Sjmallett /* Tell the user */ 1070232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1071232812Sjmallett cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, (unsigned int)offset, (unsigned int)data); 1072215976Sjmallett 1073232812Sjmallett /* Read the proper source ID */ 1074232812Sjmallett if (srcid_index) 1075232812Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); 1076215976Sjmallett else 1077232812Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); 1078232812Sjmallett 1079232812Sjmallett if (is16bit) 1080215976Sjmallett { 1081232812Sjmallett /* Use the 16bit source ID */ 1082232812Sjmallett sourceid &= 0xffff; 1083215976Sjmallett 1084232812Sjmallett /* MAINT Writes are 19 bytes */ 1085232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16); 1086215976Sjmallett 1087232812Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 1088232812Sjmallett pkt |= 1 << 28; /* tt [29:28] */ 1089232812Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 1090232812Sjmallett pkt |= destid << 8; /* destID [23:8] */ 1091232812Sjmallett pkt |= sourceid >> 8; /* sourceID [7:0] */ 1092215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1093232812Sjmallett pkt = 0; 1094232812Sjmallett pkt |= sourceid << 24; /* sourceID [31:24] */ 1095232812Sjmallett pkt |= 1 << 20; /* transaction [23:20] */ 1096232812Sjmallett pkt |= 8 << 16; /* wrsize [19:16] */ 1097232812Sjmallett pkt |= 0xc0 << 8; /* srcTID [15:8] */ 1098232812Sjmallett pkt |= hopcount; /* hopcount [7:0] */ 1099215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1100232812Sjmallett pkt = 0; 1101232812Sjmallett pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ 1102232812Sjmallett if ((offset & 4) == 0) 1103232812Sjmallett pkt |= 0xff & (data >> 24); /* data [7:0] */ 1104215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1105232812Sjmallett if (offset & 4) 1106232812Sjmallett { 1107232812Sjmallett pkt = 0xff & (data >> 24); 1108232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1109232812Sjmallett pkt = data << 8; 1110232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1111232812Sjmallett } 1112232812Sjmallett else 1113232812Sjmallett { 1114232812Sjmallett pkt = data << 8; 1115232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1116232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); 1117232812Sjmallett } 1118215976Sjmallett } 1119215976Sjmallett else 1120215976Sjmallett { 1121232812Sjmallett /* Use the 8bit source ID */ 1122232812Sjmallett sourceid = (sourceid >> 16) & 0xff; 1123232812Sjmallett 1124232812Sjmallett /* MAINT Writes are 17 bytes */ 1125232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16); 1126232812Sjmallett 1127232812Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 1128232812Sjmallett pkt |= 0 << 28; /* tt [29:28] */ 1129232812Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 1130232812Sjmallett pkt |= destid << 16; /* destID [23:16] */ 1131232812Sjmallett pkt |= sourceid << 8; /* sourceID [15:8] */ 1132232812Sjmallett pkt |= 1 << 4; /* transaction [7:4] */ 1133232812Sjmallett pkt |= 8 << 0; /* wrsize [3:0] */ 1134215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1135232812Sjmallett pkt = 0; 1136232812Sjmallett pkt |= 0xc0 << 24; /* srcTID [31:24] */ 1137232812Sjmallett pkt |= hopcount << 16; /* hopcount [23:16] */ 1138232812Sjmallett pkt |= offset >> 8; /* offset [15:0] */ 1139215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1140232812Sjmallett pkt = 0; 1141232812Sjmallett pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ 1142232812Sjmallett if (offset & 4) 1143232812Sjmallett { 1144232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1145232812Sjmallett pkt = data >> 8; 1146232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1147232812Sjmallett pkt = data << 24; 1148232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1149232812Sjmallett } 1150232812Sjmallett else 1151232812Sjmallett { 1152232812Sjmallett pkt |= data >> 8; /* data [23:0] */ 1153232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1154232812Sjmallett pkt = data << 24; /* data [31:24] */ 1155232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 1156232812Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); 1157232812Sjmallett } 1158215976Sjmallett } 1159215976Sjmallett 1160232812Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 1161232812Sjmallett do 1162215976Sjmallett { 1163232812Sjmallett return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); 1164232812Sjmallett if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) 1165232812Sjmallett { 1166232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1167232812Sjmallett cvmx_dprintf("timeout\n"); 1168232812Sjmallett return_code = -1; 1169232812Sjmallett } 1170232812Sjmallett } while (return_code == 0); 1171232812Sjmallett 1172232812Sjmallett if (return_code == ((is16bit) ? 15 : 11)) 1173232812Sjmallett return_code = 0; 1174232812Sjmallett else 1175232812Sjmallett { 1176232812Sjmallett cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port); 1177215976Sjmallett return_code = -1; 1178215976Sjmallett } 1179215976Sjmallett 1180232812Sjmallett return return_code; 1181232812Sjmallett } 1182215976Sjmallett else 1183215976Sjmallett { 1184232812Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_HOST) 1185232812Sjmallett uint64_t physical = cvmx_srio_physical_map(srio_port, 1186232812Sjmallett CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 1187232812Sjmallett CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 1188232812Sjmallett srcid_index, destid, is16bit, offset + (hopcount<<24), 4); 1189232812Sjmallett if (!physical) 1190232812Sjmallett return -1; 1191215976Sjmallett 1192232812Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1193232812Sjmallett cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, (unsigned int)offset, (unsigned int)data); 1194215976Sjmallett 1195232812Sjmallett /* Finally do the maintenance write to complete the config request */ 1196232812Sjmallett cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data); 1197232812Sjmallett return cvmx_srio_physical_unmap(physical, 4); 1198215976Sjmallett#else 1199232812Sjmallett return -1; 1200215976Sjmallett#endif 1201232812Sjmallett } 1202215976Sjmallett } 1203215976Sjmallett} 1204215976Sjmallett 1205215976Sjmallett 1206215976Sjmallett/** 1207215976Sjmallett * Send a RapidIO doorbell to a remote device 1208215976Sjmallett * 1209215976Sjmallett * @param srio_port SRIO port the device is on 1210215976Sjmallett * @param srcid_index 1211215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 1212215976Sjmallett * @param destid RapidIO device ID. 1213215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1214215976Sjmallett * if transactions should use 8bit device IDs. 1215215976Sjmallett * @param priority Doorbell priority (0-3) 1216215976Sjmallett * @param data Data for doorbell. 1217215976Sjmallett * 1218215976Sjmallett * @return Zero on success, negative on failure. 1219215976Sjmallett */ 1220215976Sjmallettint cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16bit, int priority, uint16_t data) 1221215976Sjmallett{ 1222215976Sjmallett cvmx_sriox_tx_bell_t tx_bell; 1223215976Sjmallett tx_bell.u64 = 0; 1224215976Sjmallett tx_bell.s.data = data; 1225215976Sjmallett tx_bell.s.dest_id = destid; 1226215976Sjmallett tx_bell.s.src_id = srcid_index; 1227215976Sjmallett tx_bell.s.id16 = !!is16bit; 1228215976Sjmallett tx_bell.s.priority = priority; 1229215976Sjmallett 1230215976Sjmallett /* Make sure the previous doorbell has completed */ 1231215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_TX_BELL(srio_port), cvmx_sriox_tx_bell_t, pending, ==, 0, CVMX_SRIO_DOORBELL_TIMEOUT)) 1232215976Sjmallett { 1233215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before doorbell\n", srio_port); 1234215976Sjmallett return -1; 1235215976Sjmallett } 1236215976Sjmallett 1237215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1238215976Sjmallett cvmx_dprintf("SRIO%d: Send doorbell destid=0x%x, priority=%d, data=0x%x\n", srio_port, destid, priority, 0xffff & data); 1239215976Sjmallett 1240215976Sjmallett /* Send the doorbell. We don't wait for it to complete. The next doorbell 1241215976Sjmallett may delay on the pending bit, but this gives the caller the ability to 1242215976Sjmallett do other stuff while the doorbell processes */ 1243215976Sjmallett cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64); 1244215976Sjmallett return 0; 1245215976Sjmallett} 1246232812Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1247232812SjmallettEXPORT_SYMBOL(cvmx_srio_send_doorbell); 1248232812Sjmallett#endif 1249215976Sjmallett 1250215976Sjmallett/** 1251215976Sjmallett * Get the status of the last doorbell sent. If the dooorbell 1252215976Sjmallett * hardware is done, then the status is cleared to get ready for 1253215976Sjmallett * the next doorbell (or retry). 1254215976Sjmallett * 1255215976Sjmallett * @param srio_port SRIO port to check doorbell on 1256215976Sjmallett * 1257215976Sjmallett * @return Doorbell status 1258215976Sjmallett */ 1259215976Sjmallettcvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port) 1260215976Sjmallett{ 1261215976Sjmallett cvmx_sriox_tx_bell_t tx_bell; 1262215976Sjmallett cvmx_sriox_tx_bell_info_t tx_bell_info; 1263215976Sjmallett cvmx_sriox_int_reg_t int_reg; 1264215976Sjmallett cvmx_sriox_int_reg_t int_reg_clear; 1265215976Sjmallett 1266215976Sjmallett /* Return busy if the doorbell is still processing */ 1267215976Sjmallett tx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL(srio_port)); 1268215976Sjmallett if (tx_bell.s.pending) 1269215976Sjmallett return CVMX_SRIO_DOORBELL_BUSY; 1270215976Sjmallett 1271215976Sjmallett /* Read and clear the TX doorbell interrupts */ 1272215976Sjmallett int_reg.u64 = cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port)); 1273215976Sjmallett int_reg_clear.u64 = 0; 1274215976Sjmallett int_reg_clear.s.bell_err = int_reg.s.bell_err; 1275215976Sjmallett int_reg_clear.s.txbell = int_reg.s.txbell; 1276215976Sjmallett cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), int_reg_clear.u64); 1277215976Sjmallett 1278215976Sjmallett /* Check for errors */ 1279215976Sjmallett if (int_reg.s.bell_err) 1280215976Sjmallett { 1281215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1282215976Sjmallett cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port); 1283215976Sjmallett tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port)); 1284232812Sjmallett if (tx_bell_info.s.timeout) 1285232812Sjmallett return CVMX_SRIO_DOORBELL_TMOUT; 1286232812Sjmallett if (tx_bell_info.s.error) 1287215976Sjmallett return CVMX_SRIO_DOORBELL_ERROR; 1288215976Sjmallett if (tx_bell_info.s.retry) 1289215976Sjmallett return CVMX_SRIO_DOORBELL_RETRY; 1290215976Sjmallett } 1291215976Sjmallett 1292215976Sjmallett /* Check if we're done */ 1293215976Sjmallett if (int_reg.s.txbell) 1294215976Sjmallett return CVMX_SRIO_DOORBELL_DONE; 1295215976Sjmallett 1296215976Sjmallett /* No doorbell found */ 1297215976Sjmallett return CVMX_SRIO_DOORBELL_NONE; 1298215976Sjmallett} 1299215976Sjmallett 1300215976Sjmallett 1301215976Sjmallett/** 1302215976Sjmallett * Read a received doorbell and report data about it. 1303215976Sjmallett * 1304215976Sjmallett * @param srio_port SRIO port to check for the received doorbell 1305215976Sjmallett * @param destid_index 1306215976Sjmallett * Which Octeon destination ID was the doorbell for 1307215976Sjmallett * @param sequence_num 1308215976Sjmallett * Sequence number of doorbell (32bits) 1309215976Sjmallett * @param srcid RapidIO source ID of the doorbell sender 1310215976Sjmallett * @param priority Priority of the doorbell (0-3) 1311215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1312215976Sjmallett * if transactions should use 8bit device IDs. 1313215976Sjmallett * @param data Data in the doorbell (16 bits) 1314215976Sjmallett * 1315215976Sjmallett * @return Doorbell status. Either DONE, NONE, or ERROR. 1316215976Sjmallett */ 1317215976Sjmallettcvmx_srio_doorbell_status_t cvmx_srio_receive_doorbell(int srio_port, 1318215976Sjmallett int *destid_index, uint32_t *sequence_num, int *srcid, int *priority, 1319215976Sjmallett int *is16bit, uint16_t *data) 1320215976Sjmallett{ 1321215976Sjmallett cvmx_sriox_rx_bell_seq_t rx_bell_seq; 1322215976Sjmallett cvmx_sriox_rx_bell_t rx_bell; 1323215976Sjmallett 1324215976Sjmallett /* Check if there are any pending doorbells */ 1325215976Sjmallett rx_bell_seq.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL_SEQ(srio_port)); 1326215976Sjmallett if (!rx_bell_seq.s.count) 1327215976Sjmallett return CVMX_SRIO_DOORBELL_NONE; 1328215976Sjmallett 1329215976Sjmallett /* Read the doorbell and write our return parameters */ 1330215976Sjmallett rx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL(srio_port)); 1331215976Sjmallett *sequence_num = rx_bell_seq.s.seq; 1332215976Sjmallett *srcid = rx_bell.s.src_id; 1333215976Sjmallett *priority = rx_bell.s.priority; 1334215976Sjmallett *is16bit = rx_bell.s.id16; 1335215976Sjmallett *data = rx_bell.s.data; 1336215976Sjmallett *destid_index = rx_bell.s.dest_id; 1337215976Sjmallett 1338215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1339215976Sjmallett cvmx_dprintf("SRIO%d: Receive doorbell sequence=0x%x, srcid=0x%x, priority=%d, data=0x%x\n", 1340215976Sjmallett srio_port, rx_bell_seq.s.seq, rx_bell.s.src_id, rx_bell.s.priority, rx_bell.s.data); 1341215976Sjmallett 1342215976Sjmallett return CVMX_SRIO_DOORBELL_DONE; 1343215976Sjmallett} 1344215976Sjmallett 1345215976Sjmallett 1346215976Sjmallett/** 1347215976Sjmallett * Receive a packet from the Soft Packet FIFO (SPF). 1348215976Sjmallett * 1349215976Sjmallett * @param srio_port SRIO port to read the packet from. 1350215976Sjmallett * @param buffer Buffer to receive the packet. 1351215976Sjmallett * @param buffer_length 1352215976Sjmallett * Length of the buffer in bytes. 1353215976Sjmallett * 1354215976Sjmallett * @return Returns the length of the packet read. Negative on failure. 1355215976Sjmallett * Zero if no packets are available. 1356215976Sjmallett */ 1357215976Sjmallettint cvmx_srio_receive_spf(int srio_port, void *buffer, int buffer_length) 1358215976Sjmallett{ 1359215976Sjmallett uint32_t *ptr = (uint32_t *)buffer; 1360215976Sjmallett cvmx_sriomaintx_ir_sp_rx_stat_t sriomaintx_ir_sp_rx_stat; 1361215976Sjmallett 1362215976Sjmallett /* Read the SFP status */ 1363215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_STAT(srio_port), &sriomaintx_ir_sp_rx_stat.u32)) 1364215976Sjmallett return -1; 1365215976Sjmallett 1366215976Sjmallett /* Return zero if there isn't a packet available */ 1367215976Sjmallett if (sriomaintx_ir_sp_rx_stat.s.buffers < 1) 1368215976Sjmallett return 0; 1369215976Sjmallett 1370215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1371215976Sjmallett cvmx_dprintf("SRIO%d: Soft packet FIFO received %d bytes", srio_port, sriomaintx_ir_sp_rx_stat.s.octets); 1372215976Sjmallett 1373215976Sjmallett /* Return error if the packet is larger than our buffer */ 1374215976Sjmallett if (sriomaintx_ir_sp_rx_stat.s.octets > buffer_length) 1375215976Sjmallett return -1; 1376215976Sjmallett 1377215976Sjmallett /* Read out the packet four bytes at a time */ 1378215976Sjmallett buffer_length = sriomaintx_ir_sp_rx_stat.s.octets; 1379215976Sjmallett while (buffer_length > 0) 1380215976Sjmallett { 1381215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_DATA(srio_port), ptr); 1382215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1383215976Sjmallett cvmx_dprintf(" %08x", (unsigned int)*ptr); 1384215976Sjmallett ptr++; 1385215976Sjmallett buffer_length-=4; 1386215976Sjmallett } 1387215976Sjmallett 1388215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1389215976Sjmallett cvmx_dprintf("\n"); 1390215976Sjmallett 1391215976Sjmallett /* Return the number of bytes in the buffer */ 1392215976Sjmallett return sriomaintx_ir_sp_rx_stat.s.octets; 1393215976Sjmallett} 1394215976Sjmallett 1395215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 1396215976Sjmallett/** 1397215976Sjmallett * Map a remote device's memory region into Octeon's physical 1398215976Sjmallett * address area. The caller can then map this into a core using 1399215976Sjmallett * the TLB or XKPHYS. 1400215976Sjmallett * 1401215976Sjmallett * @param srio_port SRIO port to map the device on 1402215976Sjmallett * @param write_op Type of operation to perform on a write to the device. 1403215976Sjmallett * Normally should be CVMX_SRIO_WRITE_MODE_AUTO. 1404215976Sjmallett * @param write_priority 1405215976Sjmallett * SRIO priority of writes (0-3) 1406215976Sjmallett * @param read_op Type of operation to perform on reads to the device. 1407215976Sjmallett * Normally should be CVMX_SRIO_READ_MODE_NORMAL. 1408215976Sjmallett * @param read_priority 1409215976Sjmallett * SRIO priority of reads (0-3) 1410215976Sjmallett * @param srcid_index 1411215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 1412215976Sjmallett * @param destid RapidIO device ID. 1413215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1414215976Sjmallett * if transactions should use 8bit device IDs. 1415215976Sjmallett * @param base Device base address to start the mapping 1416215976Sjmallett * @param size Size of the mapping in bytes 1417215976Sjmallett * 1418215976Sjmallett * @return Octeon 64bit physical address that accesses the remote device, 1419215976Sjmallett * or zero on failure. 1420215976Sjmallett */ 1421215976Sjmallettuint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, 1422215976Sjmallett int write_priority, cvmx_srio_read_mode_t read_op, int read_priority, 1423215976Sjmallett int srcid_index, int destid, int is16bit, uint64_t base, uint64_t size) 1424215976Sjmallett{ 1425215976Sjmallett cvmx_sriox_s2m_typex_t needed_s2m_type; 1426215976Sjmallett cvmx_sli_mem_access_subidx_t needed_subid; 1427215976Sjmallett int s2m_index; 1428215976Sjmallett int subdid; 1429215976Sjmallett cvmx_sli_address_t sli_address; 1430215976Sjmallett 1431215976Sjmallett /* We currently don't support mapping regions that span a 34 bit boundary. 1432215976Sjmallett Keeping track of multiple regions to span 34 bits is hard and not 1433215976Sjmallett likely to be needed */ 1434215976Sjmallett if (((base+size-1)>>34) != (base>>34)) 1435215976Sjmallett { 1436215976Sjmallett cvmx_dprintf("SRIO%d: Failed to map range 0x%llx-0x%llx spanning a 34bit boundary\n", 1437215976Sjmallett srio_port, (ULL)base, (ULL)base+size-1); 1438215976Sjmallett return 0; 1439215976Sjmallett } 1440215976Sjmallett 1441215976Sjmallett /* Build the S2M_TYPE we are going to need */ 1442215976Sjmallett needed_s2m_type.u64 = 0; 1443215976Sjmallett needed_s2m_type.s.wr_op = write_op; 1444215976Sjmallett needed_s2m_type.s.rd_op = read_op; 1445215976Sjmallett needed_s2m_type.s.wr_prior = write_priority; 1446215976Sjmallett needed_s2m_type.s.rd_prior = read_priority; 1447215976Sjmallett needed_s2m_type.s.src_id = srcid_index; 1448215976Sjmallett needed_s2m_type.s.id16 = !!is16bit; 1449215976Sjmallett 1450215976Sjmallett /* Build the needed SubID config */ 1451215976Sjmallett needed_subid.u64 = 0; 1452215976Sjmallett needed_subid.s.port = srio_port; 1453232812Sjmallett needed_subid.s.nmerge = 0; 1454215976Sjmallett 1455215976Sjmallett /* FIXME: We might want to use the device ID swapping modes so the device 1456215976Sjmallett ID is part of the lower address bits. This would allow many more 1457215976Sjmallett devices to share S2M_TYPE indexes. This would require "base+size-1" 1458215976Sjmallett to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */ 1459215976Sjmallett if (base < (1ull<<34)) 1460215976Sjmallett { 1461232812Sjmallett needed_subid.cn63xx.ba = destid; 1462215976Sjmallett needed_s2m_type.s.iaow_sel = 0; 1463215976Sjmallett } 1464215976Sjmallett else if (base < (1ull<<42)) 1465215976Sjmallett { 1466232812Sjmallett needed_subid.cn63xx.ba = (base>>34) & 0xff; 1467232812Sjmallett needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (42-34); 1468232812Sjmallett needed_subid.cn63xx.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34); 1469215976Sjmallett needed_s2m_type.s.iaow_sel = 1; 1470215976Sjmallett } 1471215976Sjmallett else 1472215976Sjmallett { 1473215976Sjmallett if (destid>>8) 1474215976Sjmallett { 1475215976Sjmallett cvmx_dprintf("SRIO%d: Attempt to map 16bit device ID 0x%x using 66bit addressing\n", srio_port, destid); 1476215976Sjmallett return 0; 1477215976Sjmallett } 1478215976Sjmallett if (base>>50) 1479215976Sjmallett { 1480215976Sjmallett cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base); 1481215976Sjmallett return 0; 1482215976Sjmallett } 1483232812Sjmallett needed_subid.cn63xx.ba = (base>>34) & 0xffff; 1484232812Sjmallett needed_subid.cn63xx.ba |= ((uint64_t)destid & 0xff) << (51-34); 1485215976Sjmallett needed_s2m_type.s.iaow_sel = 2; 1486215976Sjmallett } 1487215976Sjmallett 1488215976Sjmallett /* Find a S2M_TYPE index to use. If this fails return 0 */ 1489215976Sjmallett s2m_index = __cvmx_srio_alloc_s2m(srio_port, needed_s2m_type); 1490215976Sjmallett if (s2m_index == -1) 1491215976Sjmallett return 0; 1492215976Sjmallett 1493215976Sjmallett /* Attach the SubID to the S2M_TYPE index */ 1494215976Sjmallett needed_subid.s.rtype = s2m_index & 3; 1495215976Sjmallett needed_subid.s.wtype = s2m_index & 3; 1496232812Sjmallett needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34); 1497232812Sjmallett needed_subid.cn63xx.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34); 1498215976Sjmallett 1499215976Sjmallett /* Allocate a SubID for use */ 1500215976Sjmallett subdid = __cvmx_srio_alloc_subid(needed_subid); 1501215976Sjmallett if (subdid == -1) 1502215976Sjmallett { 1503215976Sjmallett /* Free the s2m_index as we aren't using it */ 1504215976Sjmallett __cvmx_srio_free_s2m(srio_port, s2m_index); 1505215976Sjmallett return 0; 1506215976Sjmallett } 1507215976Sjmallett 1508215976Sjmallett /* Build the final core physical address */ 1509215976Sjmallett sli_address.u64 = 0; 1510215976Sjmallett sli_address.mem.io = 1; 1511215976Sjmallett sli_address.mem.did = 3; 1512215976Sjmallett sli_address.mem.subdid = subdid>>2; 1513215976Sjmallett sli_address.mem.se = subdid & 3; 1514215976Sjmallett sli_address.mem.address = base; /* Bits[33:0] of full address */ 1515215976Sjmallett return sli_address.u64; 1516215976Sjmallett} 1517215976Sjmallett 1518215976Sjmallett 1519215976Sjmallett/** 1520215976Sjmallett * Unmap a physical address window created by cvmx_srio_phys_map(). 1521215976Sjmallett * 1522215976Sjmallett * @param physical_address 1523215976Sjmallett * Physical address returned by cvmx_srio_phys_map(). 1524215976Sjmallett * @param size Size used on original call. 1525215976Sjmallett * 1526215976Sjmallett * @return Zero on success, negative on failure. 1527215976Sjmallett */ 1528215976Sjmallettint cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size) 1529215976Sjmallett{ 1530215976Sjmallett cvmx_sli_mem_access_subidx_t subid; 1531215976Sjmallett int subdid = (physical_address >> 40) & 7; 1532215976Sjmallett int extender = (physical_address >> 34) & 3; 1533215976Sjmallett int mem_index = subdid * 4 + extender; 1534215976Sjmallett int read_s2m_type; 1535215976Sjmallett 1536215976Sjmallett /* Get the subid setup so we can figure out where this mapping was for */ 1537215976Sjmallett subid.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)); 1538215976Sjmallett /* Type[0] is mapped to the Relaxed Ordering 1539215976Sjmallett Type[1] is mapped to the No Snoop 1540215976Sjmallett Type[2] is mapped directly to bit 50 of the SLI address 1541215976Sjmallett Type[3] is mapped directly to bit 59 of the SLI address */ 1542232812Sjmallett read_s2m_type = ((subid.cn63xx.ba>>(50-34))&1<<2) | ((subid.cn63xx.ba>>(59-34))&1<<3); 1543215976Sjmallett read_s2m_type |= subid.s.rtype; 1544215976Sjmallett __cvmx_srio_free_subid(mem_index); 1545215976Sjmallett __cvmx_srio_free_s2m(subid.s.port, read_s2m_type); 1546215976Sjmallett return 0; 1547215976Sjmallett} 1548232812Sjmallett 1549232812Sjmallett#ifdef CVMX_ENABLE_PKO_FUNCTIONS 1550232812Sjmallett/** 1551232812Sjmallett * fill out outbound message descriptor 1552232812Sjmallett * 1553232812Sjmallett * @param port pip/ipd port number 1554232812Sjmallett * @param buf_ptr pointer to a buffer pointer. the buffer pointer points 1555232812Sjmallett * to a chain of buffers that hold an outbound srio packet. 1556232812Sjmallett * the packet can take the format of (1) a pip/ipd inbound 1557232812Sjmallett * message or (2) an application-generated outbound message 1558232812Sjmallett * @param desc_ptr pointer to an outbound message descriptor. should be null 1559232812Sjmallett * if *buf_ptr is in the format (1) 1560232812Sjmallett * 1561232812Sjmallett * @return 0 on success; negative of failure. 1562232812Sjmallett */ 1563232812Sjmallettint cvmx_srio_omsg_desc (uint64_t port, cvmx_buf_ptr_t *buf_ptr, 1564232812Sjmallett cvmx_srio_tx_message_header_t *desc_ptr) 1565232812Sjmallett{ 1566232812Sjmallett int ret_val = -1; 1567232812Sjmallett int intf_num; 1568232812Sjmallett cvmx_helper_interface_mode_t imode; 1569232812Sjmallett 1570232812Sjmallett uint64_t *desc_addr, *hdr_addr; 1571232812Sjmallett cvmx_srio_rx_message_header_t rx_msg_hdr; 1572232812Sjmallett cvmx_srio_tx_message_header_t *tx_msg_hdr_ptr; 1573232812Sjmallett 1574232812Sjmallett if (buf_ptr == NULL) 1575232812Sjmallett return ret_val; 1576232812Sjmallett 1577232812Sjmallett /* check if port is an srio port */ 1578232812Sjmallett intf_num = cvmx_helper_get_interface_num (port); 1579232812Sjmallett imode = cvmx_helper_interface_get_mode (intf_num); 1580232812Sjmallett if (imode != CVMX_HELPER_INTERFACE_MODE_SRIO) 1581232812Sjmallett return ret_val; 1582232812Sjmallett 1583232812Sjmallett /* app-generated outbound message. descriptor space pre-allocated */ 1584232812Sjmallett if (desc_ptr != NULL) 1585232812Sjmallett { 1586232812Sjmallett desc_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr); 1587232812Sjmallett *desc_addr = *(uint64_t *) desc_ptr; 1588232812Sjmallett ret_val = 0; 1589232812Sjmallett return ret_val; 1590232812Sjmallett } 1591232812Sjmallett 1592232812Sjmallett /* pip/ipd inbound message. 16-byte srio message header is present */ 1593232812Sjmallett hdr_addr = (uint64_t *) cvmx_phys_to_ptr ((*buf_ptr).s.addr); 1594232812Sjmallett rx_msg_hdr.word0.u64 = *hdr_addr; 1595232812Sjmallett 1596232812Sjmallett /* adjust buffer pointer to get rid of srio message header word 0 */ 1597232812Sjmallett (*buf_ptr).s.addr += 8; 1598232812Sjmallett (*buf_ptr).s.size -= 8; /* last buffer or not */ 1599232812Sjmallett if ((*buf_ptr).s.addr >> 7 > ((*buf_ptr).s.addr - 8) >> 7) 1600232812Sjmallett (*buf_ptr).s.back++; 1601232812Sjmallett tx_msg_hdr_ptr = (cvmx_srio_tx_message_header_t *) 1602232812Sjmallett cvmx_phys_to_ptr ((*buf_ptr).s.addr); 1603232812Sjmallett 1604232812Sjmallett /* transfer values from rx to tx */ 1605232812Sjmallett tx_msg_hdr_ptr->s.prio = rx_msg_hdr.word0.s.prio; 1606232812Sjmallett tx_msg_hdr_ptr->s.tt = rx_msg_hdr.word0.s.tt; /* called id in hrm */ 1607232812Sjmallett tx_msg_hdr_ptr->s.sis = rx_msg_hdr.word0.s.dis; 1608232812Sjmallett tx_msg_hdr_ptr->s.ssize = rx_msg_hdr.word0.s.ssize; 1609232812Sjmallett tx_msg_hdr_ptr->s.did = rx_msg_hdr.word0.s.sid; 1610232812Sjmallett tx_msg_hdr_ptr->s.mbox = rx_msg_hdr.word0.s.mbox; 1611232812Sjmallett 1612232812Sjmallett /* other values we have to decide */ 1613232812Sjmallett tx_msg_hdr_ptr->s.xmbox = 0; /* multi-segement in general */ 1614232812Sjmallett tx_msg_hdr_ptr->s.letter = 0; /* fake like traffic gen */ 1615232812Sjmallett tx_msg_hdr_ptr->s.lns = 0; /* not use sriox_omsg_ctrly[] */ 1616232812Sjmallett tx_msg_hdr_ptr->s.intr = 1; /* get status */ 1617232812Sjmallett 1618232812Sjmallett ret_val = 0; 1619232812Sjmallett return ret_val; 1620232812Sjmallett} 1621215976Sjmallett#endif 1622232812Sjmallett#endif 1623