1215976Sjmallett/***********************license start*************** 2215976Sjmallett * Copyright (c) 2003-2010 Cavium Networks (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 18215976Sjmallett * * Neither the name of Cavium Networks 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" 29215976Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS 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> 63215976Sjmallett#else 64215976Sjmallett#include "cvmx.h" 65215976Sjmallett#include "cvmx-srio.h" 66215976Sjmallett#include "cvmx-clock.h" 67215976Sjmallett#include "cvmx-helper.h" 68215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 69215976Sjmallett#include "cvmx-atomic.h" 70215976Sjmallett#include "cvmx-error.h" 71215976Sjmallett#include "cvmx-helper-errata.h" 72215976Sjmallett#endif 73215976Sjmallett#endif 74215976Sjmallett 75215976Sjmallett#define CVMX_SRIO_USE_FIFO_FOR_MAINT 1 76215976Sjmallett#define CVMX_SRIO_CONFIG_TIMEOUT 10000 /* 10ms */ 77215976Sjmallett#define CVMX_SRIO_DOORBELL_TIMEOUT 10000 /* 10ms */ 78215976Sjmallett#define CVMX_SRIO_CONFIG_PRIORITY 0 79215976Sjmallett#define ULL unsigned long long 80215976Sjmallett 81215976Sjmalletttypedef union 82215976Sjmallett{ 83215976Sjmallett uint64_t u64; 84215976Sjmallett struct 85215976Sjmallett { 86215976Sjmallett#if __BYTE_ORDER == __BIG_ENDIAN 87215976Sjmallett uint64_t upper : 2; /* Normally 2 for XKPHYS */ 88215976Sjmallett uint64_t reserved_49_61 : 13; /* Must be zero */ 89215976Sjmallett uint64_t io : 1; /* 1 for IO space access */ 90215976Sjmallett uint64_t did : 5; /* DID = 3 */ 91215976Sjmallett uint64_t subdid : 3; /* SubDID = 3-6 */ 92215976Sjmallett uint64_t reserved_36_39 : 4; /* Must be zero */ 93215976Sjmallett uint64_t se : 2; /* SubDID extender */ 94215976Sjmallett uint64_t reserved_32_33 : 2; /* Must be zero */ 95215976Sjmallett uint64_t hopcount : 8; /* Hopcount */ 96215976Sjmallett uint64_t address : 24; /* Mem address */ 97215976Sjmallett#else 98215976Sjmallett uint64_t address : 24; 99215976Sjmallett uint64_t hopcount : 8; 100215976Sjmallett uint64_t reserved_32_33 : 2; 101215976Sjmallett uint64_t se : 2; 102215976Sjmallett uint64_t reserved_36_39 : 4; 103215976Sjmallett uint64_t subdid : 3; 104215976Sjmallett uint64_t did : 5; 105215976Sjmallett uint64_t io : 1; 106215976Sjmallett uint64_t reserved_49_61 : 13; 107215976Sjmallett uint64_t upper : 2; 108215976Sjmallett#endif 109215976Sjmallett } config; 110215976Sjmallett struct 111215976Sjmallett { 112215976Sjmallett#if __BYTE_ORDER == __BIG_ENDIAN 113215976Sjmallett uint64_t upper : 2; /* Normally 2 for XKPHYS */ 114215976Sjmallett uint64_t reserved_49_61 : 13; /* Must be zero */ 115215976Sjmallett uint64_t io : 1; /* 1 for IO space access */ 116215976Sjmallett uint64_t did : 5; /* DID = 3 */ 117215976Sjmallett uint64_t subdid : 3; /* SubDID = 3-6 */ 118215976Sjmallett uint64_t reserved_36_39 : 4; /* Must be zero */ 119215976Sjmallett uint64_t se : 2; /* SubDID extender */ 120215976Sjmallett uint64_t address : 34; /* Mem address */ 121215976Sjmallett#else 122215976Sjmallett uint64_t address : 34; 123215976Sjmallett uint64_t se : 2; 124215976Sjmallett uint64_t reserved_36_39 : 4; 125215976Sjmallett uint64_t subdid : 3; 126215976Sjmallett uint64_t did : 5; 127215976Sjmallett uint64_t io : 1; 128215976Sjmallett uint64_t reserved_49_61 : 13; 129215976Sjmallett uint64_t upper : 2; 130215976Sjmallett#endif 131215976Sjmallett } mem; 132215976Sjmallett} cvmx_sli_address_t; 133215976Sjmallett 134215976Sjmalletttypedef struct 135215976Sjmallett{ 136215976Sjmallett cvmx_srio_initialize_flags_t flags; 137215976Sjmallett int32_t subidx_ref_count[16]; /* Reference count for SLI_MEM_ACCESS_SUBID[12-27]. Index=X-12 */ 138215976Sjmallett int32_t s2m_ref_count[16]; /* Reference count for SRIOX_S2M_TYPE[0-15]. */ 139215976Sjmallett} __cvmx_srio_state_t; 140215976Sjmallett 141215976Sjmallettstatic CVMX_SHARED __cvmx_srio_state_t __cvmx_srio_state[2]; 142215976Sjmallett 143215976Sjmallett 144215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 145215976Sjmallett/** 146215976Sjmallett * @INTERNAL 147215976Sjmallett * Allocate a SRIOX_S2M_TYPEX register for mapping a remote SRIO 148215976Sjmallett * device's address range into Octeons SLI address space. Reference 149215976Sjmallett * counting is used to allow sharing of duplicate setups. The current 150215976Sjmallett * implementation treats reads and writes as paired, but this could be 151215976Sjmallett * changed if we have trouble running out of indexes. 152215976Sjmallett * 153215976Sjmallett * @param srio_port SRIO port device is on 154215976Sjmallett * @param s2m SRIOX_S2M_TYPEX setup required 155215976Sjmallett * 156215976Sjmallett * @return Index of CSR, or negative on failure 157215976Sjmallett */ 158215976Sjmallettstatic int __cvmx_srio_alloc_s2m(int srio_port, cvmx_sriox_s2m_typex_t s2m) 159215976Sjmallett{ 160215976Sjmallett int s2m_index; 161215976Sjmallett /* Search through the S2M_TYPE registers looking for an unsed one or one 162215976Sjmallett setup the way we need it */ 163215976Sjmallett for (s2m_index=0; s2m_index<16; s2m_index++) 164215976Sjmallett { 165215976Sjmallett /* Increment ref count by 2 since we count read and write 166215976Sjmallett independently. We might need a more complicated search in the 167215976Sjmallett future */ 168215976Sjmallett int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], 2); 169215976Sjmallett if (ref_count == 0) 170215976Sjmallett { 171215976Sjmallett /* Unused location. Write our value */ 172215976Sjmallett cvmx_write_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port), s2m.u64); 173215976Sjmallett return s2m_index; 174215976Sjmallett } 175215976Sjmallett else 176215976Sjmallett { 177215976Sjmallett /* In use, see if we can use it */ 178215976Sjmallett if (cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(s2m_index, srio_port)) == s2m.u64) 179215976Sjmallett return s2m_index; 180215976Sjmallett else 181215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[s2m_index], -2); 182215976Sjmallett } 183215976Sjmallett } 184215976Sjmallett cvmx_dprintf("SRIO%d: Unable to find free SRIOX_S2M_TYPEX\n", srio_port); 185215976Sjmallett return -1; 186215976Sjmallett} 187215976Sjmallett 188215976Sjmallett 189215976Sjmallett/** 190215976Sjmallett * @INTERNAL 191215976Sjmallett * Free a handle allocated by __cvmx_srio_alloc_s2m 192215976Sjmallett * 193215976Sjmallett * @param srio_port SRIO port 194215976Sjmallett * @param index Index to free 195215976Sjmallett */ 196215976Sjmallettstatic void __cvmx_srio_free_s2m(int srio_port, int index) 197215976Sjmallett{ 198215976Sjmallett /* Read to force pending transactions to complete */ 199215976Sjmallett cvmx_read_csr(CVMX_SRIOX_S2M_TYPEX(index, srio_port)); 200215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[srio_port].s2m_ref_count[index], -2); 201215976Sjmallett} 202215976Sjmallett 203215976Sjmallett 204215976Sjmallett/** 205215976Sjmallett * @INTERNAL 206215976Sjmallett * Allocate a SLI SubID to map a region of memory. Reference 207215976Sjmallett * counting is used to allow sharing of duplicate setups. 208215976Sjmallett * 209215976Sjmallett * @param subid SLI_MEM_ACCESS_SUBIDX we need an index for 210215976Sjmallett * 211215976Sjmallett * @return Index of CSR, or negative on failure 212215976Sjmallett */ 213215976Sjmallettstatic int __cvmx_srio_alloc_subid(cvmx_sli_mem_access_subidx_t subid) 214215976Sjmallett{ 215215976Sjmallett int mem_index; 216215976Sjmallett /* Search through the mem access subid registers looking for an unsed one 217215976Sjmallett or one setup the way we need it. PCIe uses the low indexes, so search 218215976Sjmallett backwards */ 219215976Sjmallett for (mem_index=27; mem_index>=12; mem_index--) 220215976Sjmallett { 221215976Sjmallett int ref_count = cvmx_atomic_fetch_and_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], 1); 222215976Sjmallett if (ref_count == 0) 223215976Sjmallett { 224215976Sjmallett /* Unused location. Write our value */ 225215976Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index), subid.u64); 226215976Sjmallett return mem_index; 227215976Sjmallett } 228215976Sjmallett else 229215976Sjmallett { 230215976Sjmallett /* In use, see if we can use it */ 231215976Sjmallett if (cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)) == subid.u64) 232215976Sjmallett return mem_index; 233215976Sjmallett else 234215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[mem_index-12], -1); 235215976Sjmallett } 236215976Sjmallett } 237215976Sjmallett cvmx_dprintf("SRIO: Unable to find free SLI_MEM_ACCESS_SUBIDX\n"); 238215976Sjmallett return -1; 239215976Sjmallett} 240215976Sjmallett 241215976Sjmallett 242215976Sjmallett/** 243215976Sjmallett * @INTERNAL 244215976Sjmallett * Free a handle allocated by __cvmx_srio_alloc_subid 245215976Sjmallett * 246215976Sjmallett * @param index Index to free 247215976Sjmallett */ 248215976Sjmallettstatic void __cvmx_srio_free_subid(int index) 249215976Sjmallett{ 250215976Sjmallett /* Read to force pending transactions to complete */ 251215976Sjmallett cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(index)); 252215976Sjmallett cvmx_atomic_add32(&__cvmx_srio_state[0].subidx_ref_count[index-12], -1); 253215976Sjmallett} 254215976Sjmallett#endif 255215976Sjmallett 256215976Sjmallett 257215976Sjmallett/** 258215976Sjmallett * @INTERNAL 259215976Sjmallett * Read 32bits from a local port 260215976Sjmallett * 261215976Sjmallett * @param srio_port SRIO port the device is on 262215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 263215976Sjmallett * @param result Result of the read. This will be unmodified on failure. 264215976Sjmallett * 265215976Sjmallett * @return Zero on success, negative on failure. 266215976Sjmallett */ 267215976Sjmallettstatic int __cvmx_srio_local_read32(int srio_port, uint32_t offset, uint32_t *result) 268215976Sjmallett{ 269215976Sjmallett cvmx_sriox_maint_op_t maint_op; 270215976Sjmallett cvmx_sriox_maint_rd_data_t maint_rd_data; 271215976Sjmallett maint_op.u64 = 0; 272215976Sjmallett maint_op.s.op = 0; /* Read */ 273215976Sjmallett maint_op.s.addr = offset; 274215976Sjmallett 275215976Sjmallett /* Make sure SRIO isn't already busy */ 276215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 277215976Sjmallett { 278215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before config read\n", srio_port); 279215976Sjmallett return -1; 280215976Sjmallett } 281215976Sjmallett 282215976Sjmallett /* Issue the read to the hardware */ 283215976Sjmallett cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64); 284215976Sjmallett 285215976Sjmallett /* Wait for the hardware to complete the operation */ 286215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 287215976Sjmallett { 288215976Sjmallett cvmx_dprintf("SRIO%d: Config read timeout\n", srio_port); 289215976Sjmallett return -1; 290215976Sjmallett } 291215976Sjmallett 292215976Sjmallett /* Display and error and return if the operation failed to issue */ 293215976Sjmallett maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port)); 294215976Sjmallett if (maint_op.s.fail) 295215976Sjmallett { 296215976Sjmallett cvmx_dprintf("SRIO%d: Config read addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset); 297215976Sjmallett return -1; 298215976Sjmallett } 299215976Sjmallett 300215976Sjmallett /* Wait for the read data to become valid */ 301215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_RD_DATA(srio_port), cvmx_sriox_maint_rd_data_t, valid, ==, 1, CVMX_SRIO_CONFIG_TIMEOUT)) 302215976Sjmallett { 303215976Sjmallett cvmx_dprintf("SRIO%d: Config read data timeout\n", srio_port); 304215976Sjmallett return -1; 305215976Sjmallett } 306215976Sjmallett 307215976Sjmallett /* Get the read data */ 308215976Sjmallett maint_rd_data.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_RD_DATA(srio_port)); 309215976Sjmallett *result = maint_rd_data.s.rd_data; 310215976Sjmallett return 0; 311215976Sjmallett} 312215976Sjmallett 313215976Sjmallett 314215976Sjmallett/** 315215976Sjmallett * @INTERNAL 316215976Sjmallett * Write 32bits to a local port 317215976Sjmallett * @param srio_port SRIO port the device is on 318215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 319215976Sjmallett * @param data Data to write. 320215976Sjmallett * 321215976Sjmallett * @return Zero on success, negative on failure. 322215976Sjmallett */ 323215976Sjmallettstatic int __cvmx_srio_local_write32(int srio_port, uint32_t offset, uint32_t data) 324215976Sjmallett{ 325215976Sjmallett cvmx_sriox_maint_op_t maint_op; 326215976Sjmallett maint_op.u64 = 0; 327215976Sjmallett maint_op.s.wr_data = data; 328215976Sjmallett maint_op.s.op = 1; /* Write */ 329215976Sjmallett maint_op.s.addr = offset; 330215976Sjmallett 331215976Sjmallett /* Make sure SRIO isn't already busy */ 332215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 333215976Sjmallett { 334215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before config write\n", srio_port); 335215976Sjmallett return -1; 336215976Sjmallett } 337215976Sjmallett 338215976Sjmallett /* Issue the write to the hardware */ 339215976Sjmallett cvmx_write_csr(CVMX_SRIOX_MAINT_OP(srio_port), maint_op.u64); 340215976Sjmallett 341215976Sjmallett /* Wait for the hardware to complete the operation */ 342215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_MAINT_OP(srio_port), cvmx_sriox_maint_op_t, pending, ==, 0, CVMX_SRIO_CONFIG_TIMEOUT)) 343215976Sjmallett { 344215976Sjmallett cvmx_dprintf("SRIO%d: Config write timeout\n", srio_port); 345215976Sjmallett return -1; 346215976Sjmallett } 347215976Sjmallett 348215976Sjmallett /* Display and error and return if the operation failed to issue */ 349215976Sjmallett maint_op.u64 = cvmx_read_csr(CVMX_SRIOX_MAINT_OP(srio_port)); 350215976Sjmallett if (maint_op.s.fail) 351215976Sjmallett { 352215976Sjmallett cvmx_dprintf("SRIO%d: Config write addressing error (offset=0x%x)\n", srio_port, (unsigned int)offset); 353215976Sjmallett return -1; 354215976Sjmallett } 355215976Sjmallett return 0; 356215976Sjmallett} 357215976Sjmallett 358215976Sjmallett 359215976Sjmallett/** 360215976Sjmallett * Initialize a SRIO port for use. 361215976Sjmallett * 362215976Sjmallett * @param srio_port SRIO port to initialize 363215976Sjmallett * @param flags Optional flags 364215976Sjmallett * 365215976Sjmallett * @return Zero on success 366215976Sjmallett */ 367215976Sjmallettint cvmx_srio_initialize(int srio_port, cvmx_srio_initialize_flags_t flags) 368215976Sjmallett{ 369215976Sjmallett cvmx_sriomaintx_port_lt_ctl_t port_lt_ctl; 370215976Sjmallett cvmx_sriomaintx_port_rt_ctl_t port_rt_ctl; 371215976Sjmallett cvmx_sriomaintx_port_0_ctl_t port_0_ctl; 372215976Sjmallett cvmx_sriomaintx_core_enables_t core_enables; 373215976Sjmallett cvmx_sriomaintx_port_gen_ctl_t port_gen_ctl; 374215976Sjmallett cvmx_sriox_status_reg_t sriox_status_reg; 375215976Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 376215976Sjmallett cvmx_sriox_imsg_vport_thr_t sriox_imsg_vport_thr; 377215976Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 378215976Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 379215976Sjmallett 380215976Sjmallett sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(srio_port)); 381215976Sjmallett if (!sriox_status_reg.s.srio) 382215976Sjmallett { 383215976Sjmallett cvmx_dprintf("SRIO%d: Initialization called on a port not in SRIO mode\n", srio_port); 384215976Sjmallett return -1; 385215976Sjmallett } 386215976Sjmallett 387215976Sjmallett __cvmx_srio_state[srio_port].flags = flags; 388215976Sjmallett 389215976Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be 390215976Sjmallett programmed */ 391215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 392215976Sjmallett { 393215976Sjmallett if (srio_port) 394215976Sjmallett { 395215976Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 396215976Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 397215976Sjmallett ciu_qlm.s.txbypass = 1; 398215976Sjmallett ciu_qlm.s.txdeemph = 5; 399215976Sjmallett ciu_qlm.s.txmargin = 0x17; 400215976Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 401215976Sjmallett } 402215976Sjmallett else 403215976Sjmallett { 404215976Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 405215976Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 406215976Sjmallett ciu_qlm.s.txbypass = 1; 407215976Sjmallett ciu_qlm.s.txdeemph = 5; 408215976Sjmallett ciu_qlm.s.txmargin = 0x17; 409215976Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 410215976Sjmallett } 411215976Sjmallett } 412215976Sjmallett 413215976Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(srio_port)); 414215976Sjmallett cvmx_dprintf("SRIO%d: Port in %s mode\n", srio_port, 415215976Sjmallett (mio_rst_ctl.s.prtmode) ? "host" : "endpoint"); 416215976Sjmallett 417215976Sjmallett /* Bring the port out of reset if necessary */ 418215976Sjmallett if (srio_port) 419215976Sjmallett { 420215976Sjmallett cvmx_ciu_soft_prst1_t prst; 421215976Sjmallett prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 422215976Sjmallett if (prst.s.soft_prst) 423215976Sjmallett { 424215976Sjmallett prst.s.soft_prst = 0; 425215976Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, prst.u64); 426215976Sjmallett cvmx_wait_usec(10000); /* 10ms for new link to stabalize */ 427215976Sjmallett } 428215976Sjmallett } 429215976Sjmallett else 430215976Sjmallett { 431215976Sjmallett cvmx_ciu_soft_prst_t prst; 432215976Sjmallett prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 433215976Sjmallett if (prst.s.soft_prst) 434215976Sjmallett { 435215976Sjmallett prst.s.soft_prst = 0; 436215976Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, prst.u64); 437215976Sjmallett cvmx_wait_usec(10000); /* 10ms for new link to stabalize */ 438215976Sjmallett } 439215976Sjmallett } 440215976Sjmallett 441215976Sjmallett /* Disable the link while we make changes */ 442215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32)) 443215976Sjmallett return -1; 444215976Sjmallett port_0_ctl.s.disable = 1; 445215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) 446215976Sjmallett return -1; 447215976Sjmallett 448215976Sjmallett /* Errata SRIO-14485: Link speed is reported incorrectly in CN63XX 449215976Sjmallett pass 1.x */ 450215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 451215976Sjmallett { 452215976Sjmallett cvmx_sriomaintx_port_0_ctl2_t port_0_ctl2; 453215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), &port_0_ctl2.u32)) 454215976Sjmallett return -1; 455215976Sjmallett if (port_0_ctl2.s.enb_500g) 456215976Sjmallett { 457215976Sjmallett port_0_ctl2.u32 = 0; 458215976Sjmallett port_0_ctl2.s.enb_625g = 1; 459215976Sjmallett } 460215976Sjmallett else if (port_0_ctl2.s.enb_312g) 461215976Sjmallett { 462215976Sjmallett port_0_ctl2.u32 = 0; 463215976Sjmallett port_0_ctl2.s.enb_500g = 1; 464215976Sjmallett } 465215976Sjmallett else if (port_0_ctl2.s.enb_250g) 466215976Sjmallett { 467215976Sjmallett port_0_ctl2.u32 = 0; 468215976Sjmallett port_0_ctl2.s.enb_312g = 1; 469215976Sjmallett } 470215976Sjmallett else if (port_0_ctl2.s.enb_125g) 471215976Sjmallett { 472215976Sjmallett port_0_ctl2.u32 = 0; 473215976Sjmallett port_0_ctl2.s.enb_250g = 1; 474215976Sjmallett } 475215976Sjmallett else 476215976Sjmallett { 477215976Sjmallett port_0_ctl2.u32 = 0; 478215976Sjmallett port_0_ctl2.s.enb_125g = 1; 479215976Sjmallett } 480215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL2(srio_port), port_0_ctl2.u32)) 481215976Sjmallett return -1; 482215976Sjmallett } 483215976Sjmallett 484215976Sjmallett /* Set the link layer timeout to 10us. The default is too high and causes 485215976Sjmallett core bus errors */ 486215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), &port_lt_ctl.u32)) 487215976Sjmallett return -1; 488215976Sjmallett port_lt_ctl.s.timeout = 10000 / 200; /* 10us = 10000ns / 200ns */ 489215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_LT_CTL(srio_port), port_lt_ctl.u32)) 490215976Sjmallett return -1; 491215976Sjmallett 492215976Sjmallett /* Set the logical layer timeout to 10ms. The default is too high and causes 493215976Sjmallett core bus errors */ 494215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), &port_rt_ctl.u32)) 495215976Sjmallett return -1; 496215976Sjmallett port_rt_ctl.s.timeout = 10000000 / 200; /* 10ms = 10000000ns / 200ns */ 497215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_RT_CTL(srio_port), port_rt_ctl.u32)) 498215976Sjmallett return -1; 499215976Sjmallett 500215976Sjmallett /* Allow memory and doorbells. Messaging is enabled later */ 501215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), &core_enables.u32)) 502215976Sjmallett return -1; 503215976Sjmallett core_enables.s.doorbell = 1; 504215976Sjmallett core_enables.s.memory = 1; 505215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_CORE_ENABLES(srio_port), core_enables.u32)) 506215976Sjmallett return -1; 507215976Sjmallett 508215976Sjmallett /* Allow us to master transactions */ 509215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), &port_gen_ctl.u32)) 510215976Sjmallett return -1; 511215976Sjmallett port_gen_ctl.s.menable = 1; 512215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_GEN_CTL(srio_port), port_gen_ctl.u32)) 513215976Sjmallett return -1; 514215976Sjmallett 515215976Sjmallett /* Set the MRRS and MPS for optimal SRIO performance */ 516215976Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port)); 517215976Sjmallett prt_cfg.s.mps = 1; 518215976Sjmallett prt_cfg.s.mrrs = 1; 519215976Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(srio_port), prt_cfg.u64); 520215976Sjmallett 521215976Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port)); 522215976Sjmallett sli_s2m_portx_ctl.s.mrrs = 1; 523215976Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(srio_port), sli_s2m_portx_ctl.u64); 524215976Sjmallett 525215976Sjmallett /* Setup RX messaging thresholds */ 526215976Sjmallett sriox_imsg_vport_thr.u64 = cvmx_read_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port)); 527215976Sjmallett sriox_imsg_vport_thr.s.max_tot = 48; 528215976Sjmallett sriox_imsg_vport_thr.s.max_s1 = 24; 529215976Sjmallett sriox_imsg_vport_thr.s.max_s0 = 24; 530215976Sjmallett sriox_imsg_vport_thr.s.sp_vport = 1; 531215976Sjmallett sriox_imsg_vport_thr.s.buf_thr = 4; 532215976Sjmallett sriox_imsg_vport_thr.s.max_p1 = 12; 533215976Sjmallett sriox_imsg_vport_thr.s.max_p0 = 12; 534215976Sjmallett cvmx_write_csr(CVMX_SRIOX_IMSG_VPORT_THR(srio_port), sriox_imsg_vport_thr.u64); 535215976Sjmallett 536215976Sjmallett /* Errata SRIO-X: SRIO error behavior may not be optimal in CN63XX pass 1.x */ 537215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 538215976Sjmallett { 539215976Sjmallett cvmx_sriox_tx_ctrl_t sriox_tx_ctrl; 540215976Sjmallett sriox_tx_ctrl.u64 = cvmx_read_csr(CVMX_SRIOX_TX_CTRL(srio_port)); 541215976Sjmallett sriox_tx_ctrl.s.tag_th2 = 2; 542215976Sjmallett sriox_tx_ctrl.s.tag_th1 = 3; 543215976Sjmallett sriox_tx_ctrl.s.tag_th0 = 4; 544215976Sjmallett cvmx_write_csr(CVMX_SRIOX_TX_CTRL(srio_port), sriox_tx_ctrl.u64); 545215976Sjmallett } 546215976Sjmallett 547215976Sjmallett /* Clear any pending interrupts */ 548215976Sjmallett cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port))); 549215976Sjmallett 550215976Sjmallett /* Enable error reporting */ 551215976Sjmallett#if (!defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_LINUX_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL) 552215976Sjmallett cvmx_error_enable_group(CVMX_ERROR_GROUP_SRIO, srio_port); 553215976Sjmallett#endif 554215976Sjmallett 555215976Sjmallett /* Finally enable the link */ 556215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), &port_0_ctl.u32)) 557215976Sjmallett return -1; 558215976Sjmallett port_0_ctl.s.o_enable = 1; 559215976Sjmallett port_0_ctl.s.i_enable = 1; 560215976Sjmallett port_0_ctl.s.disable = 0; 561215976Sjmallett port_0_ctl.s.prt_lock = 0; 562215976Sjmallett if (__cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_PORT_0_CTL(srio_port), port_0_ctl.u32)) 563215976Sjmallett return -1; 564215976Sjmallett 565215976Sjmallett return 0; 566215976Sjmallett} 567215976Sjmallett 568215976Sjmallett 569215976Sjmallett/** 570215976Sjmallett * Read 32bits from a Device's config space 571215976Sjmallett * 572215976Sjmallett * @param srio_port SRIO port the device is on 573215976Sjmallett * @param srcid_index 574215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 575215976Sjmallett * @param destid RapidIO device ID, or -1 for the local Octeon. 576215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 577215976Sjmallett * if transactions should use 8bit device IDs. 578215976Sjmallett * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon. 579215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 580215976Sjmallett * @param result Result of the read. This will be unmodified on failure. 581215976Sjmallett * 582215976Sjmallett * @return Zero on success, negative on failure. 583215976Sjmallett */ 584215976Sjmallettint cvmx_srio_config_read32(int srio_port, int srcid_index, int destid, 585215976Sjmallett int is16bit, uint8_t hopcount, uint32_t offset, 586215976Sjmallett uint32_t *result) 587215976Sjmallett{ 588215976Sjmallett if (destid == -1) 589215976Sjmallett { 590215976Sjmallett int status = __cvmx_srio_local_read32(srio_port, offset, result); 591215976Sjmallett 592215976Sjmallett if ((status == 0) && (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG)) 593215976Sjmallett cvmx_dprintf("SRIO%d: Local read [0x%06x] <= 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)*result); 594215976Sjmallett 595215976Sjmallett return status; 596215976Sjmallett } 597215976Sjmallett else 598215976Sjmallett { 599215976Sjmallett#if CVMX_SRIO_USE_FIFO_FOR_MAINT 600215976Sjmallett int return_code; 601215976Sjmallett uint32_t pkt = 0; 602215976Sjmallett uint32_t sourceid; 603215976Sjmallett uint64_t stop_cycle; 604215976Sjmallett char rx_buffer[64]; 605215976Sjmallett 606215976Sjmallett /* Tell the user */ 607215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 608215976Sjmallett cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, (unsigned int)offset); 609215976Sjmallett 610215976Sjmallett /* Read the proper source ID */ 611215976Sjmallett if (srcid_index) 612215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); 613215976Sjmallett else 614215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); 615215976Sjmallett 616215976Sjmallett if (is16bit) 617215976Sjmallett { 618215976Sjmallett /* Use the 16bit source ID */ 619215976Sjmallett sourceid &= 0xffff; 620215976Sjmallett 621215976Sjmallett /* MAINT Reads are 11 bytes */ 622215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 11<<16); 623215976Sjmallett 624215976Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 625215976Sjmallett pkt |= 1 << 28; /* tt [29:28] */ 626215976Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 627215976Sjmallett pkt |= destid << 8; /* destID [23:8] */ 628215976Sjmallett pkt |= sourceid >> 8; /* sourceID [7:0] */ 629215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 630215976Sjmallett pkt = 0; 631215976Sjmallett pkt |= sourceid << 24; /* sourceID [31:24] */ 632215976Sjmallett pkt |= 0 << 20; /* transaction [23:20] */ 633215976Sjmallett pkt |= 8 << 16; /* rdsize [19:16] */ 634215976Sjmallett pkt |= 0xc0 << 8; /* srcTID [15:8] */ 635215976Sjmallett pkt |= hopcount; /* hopcount [7:0] */ 636215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 637215976Sjmallett pkt = 0; 638215976Sjmallett pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ 639215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 640215976Sjmallett } 641215976Sjmallett else 642215976Sjmallett { 643215976Sjmallett /* Use the 8bit source ID */ 644215976Sjmallett sourceid = (sourceid >> 16) & 0xff; 645215976Sjmallett 646215976Sjmallett /* MAINT Reads are 9 bytes */ 647215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 9<<16); 648215976Sjmallett 649215976Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 650215976Sjmallett pkt |= 0 << 28; /* tt [29:28] */ 651215976Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 652215976Sjmallett pkt |= destid << 16; /* destID [23:16] */ 653215976Sjmallett pkt |= sourceid << 8; /* sourceID [15:8] */ 654215976Sjmallett pkt |= 0 << 4; /* transaction [7:4] */ 655215976Sjmallett pkt |= 8 << 0; /* rdsize [3:0] */ 656215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 657215976Sjmallett pkt = 0; 658215976Sjmallett pkt |= 0xc0 << 24; /* srcTID [31:24] */ 659215976Sjmallett pkt |= hopcount << 16; /* hopcount [23:16] */ 660215976Sjmallett pkt |= offset >> 8; /* offset [15:0] */ 661215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 662215976Sjmallett pkt = 0; 663215976Sjmallett pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ 664215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 665215976Sjmallett } 666215976Sjmallett 667215976Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 668215976Sjmallett do 669215976Sjmallett { 670215976Sjmallett return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); 671215976Sjmallett if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) 672215976Sjmallett { 673215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 674215976Sjmallett cvmx_dprintf("timeout\n"); 675215976Sjmallett return_code = -1; 676215976Sjmallett } 677215976Sjmallett } while (return_code == 0); 678215976Sjmallett 679215976Sjmallett if (return_code == ((is16bit) ? 23 : 19)) 680215976Sjmallett { 681215976Sjmallett if (is16bit) 682215976Sjmallett { 683215976Sjmallett if (offset & 4) 684215976Sjmallett *result = *(uint32_t*)(rx_buffer + 15); 685215976Sjmallett else 686215976Sjmallett *result = *(uint32_t*)(rx_buffer + 11); 687215976Sjmallett } 688215976Sjmallett else 689215976Sjmallett { 690215976Sjmallett if (offset & 4) 691215976Sjmallett *result = *(uint32_t*)(rx_buffer + 13); 692215976Sjmallett else 693215976Sjmallett *result = *(uint32_t*)(rx_buffer + 9); 694215976Sjmallett } 695215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 696215976Sjmallett cvmx_dprintf("0x%08x\n", (unsigned int)*result); 697215976Sjmallett return_code = 0; 698215976Sjmallett } 699215976Sjmallett else 700215976Sjmallett { 701215976Sjmallett *result = 0xffffffff; 702215976Sjmallett return_code = -1; 703215976Sjmallett } 704215976Sjmallett 705215976Sjmallett return return_code; 706215976Sjmallett#elif !defined(CVMX_BUILD_FOR_LINUX_HOST) 707215976Sjmallett uint64_t physical; 708215976Sjmallett physical = cvmx_srio_physical_map(srio_port, 709215976Sjmallett CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 710215976Sjmallett CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 711215976Sjmallett srcid_index, destid, is16bit, offset + (hopcount<<24), 4); 712215976Sjmallett if (!physical) 713215976Sjmallett return -1; 714215976Sjmallett 715215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 716215976Sjmallett cvmx_dprintf("SRIO%d: Remote read [id=0x%04x hop=%3d offset=0x%06x] <= ", srio_port, destid, hopcount, offset); 717215976Sjmallett 718215976Sjmallett /* Finally do the maintenance read to complete the config request */ 719215976Sjmallett *result = cvmx_read64_uint32(CVMX_ADD_IO_SEG(physical)); 720215976Sjmallett cvmx_srio_physical_unmap(physical, 4); 721215976Sjmallett 722215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 723215976Sjmallett cvmx_dprintf("0x%08x\n", *result); 724215976Sjmallett 725215976Sjmallett return 0; 726215976Sjmallett#else 727215976Sjmallett return -1; 728215976Sjmallett#endif 729215976Sjmallett } 730215976Sjmallett} 731215976Sjmallett 732215976Sjmallett 733215976Sjmallett/** 734215976Sjmallett * Write 32bits to a Device's config space 735215976Sjmallett * 736215976Sjmallett * @param srio_port SRIO port the device is on 737215976Sjmallett * @param srcid_index 738215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 739215976Sjmallett * @param destid RapidIO device ID, or -1 for the local Octeon. 740215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 741215976Sjmallett * if transactions should use 8bit device IDs. 742215976Sjmallett * @param hopcount Number of hops to the remote device. Use 0 for the local Octeon. 743215976Sjmallett * @param offset Offset in config space. This must be a multiple of 32 bits. 744215976Sjmallett * @param data Data to write. 745215976Sjmallett * 746215976Sjmallett * @return Zero on success, negative on failure. 747215976Sjmallett */ 748215976Sjmallettint cvmx_srio_config_write32(int srio_port, int srcid_index, int destid, 749215976Sjmallett int is16bit, uint8_t hopcount, uint32_t offset, 750215976Sjmallett uint32_t data) 751215976Sjmallett{ 752215976Sjmallett if (destid == -1) 753215976Sjmallett { 754215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 755215976Sjmallett cvmx_dprintf("SRIO%d: Local write[0x%06x] => 0x%08x\n", srio_port, (unsigned int)offset, (unsigned int)data); 756215976Sjmallett 757215976Sjmallett return __cvmx_srio_local_write32(srio_port, offset, data); 758215976Sjmallett } 759215976Sjmallett else 760215976Sjmallett { 761215976Sjmallett#if CVMX_SRIO_USE_FIFO_FOR_MAINT 762215976Sjmallett int return_code; 763215976Sjmallett uint32_t pkt = 0; 764215976Sjmallett uint32_t sourceid; 765215976Sjmallett uint64_t stop_cycle; 766215976Sjmallett char rx_buffer[64]; 767215976Sjmallett 768215976Sjmallett /* Tell the user */ 769215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 770215976Sjmallett 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); 771215976Sjmallett 772215976Sjmallett /* Read the proper source ID */ 773215976Sjmallett if (srcid_index) 774215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_SEC_DEV_ID(srio_port), &sourceid); 775215976Sjmallett else 776215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_PRI_DEV_ID(srio_port), &sourceid); 777215976Sjmallett 778215976Sjmallett if (is16bit) 779215976Sjmallett { 780215976Sjmallett /* Use the 16bit source ID */ 781215976Sjmallett sourceid &= 0xffff; 782215976Sjmallett 783215976Sjmallett /* MAINT Writes are 19 bytes */ 784215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 19<<16); 785215976Sjmallett 786215976Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 787215976Sjmallett pkt |= 1 << 28; /* tt [29:28] */ 788215976Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 789215976Sjmallett pkt |= destid << 8; /* destID [23:8] */ 790215976Sjmallett pkt |= sourceid >> 8; /* sourceID [7:0] */ 791215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 792215976Sjmallett pkt = 0; 793215976Sjmallett pkt |= sourceid << 24; /* sourceID [31:24] */ 794215976Sjmallett pkt |= 1 << 20; /* transaction [23:20] */ 795215976Sjmallett pkt |= 8 << 16; /* wrsize [19:16] */ 796215976Sjmallett pkt |= 0xc0 << 8; /* srcTID [15:8] */ 797215976Sjmallett pkt |= hopcount; /* hopcount [7:0] */ 798215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 799215976Sjmallett pkt = 0; 800215976Sjmallett pkt |= offset << 8; /* offset [31:11, wdptr[10], reserved[9:8] */ 801215976Sjmallett if ((offset & 4) == 0) 802215976Sjmallett pkt |= 0xff & (data >> 24); /* data [7:0] */ 803215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 804215976Sjmallett if (offset & 4) 805215976Sjmallett { 806215976Sjmallett pkt = 0xff & (data >> 24); 807215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 808215976Sjmallett pkt = data << 8; 809215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 810215976Sjmallett } 811215976Sjmallett else 812215976Sjmallett { 813215976Sjmallett pkt = data << 8; 814215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 815215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); 816215976Sjmallett } 817215976Sjmallett } 818215976Sjmallett else 819215976Sjmallett { 820215976Sjmallett /* Use the 8bit source ID */ 821215976Sjmallett sourceid = (sourceid >> 16) & 0xff; 822215976Sjmallett 823215976Sjmallett /* MAINT Writes are 17 bytes */ 824215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_CTRL(srio_port), 17<<16); 825215976Sjmallett 826215976Sjmallett pkt |= CVMX_SRIO_CONFIG_PRIORITY << 30; /* priority [31:30] */ 827215976Sjmallett pkt |= 0 << 28; /* tt [29:28] */ 828215976Sjmallett pkt |= 0x8 << 24; /* ftype [27:24] */ 829215976Sjmallett pkt |= destid << 16; /* destID [23:16] */ 830215976Sjmallett pkt |= sourceid << 8; /* sourceID [15:8] */ 831215976Sjmallett pkt |= 1 << 4; /* transaction [7:4] */ 832215976Sjmallett pkt |= 8 << 0; /* wrsize [3:0] */ 833215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 834215976Sjmallett pkt = 0; 835215976Sjmallett pkt |= 0xc0 << 24; /* srcTID [31:24] */ 836215976Sjmallett pkt |= hopcount << 16; /* hopcount [23:16] */ 837215976Sjmallett pkt |= offset >> 8; /* offset [15:0] */ 838215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 839215976Sjmallett pkt = 0; 840215976Sjmallett pkt |= offset << 24; /* offset [31:27, wdptr[26], reserved[25:24] */ 841215976Sjmallett if (offset & 4) 842215976Sjmallett { 843215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 844215976Sjmallett pkt = data >> 8; 845215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 846215976Sjmallett pkt = data << 24; 847215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 848215976Sjmallett } 849215976Sjmallett else 850215976Sjmallett { 851215976Sjmallett pkt |= data >> 8; /* data [23:0] */ 852215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 853215976Sjmallett pkt = data << 24; /* data [31:24] */ 854215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), pkt); 855215976Sjmallett __cvmx_srio_local_write32(srio_port, CVMX_SRIOMAINTX_IR_SP_TX_DATA(srio_port), 0); 856215976Sjmallett } 857215976Sjmallett } 858215976Sjmallett 859215976Sjmallett stop_cycle = cvmx_clock_get_rate(CVMX_CLOCK_CORE)/10 + cvmx_clock_get_count(CVMX_CLOCK_CORE); 860215976Sjmallett do 861215976Sjmallett { 862215976Sjmallett return_code = cvmx_srio_receive_spf(srio_port, rx_buffer, sizeof(rx_buffer)); 863215976Sjmallett if ((return_code == 0) && (cvmx_clock_get_count(CVMX_CLOCK_CORE) > stop_cycle)) 864215976Sjmallett { 865215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 866215976Sjmallett cvmx_dprintf("timeout\n"); 867215976Sjmallett return_code = -1; 868215976Sjmallett } 869215976Sjmallett } while (return_code == 0); 870215976Sjmallett 871215976Sjmallett if (return_code == ((is16bit) ? 15 : 11)) 872215976Sjmallett return_code = 0; 873215976Sjmallett else 874215976Sjmallett { 875215976Sjmallett cvmx_dprintf("SRIO%d: Remote write failed\n", srio_port); 876215976Sjmallett return_code = -1; 877215976Sjmallett } 878215976Sjmallett 879215976Sjmallett return return_code; 880215976Sjmallett#elif !defined(CVMX_BUILD_FOR_LINUX_HOST) 881215976Sjmallett uint64_t physical = cvmx_srio_physical_map(srio_port, 882215976Sjmallett CVMX_SRIO_WRITE_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 883215976Sjmallett CVMX_SRIO_READ_MODE_MAINTENANCE, CVMX_SRIO_CONFIG_PRIORITY, 884215976Sjmallett srcid_index, destid, is16bit, offset + (hopcount<<24), 4); 885215976Sjmallett if (!physical) 886215976Sjmallett return -1; 887215976Sjmallett 888215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 889215976Sjmallett cvmx_dprintf("SRIO%d: Remote write[id=0x%04x hop=%3d offset=0x%06x] => 0x%08x\n", srio_port, destid, hopcount, offset, data); 890215976Sjmallett 891215976Sjmallett /* Finally do the maintenance write to complete the config request */ 892215976Sjmallett cvmx_write64_uint32(CVMX_ADD_IO_SEG(physical), data); 893215976Sjmallett return cvmx_srio_physical_unmap(physical, 4); 894215976Sjmallett#else 895215976Sjmallett return -1; 896215976Sjmallett#endif 897215976Sjmallett } 898215976Sjmallett} 899215976Sjmallett 900215976Sjmallett 901215976Sjmallett/** 902215976Sjmallett * Send a RapidIO doorbell to a remote device 903215976Sjmallett * 904215976Sjmallett * @param srio_port SRIO port the device is on 905215976Sjmallett * @param srcid_index 906215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 907215976Sjmallett * @param destid RapidIO device ID. 908215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 909215976Sjmallett * if transactions should use 8bit device IDs. 910215976Sjmallett * @param priority Doorbell priority (0-3) 911215976Sjmallett * @param data Data for doorbell. 912215976Sjmallett * 913215976Sjmallett * @return Zero on success, negative on failure. 914215976Sjmallett */ 915215976Sjmallettint cvmx_srio_send_doorbell(int srio_port, int srcid_index, int destid, int is16bit, int priority, uint16_t data) 916215976Sjmallett{ 917215976Sjmallett cvmx_sriox_tx_bell_t tx_bell; 918215976Sjmallett tx_bell.u64 = 0; 919215976Sjmallett tx_bell.s.data = data; 920215976Sjmallett tx_bell.s.dest_id = destid; 921215976Sjmallett tx_bell.s.src_id = srcid_index; 922215976Sjmallett tx_bell.s.id16 = !!is16bit; 923215976Sjmallett tx_bell.s.priority = priority; 924215976Sjmallett 925215976Sjmallett /* Make sure the previous doorbell has completed */ 926215976Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_SRIOX_TX_BELL(srio_port), cvmx_sriox_tx_bell_t, pending, ==, 0, CVMX_SRIO_DOORBELL_TIMEOUT)) 927215976Sjmallett { 928215976Sjmallett cvmx_dprintf("SRIO%d: Pending bit stuck before doorbell\n", srio_port); 929215976Sjmallett return -1; 930215976Sjmallett } 931215976Sjmallett 932215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 933215976Sjmallett cvmx_dprintf("SRIO%d: Send doorbell destid=0x%x, priority=%d, data=0x%x\n", srio_port, destid, priority, 0xffff & data); 934215976Sjmallett 935215976Sjmallett /* Send the doorbell. We don't wait for it to complete. The next doorbell 936215976Sjmallett may delay on the pending bit, but this gives the caller the ability to 937215976Sjmallett do other stuff while the doorbell processes */ 938215976Sjmallett cvmx_write_csr(CVMX_SRIOX_TX_BELL(srio_port), tx_bell.u64); 939215976Sjmallett return 0; 940215976Sjmallett} 941215976Sjmallett 942215976Sjmallett 943215976Sjmallett/** 944215976Sjmallett * Get the status of the last doorbell sent. If the dooorbell 945215976Sjmallett * hardware is done, then the status is cleared to get ready for 946215976Sjmallett * the next doorbell (or retry). 947215976Sjmallett * 948215976Sjmallett * @param srio_port SRIO port to check doorbell on 949215976Sjmallett * 950215976Sjmallett * @return Doorbell status 951215976Sjmallett */ 952215976Sjmallettcvmx_srio_doorbell_status_t cvmx_srio_send_doorbell_status(int srio_port) 953215976Sjmallett{ 954215976Sjmallett cvmx_sriox_tx_bell_t tx_bell; 955215976Sjmallett cvmx_sriox_tx_bell_info_t tx_bell_info; 956215976Sjmallett cvmx_sriox_int_reg_t int_reg; 957215976Sjmallett cvmx_sriox_int_reg_t int_reg_clear; 958215976Sjmallett 959215976Sjmallett /* Return busy if the doorbell is still processing */ 960215976Sjmallett tx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL(srio_port)); 961215976Sjmallett if (tx_bell.s.pending) 962215976Sjmallett return CVMX_SRIO_DOORBELL_BUSY; 963215976Sjmallett 964215976Sjmallett /* Read and clear the TX doorbell interrupts */ 965215976Sjmallett int_reg.u64 = cvmx_read_csr(CVMX_SRIOX_INT_REG(srio_port)); 966215976Sjmallett int_reg_clear.u64 = 0; 967215976Sjmallett int_reg_clear.s.bell_err = int_reg.s.bell_err; 968215976Sjmallett int_reg_clear.s.txbell = int_reg.s.txbell; 969215976Sjmallett cvmx_write_csr(CVMX_SRIOX_INT_REG(srio_port), int_reg_clear.u64); 970215976Sjmallett 971215976Sjmallett /* Check for errors */ 972215976Sjmallett if (int_reg.s.bell_err) 973215976Sjmallett { 974215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 975215976Sjmallett cvmx_dprintf("SRIO%d: Send doorbell failed\n", srio_port); 976215976Sjmallett tx_bell_info.u64 = cvmx_read_csr(CVMX_SRIOX_TX_BELL_INFO(srio_port)); 977215976Sjmallett if (tx_bell_info.s.timeout || tx_bell_info.s.error) 978215976Sjmallett return CVMX_SRIO_DOORBELL_ERROR; 979215976Sjmallett if (tx_bell_info.s.retry) 980215976Sjmallett return CVMX_SRIO_DOORBELL_RETRY; 981215976Sjmallett } 982215976Sjmallett 983215976Sjmallett /* Check if we're done */ 984215976Sjmallett if (int_reg.s.txbell) 985215976Sjmallett return CVMX_SRIO_DOORBELL_DONE; 986215976Sjmallett 987215976Sjmallett /* No doorbell found */ 988215976Sjmallett return CVMX_SRIO_DOORBELL_NONE; 989215976Sjmallett} 990215976Sjmallett 991215976Sjmallett 992215976Sjmallett/** 993215976Sjmallett * Read a received doorbell and report data about it. 994215976Sjmallett * 995215976Sjmallett * @param srio_port SRIO port to check for the received doorbell 996215976Sjmallett * @param destid_index 997215976Sjmallett * Which Octeon destination ID was the doorbell for 998215976Sjmallett * @param sequence_num 999215976Sjmallett * Sequence number of doorbell (32bits) 1000215976Sjmallett * @param srcid RapidIO source ID of the doorbell sender 1001215976Sjmallett * @param priority Priority of the doorbell (0-3) 1002215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1003215976Sjmallett * if transactions should use 8bit device IDs. 1004215976Sjmallett * @param data Data in the doorbell (16 bits) 1005215976Sjmallett * 1006215976Sjmallett * @return Doorbell status. Either DONE, NONE, or ERROR. 1007215976Sjmallett */ 1008215976Sjmallettcvmx_srio_doorbell_status_t cvmx_srio_receive_doorbell(int srio_port, 1009215976Sjmallett int *destid_index, uint32_t *sequence_num, int *srcid, int *priority, 1010215976Sjmallett int *is16bit, uint16_t *data) 1011215976Sjmallett{ 1012215976Sjmallett cvmx_sriox_rx_bell_seq_t rx_bell_seq; 1013215976Sjmallett cvmx_sriox_rx_bell_t rx_bell; 1014215976Sjmallett 1015215976Sjmallett /* Check if there are any pending doorbells */ 1016215976Sjmallett rx_bell_seq.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL_SEQ(srio_port)); 1017215976Sjmallett if (!rx_bell_seq.s.count) 1018215976Sjmallett return CVMX_SRIO_DOORBELL_NONE; 1019215976Sjmallett 1020215976Sjmallett /* Read the doorbell and write our return parameters */ 1021215976Sjmallett rx_bell.u64 = cvmx_read_csr(CVMX_SRIOX_RX_BELL(srio_port)); 1022215976Sjmallett *sequence_num = rx_bell_seq.s.seq; 1023215976Sjmallett *srcid = rx_bell.s.src_id; 1024215976Sjmallett *priority = rx_bell.s.priority; 1025215976Sjmallett *is16bit = rx_bell.s.id16; 1026215976Sjmallett *data = rx_bell.s.data; 1027215976Sjmallett *destid_index = rx_bell.s.dest_id; 1028215976Sjmallett 1029215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1030215976Sjmallett cvmx_dprintf("SRIO%d: Receive doorbell sequence=0x%x, srcid=0x%x, priority=%d, data=0x%x\n", 1031215976Sjmallett srio_port, rx_bell_seq.s.seq, rx_bell.s.src_id, rx_bell.s.priority, rx_bell.s.data); 1032215976Sjmallett 1033215976Sjmallett return CVMX_SRIO_DOORBELL_DONE; 1034215976Sjmallett} 1035215976Sjmallett 1036215976Sjmallett 1037215976Sjmallett/** 1038215976Sjmallett * Receive a packet from the Soft Packet FIFO (SPF). 1039215976Sjmallett * 1040215976Sjmallett * @param srio_port SRIO port to read the packet from. 1041215976Sjmallett * @param buffer Buffer to receive the packet. 1042215976Sjmallett * @param buffer_length 1043215976Sjmallett * Length of the buffer in bytes. 1044215976Sjmallett * 1045215976Sjmallett * @return Returns the length of the packet read. Negative on failure. 1046215976Sjmallett * Zero if no packets are available. 1047215976Sjmallett */ 1048215976Sjmallettint cvmx_srio_receive_spf(int srio_port, void *buffer, int buffer_length) 1049215976Sjmallett{ 1050215976Sjmallett uint32_t *ptr = (uint32_t *)buffer; 1051215976Sjmallett cvmx_sriomaintx_ir_sp_rx_stat_t sriomaintx_ir_sp_rx_stat; 1052215976Sjmallett 1053215976Sjmallett /* Read the SFP status */ 1054215976Sjmallett if (__cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_STAT(srio_port), &sriomaintx_ir_sp_rx_stat.u32)) 1055215976Sjmallett return -1; 1056215976Sjmallett 1057215976Sjmallett /* Return zero if there isn't a packet available */ 1058215976Sjmallett if (sriomaintx_ir_sp_rx_stat.s.buffers < 1) 1059215976Sjmallett return 0; 1060215976Sjmallett 1061215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1062215976Sjmallett cvmx_dprintf("SRIO%d: Soft packet FIFO received %d bytes", srio_port, sriomaintx_ir_sp_rx_stat.s.octets); 1063215976Sjmallett 1064215976Sjmallett /* Return error if the packet is larger than our buffer */ 1065215976Sjmallett if (sriomaintx_ir_sp_rx_stat.s.octets > buffer_length) 1066215976Sjmallett return -1; 1067215976Sjmallett 1068215976Sjmallett /* Read out the packet four bytes at a time */ 1069215976Sjmallett buffer_length = sriomaintx_ir_sp_rx_stat.s.octets; 1070215976Sjmallett while (buffer_length > 0) 1071215976Sjmallett { 1072215976Sjmallett __cvmx_srio_local_read32(srio_port, CVMX_SRIOMAINTX_IR_SP_RX_DATA(srio_port), ptr); 1073215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1074215976Sjmallett cvmx_dprintf(" %08x", (unsigned int)*ptr); 1075215976Sjmallett ptr++; 1076215976Sjmallett buffer_length-=4; 1077215976Sjmallett } 1078215976Sjmallett 1079215976Sjmallett if (__cvmx_srio_state[srio_port].flags & CVMX_SRIO_INITIALIZE_DEBUG) 1080215976Sjmallett cvmx_dprintf("\n"); 1081215976Sjmallett 1082215976Sjmallett /* Return the number of bytes in the buffer */ 1083215976Sjmallett return sriomaintx_ir_sp_rx_stat.s.octets; 1084215976Sjmallett} 1085215976Sjmallett 1086215976Sjmallett#ifndef CVMX_BUILD_FOR_LINUX_HOST 1087215976Sjmallett/** 1088215976Sjmallett * Map a remote device's memory region into Octeon's physical 1089215976Sjmallett * address area. The caller can then map this into a core using 1090215976Sjmallett * the TLB or XKPHYS. 1091215976Sjmallett * 1092215976Sjmallett * @param srio_port SRIO port to map the device on 1093215976Sjmallett * @param write_op Type of operation to perform on a write to the device. 1094215976Sjmallett * Normally should be CVMX_SRIO_WRITE_MODE_AUTO. 1095215976Sjmallett * @param write_priority 1096215976Sjmallett * SRIO priority of writes (0-3) 1097215976Sjmallett * @param read_op Type of operation to perform on reads to the device. 1098215976Sjmallett * Normally should be CVMX_SRIO_READ_MODE_NORMAL. 1099215976Sjmallett * @param read_priority 1100215976Sjmallett * SRIO priority of reads (0-3) 1101215976Sjmallett * @param srcid_index 1102215976Sjmallett * Which SRIO source ID to use. 0 = Primary, 1 = Secondary 1103215976Sjmallett * @param destid RapidIO device ID. 1104215976Sjmallett * @param is16bit Non zero if the transactions should use 16bit device IDs. Zero 1105215976Sjmallett * if transactions should use 8bit device IDs. 1106215976Sjmallett * @param base Device base address to start the mapping 1107215976Sjmallett * @param size Size of the mapping in bytes 1108215976Sjmallett * 1109215976Sjmallett * @return Octeon 64bit physical address that accesses the remote device, 1110215976Sjmallett * or zero on failure. 1111215976Sjmallett */ 1112215976Sjmallettuint64_t cvmx_srio_physical_map(int srio_port, cvmx_srio_write_mode_t write_op, 1113215976Sjmallett int write_priority, cvmx_srio_read_mode_t read_op, int read_priority, 1114215976Sjmallett int srcid_index, int destid, int is16bit, uint64_t base, uint64_t size) 1115215976Sjmallett{ 1116215976Sjmallett cvmx_sriox_s2m_typex_t needed_s2m_type; 1117215976Sjmallett cvmx_sli_mem_access_subidx_t needed_subid; 1118215976Sjmallett int s2m_index; 1119215976Sjmallett int subdid; 1120215976Sjmallett cvmx_sli_address_t sli_address; 1121215976Sjmallett 1122215976Sjmallett /* We currently don't support mapping regions that span a 34 bit boundary. 1123215976Sjmallett Keeping track of multiple regions to span 34 bits is hard and not 1124215976Sjmallett likely to be needed */ 1125215976Sjmallett if (((base+size-1)>>34) != (base>>34)) 1126215976Sjmallett { 1127215976Sjmallett cvmx_dprintf("SRIO%d: Failed to map range 0x%llx-0x%llx spanning a 34bit boundary\n", 1128215976Sjmallett srio_port, (ULL)base, (ULL)base+size-1); 1129215976Sjmallett return 0; 1130215976Sjmallett } 1131215976Sjmallett 1132215976Sjmallett /* Build the S2M_TYPE we are going to need */ 1133215976Sjmallett needed_s2m_type.u64 = 0; 1134215976Sjmallett needed_s2m_type.s.wr_op = write_op; 1135215976Sjmallett needed_s2m_type.s.rd_op = read_op; 1136215976Sjmallett needed_s2m_type.s.wr_prior = write_priority; 1137215976Sjmallett needed_s2m_type.s.rd_prior = read_priority; 1138215976Sjmallett needed_s2m_type.s.src_id = srcid_index; 1139215976Sjmallett needed_s2m_type.s.id16 = !!is16bit; 1140215976Sjmallett 1141215976Sjmallett /* Build the needed SubID config */ 1142215976Sjmallett needed_subid.u64 = 0; 1143215976Sjmallett needed_subid.s.port = srio_port; 1144215976Sjmallett needed_subid.s.nmerge = 1; 1145215976Sjmallett 1146215976Sjmallett /* FIXME: We might want to use the device ID swapping modes so the device 1147215976Sjmallett ID is part of the lower address bits. This would allow many more 1148215976Sjmallett devices to share S2M_TYPE indexes. This would require "base+size-1" 1149215976Sjmallett to fit in bits [17:0] or bits[25:0] for 8 bits of device ID */ 1150215976Sjmallett if (base < (1ull<<34)) 1151215976Sjmallett { 1152215976Sjmallett needed_subid.s.ba = destid; 1153215976Sjmallett needed_s2m_type.s.iaow_sel = 0; 1154215976Sjmallett } 1155215976Sjmallett else if (base < (1ull<<42)) 1156215976Sjmallett { 1157215976Sjmallett needed_subid.s.ba = (base>>34) & 0xff; 1158215976Sjmallett needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (42-34); 1159215976Sjmallett needed_subid.s.ba |= (((uint64_t)destid>>8) & 0xff) << (51-34); 1160215976Sjmallett needed_s2m_type.s.iaow_sel = 1; 1161215976Sjmallett } 1162215976Sjmallett else 1163215976Sjmallett { 1164215976Sjmallett if (destid>>8) 1165215976Sjmallett { 1166215976Sjmallett cvmx_dprintf("SRIO%d: Attempt to map 16bit device ID 0x%x using 66bit addressing\n", srio_port, destid); 1167215976Sjmallett return 0; 1168215976Sjmallett } 1169215976Sjmallett if (base>>50) 1170215976Sjmallett { 1171215976Sjmallett cvmx_dprintf("SRIO%d: Attempt to map address 0x%llx using 66bit addressing\n", srio_port, (ULL)base); 1172215976Sjmallett return 0; 1173215976Sjmallett } 1174215976Sjmallett needed_subid.s.ba = (base>>34) & 0xffff; 1175215976Sjmallett needed_subid.s.ba |= ((uint64_t)destid & 0xff) << (51-34); 1176215976Sjmallett needed_s2m_type.s.iaow_sel = 2; 1177215976Sjmallett } 1178215976Sjmallett 1179215976Sjmallett /* Find a S2M_TYPE index to use. If this fails return 0 */ 1180215976Sjmallett s2m_index = __cvmx_srio_alloc_s2m(srio_port, needed_s2m_type); 1181215976Sjmallett if (s2m_index == -1) 1182215976Sjmallett return 0; 1183215976Sjmallett 1184215976Sjmallett /* Attach the SubID to the S2M_TYPE index */ 1185215976Sjmallett needed_subid.s.rtype = s2m_index & 3; 1186215976Sjmallett needed_subid.s.wtype = s2m_index & 3; 1187215976Sjmallett needed_subid.s.ba |= (((uint64_t)s2m_index >> 2) & 1) << (50-34); 1188215976Sjmallett needed_subid.s.ba |= (((uint64_t)s2m_index >> 3) & 1) << (59-34); 1189215976Sjmallett 1190215976Sjmallett /* Allocate a SubID for use */ 1191215976Sjmallett subdid = __cvmx_srio_alloc_subid(needed_subid); 1192215976Sjmallett if (subdid == -1) 1193215976Sjmallett { 1194215976Sjmallett /* Free the s2m_index as we aren't using it */ 1195215976Sjmallett __cvmx_srio_free_s2m(srio_port, s2m_index); 1196215976Sjmallett return 0; 1197215976Sjmallett } 1198215976Sjmallett 1199215976Sjmallett /* Build the final core physical address */ 1200215976Sjmallett sli_address.u64 = 0; 1201215976Sjmallett sli_address.mem.io = 1; 1202215976Sjmallett sli_address.mem.did = 3; 1203215976Sjmallett sli_address.mem.subdid = subdid>>2; 1204215976Sjmallett sli_address.mem.se = subdid & 3; 1205215976Sjmallett sli_address.mem.address = base; /* Bits[33:0] of full address */ 1206215976Sjmallett return sli_address.u64; 1207215976Sjmallett} 1208215976Sjmallett 1209215976Sjmallett 1210215976Sjmallett/** 1211215976Sjmallett * Unmap a physical address window created by cvmx_srio_phys_map(). 1212215976Sjmallett * 1213215976Sjmallett * @param physical_address 1214215976Sjmallett * Physical address returned by cvmx_srio_phys_map(). 1215215976Sjmallett * @param size Size used on original call. 1216215976Sjmallett * 1217215976Sjmallett * @return Zero on success, negative on failure. 1218215976Sjmallett */ 1219215976Sjmallettint cvmx_srio_physical_unmap(uint64_t physical_address, uint64_t size) 1220215976Sjmallett{ 1221215976Sjmallett cvmx_sli_mem_access_subidx_t subid; 1222215976Sjmallett int subdid = (physical_address >> 40) & 7; 1223215976Sjmallett int extender = (physical_address >> 34) & 3; 1224215976Sjmallett int mem_index = subdid * 4 + extender; 1225215976Sjmallett int read_s2m_type; 1226215976Sjmallett 1227215976Sjmallett /* Get the subid setup so we can figure out where this mapping was for */ 1228215976Sjmallett subid.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(mem_index)); 1229215976Sjmallett /* Type[0] is mapped to the Relaxed Ordering 1230215976Sjmallett Type[1] is mapped to the No Snoop 1231215976Sjmallett Type[2] is mapped directly to bit 50 of the SLI address 1232215976Sjmallett Type[3] is mapped directly to bit 59 of the SLI address */ 1233215976Sjmallett read_s2m_type = ((subid.s.ba>>(50-34))&1<<2) | ((subid.s.ba>>(59-34))&1<<3); 1234215976Sjmallett read_s2m_type |= subid.s.rtype; 1235215976Sjmallett __cvmx_srio_free_subid(mem_index); 1236215976Sjmallett __cvmx_srio_free_s2m(subid.s.port, read_s2m_type); 1237215976Sjmallett return 0; 1238215976Sjmallett} 1239215976Sjmallett#endif 1240