cvmx-pcie.c revision 215990
1210284Sjmallett/***********************license start*************** 2215990Sjmallett * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights 3215990Sjmallett * reserved. 4210284Sjmallett * 5210284Sjmallett * 6215990Sjmallett * Redistribution and use in source and binary forms, with or without 7215990Sjmallett * modification, are permitted provided that the following conditions are 8215990Sjmallett * met: 9210284Sjmallett * 10215990Sjmallett * * Redistributions of source code must retain the above copyright 11215990Sjmallett * notice, this list of conditions and the following disclaimer. 12210284Sjmallett * 13215990Sjmallett * * Redistributions in binary form must reproduce the above 14215990Sjmallett * copyright notice, this list of conditions and the following 15215990Sjmallett * disclaimer in the documentation and/or other materials provided 16215990Sjmallett * with the distribution. 17215990Sjmallett 18215990Sjmallett * * Neither the name of Cavium Networks nor the names of 19215990Sjmallett * its contributors may be used to endorse or promote products 20215990Sjmallett * derived from this software without specific prior written 21215990Sjmallett * permission. 22215990Sjmallett 23215990Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215990Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215990Sjmallett * regulations, and may be subject to export or import regulations in other 26215990Sjmallett * countries. 27215990Sjmallett 28215990Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29215990Sjmallett * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR 30215990Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215990Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215990Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215990Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215990Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215990Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215990Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215990Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38210284Sjmallett ***********************license end**************************************/ 39210284Sjmallett 40210284Sjmallett 41210284Sjmallett 42210284Sjmallett 43210284Sjmallett 44210284Sjmallett 45215990Sjmallett 46210284Sjmallett/** 47210284Sjmallett * @file 48210284Sjmallett * 49210284Sjmallett * Interface to PCIe as a host(RC) or target(EP) 50210284Sjmallett * 51215990Sjmallett * <hr>$Revision: 52004 $<hr> 52210284Sjmallett */ 53215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 54215990Sjmallett#include <asm/octeon/cvmx.h> 55215990Sjmallett#include <asm/octeon/cvmx-config.h> 56215990Sjmallett#include <asm/octeon/cvmx-clock.h> 57215990Sjmallett#include <asm/octeon/cvmx-ciu-defs.h> 58215990Sjmallett#include <asm/octeon/cvmx-dpi-defs.h> 59215990Sjmallett#include <asm/octeon/cvmx-npi-defs.h> 60215990Sjmallett#include <asm/octeon/cvmx-npei-defs.h> 61215990Sjmallett#include <asm/octeon/cvmx-pci-defs.h> 62215990Sjmallett#include <asm/octeon/cvmx-pcieepx-defs.h> 63215990Sjmallett#include <asm/octeon/cvmx-pciercx-defs.h> 64215990Sjmallett#include <asm/octeon/cvmx-pemx-defs.h> 65215990Sjmallett#include <asm/octeon/cvmx-pexp-defs.h> 66215990Sjmallett#include <asm/octeon/cvmx-pescx-defs.h> 67215990Sjmallett#include <asm/octeon/cvmx-sli-defs.h> 68215990Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 69215990Sjmallett 70215990Sjmallett#ifdef CONFIG_CAVIUM_DECODE_RSL 71215990Sjmallett#include <asm/octeon/cvmx-error.h> 72215990Sjmallett#endif 73215990Sjmallett#include <asm/octeon/cvmx-helper.h> 74215990Sjmallett#include <asm/octeon/cvmx-helper-board.h> 75215990Sjmallett#include <asm/octeon/cvmx-helper-errata.h> 76215990Sjmallett#include <asm/octeon/cvmx-pcie.h> 77215990Sjmallett#include <asm/octeon/cvmx-sysinfo.h> 78215990Sjmallett#include <asm/octeon/cvmx-swap.h> 79215990Sjmallett#include <asm/octeon/cvmx-wqe.h> 80215990Sjmallett#else 81210284Sjmallett#include "cvmx.h" 82210284Sjmallett#include "cvmx-csr-db.h" 83210284Sjmallett#include "cvmx-pcie.h" 84210284Sjmallett#include "cvmx-sysinfo.h" 85210284Sjmallett#include "cvmx-swap.h" 86210284Sjmallett#include "cvmx-wqe.h" 87215990Sjmallett#include "cvmx-error.h" 88210284Sjmallett#include "cvmx-helper-errata.h" 89215990Sjmallett#endif 90210284Sjmallett 91215990Sjmallett#define MRRS_CN5XXX 0 /* 128 byte Max Read Request Size */ 92215990Sjmallett#define MPS_CN5XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ 93215990Sjmallett#define MRRS_CN6XXX 3 /* 1024 byte Max Read Request Size */ 94215990Sjmallett#define MPS_CN6XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ 95210284Sjmallett 96210284Sjmallett/** 97210284Sjmallett * Return the Core virtual base address for PCIe IO access. IOs are 98210284Sjmallett * read/written as an offset from this address. 99210284Sjmallett * 100210284Sjmallett * @param pcie_port PCIe port the IO is for 101210284Sjmallett * 102210284Sjmallett * @return 64bit Octeon IO base address for read/write 103210284Sjmallett */ 104210284Sjmallettuint64_t cvmx_pcie_get_io_base_address(int pcie_port) 105210284Sjmallett{ 106210284Sjmallett cvmx_pcie_address_t pcie_addr; 107210284Sjmallett pcie_addr.u64 = 0; 108210284Sjmallett pcie_addr.io.upper = 0; 109210284Sjmallett pcie_addr.io.io = 1; 110210284Sjmallett pcie_addr.io.did = 3; 111210284Sjmallett pcie_addr.io.subdid = 2; 112210284Sjmallett pcie_addr.io.es = 1; 113210284Sjmallett pcie_addr.io.port = pcie_port; 114210284Sjmallett return pcie_addr.u64; 115210284Sjmallett} 116210284Sjmallett 117210284Sjmallett 118210284Sjmallett/** 119210284Sjmallett * Size of the IO address region returned at address 120210284Sjmallett * cvmx_pcie_get_io_base_address() 121210284Sjmallett * 122210284Sjmallett * @param pcie_port PCIe port the IO is for 123210284Sjmallett * 124210284Sjmallett * @return Size of the IO window 125210284Sjmallett */ 126210284Sjmallettuint64_t cvmx_pcie_get_io_size(int pcie_port) 127210284Sjmallett{ 128210284Sjmallett return 1ull<<32; 129210284Sjmallett} 130210284Sjmallett 131210284Sjmallett 132210284Sjmallett/** 133210284Sjmallett * Return the Core virtual base address for PCIe MEM access. Memory is 134210284Sjmallett * read/written as an offset from this address. 135210284Sjmallett * 136210284Sjmallett * @param pcie_port PCIe port the IO is for 137210284Sjmallett * 138210284Sjmallett * @return 64bit Octeon IO base address for read/write 139210284Sjmallett */ 140210284Sjmallettuint64_t cvmx_pcie_get_mem_base_address(int pcie_port) 141210284Sjmallett{ 142210284Sjmallett cvmx_pcie_address_t pcie_addr; 143210284Sjmallett pcie_addr.u64 = 0; 144210284Sjmallett pcie_addr.mem.upper = 0; 145210284Sjmallett pcie_addr.mem.io = 1; 146210284Sjmallett pcie_addr.mem.did = 3; 147210284Sjmallett pcie_addr.mem.subdid = 3 + pcie_port; 148210284Sjmallett return pcie_addr.u64; 149210284Sjmallett} 150210284Sjmallett 151210284Sjmallett 152210284Sjmallett/** 153210284Sjmallett * Size of the Mem address region returned at address 154210284Sjmallett * cvmx_pcie_get_mem_base_address() 155210284Sjmallett * 156210284Sjmallett * @param pcie_port PCIe port the IO is for 157210284Sjmallett * 158210284Sjmallett * @return Size of the Mem window 159210284Sjmallett */ 160210284Sjmallettuint64_t cvmx_pcie_get_mem_size(int pcie_port) 161210284Sjmallett{ 162210284Sjmallett return 1ull<<36; 163210284Sjmallett} 164210284Sjmallett 165210284Sjmallett 166210284Sjmallett/** 167210284Sjmallett * @INTERNAL 168210284Sjmallett * Initialize the RC config space CSRs 169210284Sjmallett * 170210284Sjmallett * @param pcie_port PCIe port to initialize 171210284Sjmallett */ 172210284Sjmallettstatic void __cvmx_pcie_rc_initialize_config_space(int pcie_port) 173210284Sjmallett{ 174210284Sjmallett /* Max Payload Size (PCIE*_CFG030[MPS]) */ 175210284Sjmallett /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ 176210284Sjmallett /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ 177210284Sjmallett /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ 178210284Sjmallett { 179210284Sjmallett cvmx_pciercx_cfg030_t pciercx_cfg030; 180210284Sjmallett pciercx_cfg030.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); 181215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) 182215990Sjmallett { 183215990Sjmallett pciercx_cfg030.s.mps = MPS_CN5XXX; 184215990Sjmallett pciercx_cfg030.s.mrrs = MRRS_CN5XXX; 185215990Sjmallett } 186215990Sjmallett else 187215990Sjmallett { 188215990Sjmallett pciercx_cfg030.s.mps = MPS_CN6XXX; 189215990Sjmallett pciercx_cfg030.s.mrrs = MRRS_CN6XXX; 190215990Sjmallett } 191210284Sjmallett pciercx_cfg030.s.ro_en = 1; /* Enable relaxed order processing. This will allow devices to affect read response ordering */ 192210284Sjmallett pciercx_cfg030.s.ns_en = 1; /* Enable no snoop processing. Not used by Octeon */ 193210284Sjmallett pciercx_cfg030.s.ce_en = 1; /* Correctable error reporting enable. */ 194210284Sjmallett pciercx_cfg030.s.nfe_en = 1; /* Non-fatal error reporting enable. */ 195210284Sjmallett pciercx_cfg030.s.fe_en = 1; /* Fatal error reporting enable. */ 196210284Sjmallett pciercx_cfg030.s.ur_en = 1; /* Unsupported request reporting enable. */ 197210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), pciercx_cfg030.u32); 198210284Sjmallett } 199210284Sjmallett 200215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 201210284Sjmallett { 202215990Sjmallett /* Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match PCIE*_CFG030[MPS] */ 203215990Sjmallett /* Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 204210284Sjmallett cvmx_npei_ctl_status2_t npei_ctl_status2; 205210284Sjmallett npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); 206215990Sjmallett npei_ctl_status2.s.mps = MPS_CN5XXX; /* Max payload size = 128 bytes for best Octeon DMA performance */ 207215990Sjmallett npei_ctl_status2.s.mrrs = MRRS_CN5XXX; /* Max read request size = 128 bytes for best Octeon DMA performance */ 208215990Sjmallett if (pcie_port) 209215990Sjmallett npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ 210215990Sjmallett else 211215990Sjmallett npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ 212215990Sjmallett 213210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); 214210284Sjmallett } 215215990Sjmallett else 216215990Sjmallett { 217215990Sjmallett /* Max Payload Size (DPI_SLI_PRTX_CFG[MPS]) must match PCIE*_CFG030[MPS] */ 218215990Sjmallett /* Max Read Request Size (DPI_SLI_PRTX_CFG[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 219215990Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 220215990Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 221215990Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port)); 222215990Sjmallett prt_cfg.s.mps = MPS_CN6XXX; 223215990Sjmallett prt_cfg.s.mrrs = MRRS_CN6XXX; 224215990Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port), prt_cfg.u64); 225210284Sjmallett 226215990Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port)); 227215990Sjmallett sli_s2m_portx_ctl.s.mrrs = MRRS_CN6XXX; 228215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port), sli_s2m_portx_ctl.u64); 229215990Sjmallett } 230215990Sjmallett 231210284Sjmallett /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ 232210284Sjmallett { 233210284Sjmallett cvmx_pciercx_cfg070_t pciercx_cfg070; 234210284Sjmallett pciercx_cfg070.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); 235210284Sjmallett pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ 236210284Sjmallett pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ 237210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), pciercx_cfg070.u32); 238210284Sjmallett } 239210284Sjmallett 240210284Sjmallett /* Access Enables (PCIE*_CFG001[MSAE,ME]) */ 241210284Sjmallett /* ME and MSAE should always be set. */ 242210284Sjmallett /* Interrupt Disable (PCIE*_CFG001[I_DIS]) */ 243210284Sjmallett /* System Error Message Enable (PCIE*_CFG001[SEE]) */ 244210284Sjmallett { 245210284Sjmallett cvmx_pciercx_cfg001_t pciercx_cfg001; 246210284Sjmallett pciercx_cfg001.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); 247210284Sjmallett pciercx_cfg001.s.msae = 1; /* Memory space enable. */ 248210284Sjmallett pciercx_cfg001.s.me = 1; /* Bus master enable. */ 249210284Sjmallett pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ 250210284Sjmallett pciercx_cfg001.s.see = 1; /* SERR# enable */ 251210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), pciercx_cfg001.u32); 252210284Sjmallett } 253210284Sjmallett 254210284Sjmallett 255210284Sjmallett /* Advanced Error Recovery Message Enables */ 256210284Sjmallett /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ 257210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); 258210284Sjmallett /* Use CVMX_PCIERCX_CFG067 hardware default */ 259210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); 260210284Sjmallett 261210284Sjmallett 262210284Sjmallett /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ 263210284Sjmallett { 264210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 265210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 266210284Sjmallett pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ 267210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), pciercx_cfg032.u32); 268210284Sjmallett } 269210284Sjmallett 270210284Sjmallett /* Link Width Mode (PCIERCn_CFG452[LME]) - Set during cvmx_pcie_rc_initialize_link() */ 271210284Sjmallett /* Primary Bus Number (PCIERCn_CFG006[PBNUM]) */ 272210284Sjmallett { 273210284Sjmallett /* We set the primary bus number to 1 so IDT bridges are happy. They don't like zero */ 274210284Sjmallett cvmx_pciercx_cfg006_t pciercx_cfg006; 275210284Sjmallett pciercx_cfg006.u32 = 0; 276210284Sjmallett pciercx_cfg006.s.pbnum = 1; 277210284Sjmallett pciercx_cfg006.s.sbnum = 1; 278210284Sjmallett pciercx_cfg006.s.subbnum = 1; 279210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), pciercx_cfg006.u32); 280210284Sjmallett } 281210284Sjmallett 282210284Sjmallett /* Memory-mapped I/O BAR (PCIERCn_CFG008) */ 283210284Sjmallett /* Most applications should disable the memory-mapped I/O BAR by */ 284210284Sjmallett /* setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] */ 285210284Sjmallett { 286210284Sjmallett cvmx_pciercx_cfg008_t pciercx_cfg008; 287210284Sjmallett pciercx_cfg008.u32 = 0; 288210284Sjmallett pciercx_cfg008.s.mb_addr = 0x100; 289210284Sjmallett pciercx_cfg008.s.ml_addr = 0; 290210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), pciercx_cfg008.u32); 291210284Sjmallett } 292210284Sjmallett 293210284Sjmallett /* Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) */ 294210284Sjmallett /* Most applications should disable the prefetchable BAR by setting */ 295210284Sjmallett /* PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < */ 296210284Sjmallett /* PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] */ 297210284Sjmallett { 298210284Sjmallett cvmx_pciercx_cfg009_t pciercx_cfg009; 299210284Sjmallett cvmx_pciercx_cfg010_t pciercx_cfg010; 300210284Sjmallett cvmx_pciercx_cfg011_t pciercx_cfg011; 301210284Sjmallett pciercx_cfg009.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); 302210284Sjmallett pciercx_cfg010.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); 303210284Sjmallett pciercx_cfg011.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); 304210284Sjmallett pciercx_cfg009.s.lmem_base = 0x100; 305210284Sjmallett pciercx_cfg009.s.lmem_limit = 0; 306210284Sjmallett pciercx_cfg010.s.umem_base = 0x100; 307210284Sjmallett pciercx_cfg011.s.umem_limit = 0; 308210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), pciercx_cfg009.u32); 309210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), pciercx_cfg010.u32); 310210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), pciercx_cfg011.u32); 311210284Sjmallett } 312210284Sjmallett 313210284Sjmallett /* System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) */ 314210284Sjmallett /* PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) */ 315210284Sjmallett { 316210284Sjmallett cvmx_pciercx_cfg035_t pciercx_cfg035; 317210284Sjmallett pciercx_cfg035.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); 318210284Sjmallett pciercx_cfg035.s.secee = 1; /* System error on correctable error enable. */ 319210284Sjmallett pciercx_cfg035.s.sefee = 1; /* System error on fatal error enable. */ 320210284Sjmallett pciercx_cfg035.s.senfee = 1; /* System error on non-fatal error enable. */ 321210284Sjmallett pciercx_cfg035.s.pmeie = 1; /* PME interrupt enable. */ 322210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), pciercx_cfg035.u32); 323210284Sjmallett } 324210284Sjmallett 325210284Sjmallett /* Advanced Error Recovery Interrupt Enables */ 326210284Sjmallett /* (PCIERCn_CFG075[CERE,NFERE,FERE]) */ 327210284Sjmallett { 328210284Sjmallett cvmx_pciercx_cfg075_t pciercx_cfg075; 329210284Sjmallett pciercx_cfg075.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); 330210284Sjmallett pciercx_cfg075.s.cere = 1; /* Correctable error reporting enable. */ 331210284Sjmallett pciercx_cfg075.s.nfere = 1; /* Non-fatal error reporting enable. */ 332210284Sjmallett pciercx_cfg075.s.fere = 1; /* Fatal error reporting enable. */ 333210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), pciercx_cfg075.u32); 334210284Sjmallett } 335210284Sjmallett 336210284Sjmallett /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], */ 337210284Sjmallett /* PCIERCn_CFG034[DLLS_EN,CCINT_EN]) */ 338210284Sjmallett { 339210284Sjmallett cvmx_pciercx_cfg034_t pciercx_cfg034; 340210284Sjmallett pciercx_cfg034.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); 341210284Sjmallett pciercx_cfg034.s.hpint_en = 1; /* Hot-plug interrupt enable. */ 342210284Sjmallett pciercx_cfg034.s.dlls_en = 1; /* Data Link Layer state changed enable */ 343210284Sjmallett pciercx_cfg034.s.ccint_en = 1; /* Command completed interrupt enable. */ 344210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), pciercx_cfg034.u32); 345210284Sjmallett } 346210284Sjmallett} 347210284Sjmallett 348210284Sjmallett/** 349210284Sjmallett * @INTERNAL 350215990Sjmallett * Initialize a host mode PCIe gen 1 link. This function takes a PCIe 351210284Sjmallett * port from reset to a link up state. Software can then begin 352210284Sjmallett * configuring the rest of the link. 353210284Sjmallett * 354210284Sjmallett * @param pcie_port PCIe port to initialize 355210284Sjmallett * 356210284Sjmallett * @return Zero on success 357210284Sjmallett */ 358215990Sjmallettstatic int __cvmx_pcie_rc_initialize_link_gen1(int pcie_port) 359210284Sjmallett{ 360210284Sjmallett uint64_t start_cycle; 361210284Sjmallett cvmx_pescx_ctl_status_t pescx_ctl_status; 362210284Sjmallett cvmx_pciercx_cfg452_t pciercx_cfg452; 363210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 364210284Sjmallett cvmx_pciercx_cfg448_t pciercx_cfg448; 365210284Sjmallett 366210284Sjmallett /* Set the lane width */ 367210284Sjmallett pciercx_cfg452.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); 368210284Sjmallett pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); 369210284Sjmallett if (pescx_ctl_status.s.qlm_cfg == 0) 370210284Sjmallett { 371210284Sjmallett /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ 372210284Sjmallett pciercx_cfg452.s.lme = 0xf; 373210284Sjmallett } 374210284Sjmallett else 375210284Sjmallett { 376210284Sjmallett /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ 377210284Sjmallett pciercx_cfg452.s.lme = 0x7; 378210284Sjmallett } 379210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), pciercx_cfg452.u32); 380210284Sjmallett 381210284Sjmallett /* CN52XX pass 1.x has an errata where length mismatches on UR responses can 382210284Sjmallett cause bus errors on 64bit memory reads. Turning off length error 383210284Sjmallett checking fixes this */ 384210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 385210284Sjmallett { 386210284Sjmallett cvmx_pciercx_cfg455_t pciercx_cfg455; 387210284Sjmallett pciercx_cfg455.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG455(pcie_port)); 388210284Sjmallett pciercx_cfg455.s.m_cpl_len_err = 1; 389210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), pciercx_cfg455.u32); 390210284Sjmallett } 391210284Sjmallett 392210284Sjmallett /* Lane swap needs to be manually enabled for CN52XX */ 393210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) 394210284Sjmallett { 395210284Sjmallett pescx_ctl_status.s.lane_swp = 1; 396210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port),pescx_ctl_status.u64); 397210284Sjmallett } 398210284Sjmallett 399210284Sjmallett /* Bring up the link */ 400210284Sjmallett pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); 401210284Sjmallett pescx_ctl_status.s.lnk_enb = 1; 402210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); 403210284Sjmallett 404210284Sjmallett /* CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to be disabled */ 405210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 406210284Sjmallett __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); 407210284Sjmallett 408210284Sjmallett /* Wait for the link to come up */ 409210284Sjmallett start_cycle = cvmx_get_cycle(); 410210284Sjmallett do 411210284Sjmallett { 412215990Sjmallett if (cvmx_get_cycle() - start_cycle > 2*cvmx_clock_get_rate(CVMX_CLOCK_CORE)) 413210284Sjmallett { 414210284Sjmallett cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); 415210284Sjmallett return -1; 416210284Sjmallett } 417210284Sjmallett cvmx_wait(10000); 418210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 419210284Sjmallett } while (pciercx_cfg032.s.dlla == 0); 420210284Sjmallett 421215990Sjmallett /* Clear all pending errors */ 422215990Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM)); 423215990Sjmallett 424210284Sjmallett /* Update the Replay Time Limit. Empirically, some PCIe devices take a 425210284Sjmallett little longer to respond than expected under load. As a workaround for 426210284Sjmallett this we configure the Replay Time Limit to the value expected for a 512 427210284Sjmallett byte MPS instead of our actual 256 byte MPS. The numbers below are 428210284Sjmallett directly from the PCIe spec table 3-4 */ 429210284Sjmallett pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); 430210284Sjmallett switch (pciercx_cfg032.s.nlw) 431210284Sjmallett { 432210284Sjmallett case 1: /* 1 lane */ 433210284Sjmallett pciercx_cfg448.s.rtl = 1677; 434210284Sjmallett break; 435210284Sjmallett case 2: /* 2 lanes */ 436210284Sjmallett pciercx_cfg448.s.rtl = 867; 437210284Sjmallett break; 438210284Sjmallett case 4: /* 4 lanes */ 439210284Sjmallett pciercx_cfg448.s.rtl = 462; 440210284Sjmallett break; 441210284Sjmallett case 8: /* 8 lanes */ 442210284Sjmallett pciercx_cfg448.s.rtl = 258; 443210284Sjmallett break; 444210284Sjmallett } 445210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); 446210284Sjmallett 447210284Sjmallett return 0; 448210284Sjmallett} 449210284Sjmallett 450210284Sjmallett 451210284Sjmallett/** 452215990Sjmallett * Initialize a PCIe gen 1 port for use in host(RC) mode. It doesn't enumerate 453215990Sjmallett * the bus. 454210284Sjmallett * 455210284Sjmallett * @param pcie_port PCIe port to initialize 456210284Sjmallett * 457210284Sjmallett * @return Zero on success 458210284Sjmallett */ 459215990Sjmallettstatic int __cvmx_pcie_rc_initialize_gen1(int pcie_port) 460210284Sjmallett{ 461210284Sjmallett int i; 462215990Sjmallett int base; 463215990Sjmallett uint64_t addr_swizzle; 464210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 465210284Sjmallett cvmx_pescx_bist_status_t pescx_bist_status; 466210284Sjmallett cvmx_pescx_bist_status2_t pescx_bist_status2; 467210284Sjmallett cvmx_npei_ctl_status_t npei_ctl_status; 468210284Sjmallett cvmx_npei_mem_access_ctl_t npei_mem_access_ctl; 469210284Sjmallett cvmx_npei_mem_access_subidx_t mem_access_subid; 470210284Sjmallett cvmx_npei_dbg_data_t npei_dbg_data; 471210284Sjmallett cvmx_pescx_ctl_status2_t pescx_ctl_status2; 472210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 473215990Sjmallett cvmx_npei_bar1_indexx_t bar1_index; 474210284Sjmallett 475210284Sjmallettretry: 476210284Sjmallett /* Make sure we aren't trying to setup a target mode interface in host mode */ 477210284Sjmallett npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); 478210284Sjmallett if ((pcie_port==0) && !npei_ctl_status.s.host_mode) 479210284Sjmallett { 480215990Sjmallett cvmx_dprintf("PCIe: Port %d in endpoint mode\n", pcie_port); 481210284Sjmallett return -1; 482210284Sjmallett } 483210284Sjmallett 484210284Sjmallett /* Make sure a CN52XX isn't trying to bring up port 1 when it is disabled */ 485210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 486210284Sjmallett { 487210284Sjmallett npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 488210284Sjmallett if ((pcie_port==1) && npei_dbg_data.cn52xx.qlm0_link_width) 489210284Sjmallett { 490210284Sjmallett cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port1, but port1 is disabled\n"); 491210284Sjmallett return -1; 492210284Sjmallett } 493210284Sjmallett } 494210284Sjmallett 495210284Sjmallett /* PCIe switch arbitration mode. '0' == fixed priority NPEI, PCIe0, then PCIe1. '1' == round robin. */ 496210284Sjmallett npei_ctl_status.s.arb = 1; 497210284Sjmallett /* Allow up to 0x20 config retries */ 498210284Sjmallett npei_ctl_status.s.cfg_rtry = 0x20; 499210284Sjmallett /* CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS don't reset */ 500210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 501210284Sjmallett { 502210284Sjmallett npei_ctl_status.s.p0_ntags = 0x20; 503210284Sjmallett npei_ctl_status.s.p1_ntags = 0x20; 504210284Sjmallett } 505210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); 506210284Sjmallett 507210284Sjmallett /* Bring the PCIe out of reset */ 508210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) 509210284Sjmallett { 510210284Sjmallett /* The EBH5200 board swapped the PCIe reset lines on the board. As a 511210284Sjmallett workaround for this bug, we bring both PCIe ports out of reset at 512210284Sjmallett the same time instead of on separate calls. So for port 0, we bring 513210284Sjmallett both out of reset and do nothing on port 1 */ 514210284Sjmallett if (pcie_port == 0) 515210284Sjmallett { 516210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 517210284Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 518210284Sjmallett most likely someone is trying to init it again without a proper 519210284Sjmallett PCIe reset */ 520210284Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 521210284Sjmallett { 522210284Sjmallett /* Reset the ports */ 523210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 524210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 525210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 526210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 527210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 528210284Sjmallett /* Wait until pcie resets the ports. */ 529210284Sjmallett cvmx_wait_usec(2000); 530210284Sjmallett } 531210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 532210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 533210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 534210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 535210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 536210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 537210284Sjmallett } 538210284Sjmallett } 539210284Sjmallett else 540210284Sjmallett { 541210284Sjmallett /* The normal case: The PCIe ports are completely separate and can be 542210284Sjmallett brought out of reset independently */ 543210284Sjmallett if (pcie_port) 544210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 545210284Sjmallett else 546210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 547210284Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 548210284Sjmallett most likely someone is trying to init it again without a proper 549210284Sjmallett PCIe reset */ 550210284Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 551210284Sjmallett { 552210284Sjmallett /* Reset the port */ 553210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 554210284Sjmallett if (pcie_port) 555210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 556210284Sjmallett else 557210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 558210284Sjmallett /* Wait until pcie resets the ports. */ 559210284Sjmallett cvmx_wait_usec(2000); 560210284Sjmallett } 561210284Sjmallett if (pcie_port) 562210284Sjmallett { 563210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 564210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 565210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 566210284Sjmallett } 567210284Sjmallett else 568210284Sjmallett { 569210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 570210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 571210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 572210284Sjmallett } 573210284Sjmallett } 574210284Sjmallett 575210284Sjmallett /* Wait for PCIe reset to complete. Due to errata PCIE-700, we don't poll 576210284Sjmallett PESCX_CTL_STATUS2[PCIERST], but simply wait a fixed number of cycles */ 577210284Sjmallett cvmx_wait(400000); 578210284Sjmallett 579210284Sjmallett /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and 580210284Sjmallett CN52XX, so we only probe it on newer chips */ 581210284Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 582210284Sjmallett { 583210284Sjmallett /* Clear PCLK_RUN so we can check if the clock is running */ 584210284Sjmallett pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); 585210284Sjmallett pescx_ctl_status2.s.pclk_run = 1; 586210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), pescx_ctl_status2.u64); 587210284Sjmallett /* Now that we cleared PCLK_RUN, wait for it to be set again telling 588210284Sjmallett us the clock is running */ 589210284Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), 590210284Sjmallett cvmx_pescx_ctl_status2_t, pclk_run, ==, 1, 10000)) 591210284Sjmallett { 592210284Sjmallett cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", pcie_port); 593210284Sjmallett return -1; 594210284Sjmallett } 595210284Sjmallett } 596210284Sjmallett 597210284Sjmallett /* Check and make sure PCIe came out of reset. If it doesn't the board 598210284Sjmallett probably hasn't wired the clocks up and the interface should be 599210284Sjmallett skipped */ 600210284Sjmallett pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); 601210284Sjmallett if (pescx_ctl_status2.s.pcierst) 602210284Sjmallett { 603210284Sjmallett cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); 604210284Sjmallett return -1; 605210284Sjmallett } 606210284Sjmallett 607210284Sjmallett /* Check BIST2 status. If any bits are set skip this interface. This 608210284Sjmallett is an attempt to catch PCIE-813 on pass 1 parts */ 609210284Sjmallett pescx_bist_status2.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); 610210284Sjmallett if (pescx_bist_status2.u64) 611210284Sjmallett { 612210284Sjmallett cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this port isn't hooked up, skipping.\n", pcie_port); 613210284Sjmallett return -1; 614210284Sjmallett } 615210284Sjmallett 616210284Sjmallett /* Check BIST status */ 617210284Sjmallett pescx_bist_status.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); 618210284Sjmallett if (pescx_bist_status.u64) 619210284Sjmallett cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pescx_bist_status.u64)); 620210284Sjmallett 621210284Sjmallett /* Initialize the config space CSRs */ 622210284Sjmallett __cvmx_pcie_rc_initialize_config_space(pcie_port); 623210284Sjmallett 624210284Sjmallett /* Bring the link up */ 625215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen1(pcie_port)) 626210284Sjmallett { 627215990Sjmallett cvmx_dprintf("PCIe: Failed to initialize port %d, probably the slot is empty\n", pcie_port); 628210284Sjmallett return -1; 629210284Sjmallett } 630210284Sjmallett 631210284Sjmallett /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ 632210284Sjmallett npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); 633210284Sjmallett npei_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ 634210284Sjmallett npei_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ 635210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); 636210284Sjmallett 637210284Sjmallett /* Setup Mem access SubDIDs */ 638210284Sjmallett mem_access_subid.u64 = 0; 639210284Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 640210284Sjmallett mem_access_subid.s.nmerge = 1; /* Due to an errata on pass 1 chips, no merging is allowed. */ 641210284Sjmallett mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ 642210284Sjmallett mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ 643210284Sjmallett mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ 644210284Sjmallett mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ 645210284Sjmallett mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ 646210284Sjmallett mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ 647210284Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 648210284Sjmallett 649210284Sjmallett /* Setup mem access 12-15 for port 0, 16-19 for port 1, supplying 36 bits of address space */ 650210284Sjmallett for (i=12 + pcie_port*4; i<16 + pcie_port*4; i++) 651210284Sjmallett { 652210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); 653210284Sjmallett mem_access_subid.s.ba += 1; /* Set each SUBID to extend the addressable range */ 654210284Sjmallett } 655210284Sjmallett 656210284Sjmallett /* Disable the peer to peer forwarding register. This must be setup 657210284Sjmallett by the OS after it enumerates the bus and assigns addresses to the 658210284Sjmallett PCIe busses */ 659210284Sjmallett for (i=0; i<4; i++) 660210284Sjmallett { 661210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); 662210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); 663210284Sjmallett } 664210284Sjmallett 665210284Sjmallett /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ 666210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); 667210284Sjmallett 668215990Sjmallett /* BAR1 follows BAR2 with a gap so it has the same address as for gen2. */ 669215990Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); 670210284Sjmallett 671215990Sjmallett bar1_index.u32 = 0; 672215990Sjmallett bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); 673215990Sjmallett bar1_index.s.ca = 1; /* Not Cached */ 674215990Sjmallett bar1_index.s.end_swp = 1; /* Endian Swap mode */ 675215990Sjmallett bar1_index.s.addr_v = 1; /* Valid entry */ 676215990Sjmallett 677215990Sjmallett base = pcie_port ? 16 : 0; 678215990Sjmallett 679215990Sjmallett /* Big endian swizzle for 32-bit PEXP_NCB register. */ 680215990Sjmallett#ifdef __MIPSEB__ 681215990Sjmallett addr_swizzle = 4; 682215990Sjmallett#else 683215990Sjmallett addr_swizzle = 0; 684215990Sjmallett#endif 685215990Sjmallett for (i = 0; i < 16; i++) { 686215990Sjmallett cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle), bar1_index.u32); 687215990Sjmallett base++; 688215990Sjmallett /* 256MB / 16 >> 22 == 4 */ 689215990Sjmallett bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); 690215990Sjmallett } 691215990Sjmallett 692210284Sjmallett /* Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take precedence 693210284Sjmallett where they overlap. It also overlaps with the device addresses, so 694210284Sjmallett make sure the peer to peer forwarding is set right */ 695210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); 696210284Sjmallett 697210284Sjmallett /* Setup BAR2 attributes */ 698210284Sjmallett /* Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) */ 699210284Sjmallett /* � PTLP_RO,CTLP_RO should normally be set (except for debug). */ 700210284Sjmallett /* � WAIT_COM=0 will likely work for all applications. */ 701210284Sjmallett /* Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]) */ 702210284Sjmallett if (pcie_port) 703210284Sjmallett { 704210284Sjmallett cvmx_npei_ctl_port1_t npei_ctl_port; 705210284Sjmallett npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); 706210284Sjmallett npei_ctl_port.s.bar2_enb = 1; 707210284Sjmallett npei_ctl_port.s.bar2_esx = 1; 708210284Sjmallett npei_ctl_port.s.bar2_cax = 0; 709210284Sjmallett npei_ctl_port.s.ptlp_ro = 1; 710210284Sjmallett npei_ctl_port.s.ctlp_ro = 1; 711210284Sjmallett npei_ctl_port.s.wait_com = 0; 712210284Sjmallett npei_ctl_port.s.waitl_com = 0; 713210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); 714210284Sjmallett } 715210284Sjmallett else 716210284Sjmallett { 717210284Sjmallett cvmx_npei_ctl_port0_t npei_ctl_port; 718210284Sjmallett npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); 719210284Sjmallett npei_ctl_port.s.bar2_enb = 1; 720210284Sjmallett npei_ctl_port.s.bar2_esx = 1; 721210284Sjmallett npei_ctl_port.s.bar2_cax = 0; 722210284Sjmallett npei_ctl_port.s.ptlp_ro = 1; 723210284Sjmallett npei_ctl_port.s.ctlp_ro = 1; 724210284Sjmallett npei_ctl_port.s.wait_com = 0; 725210284Sjmallett npei_ctl_port.s.waitl_com = 0; 726210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); 727210284Sjmallett } 728210284Sjmallett 729210284Sjmallett /* Both pass 1 and pass 2 of CN52XX and CN56XX have an errata that causes 730210284Sjmallett TLP ordering to not be preserved after multiple PCIe port resets. This 731210284Sjmallett code detects this fault and corrects it by aligning the TLP counters 732210284Sjmallett properly. Another link reset is then performed. See PCIE-13340 */ 733210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) || 734210284Sjmallett OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 735210284Sjmallett { 736210284Sjmallett cvmx_npei_dbg_data_t dbg_data; 737210284Sjmallett int old_in_fif_p_count; 738210284Sjmallett int in_fif_p_count; 739210284Sjmallett int out_p_count; 740210284Sjmallett int in_p_offset = (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ? 4 : 1; 741210284Sjmallett int i; 742210284Sjmallett 743210284Sjmallett /* Choose a write address of 1MB. It should be harmless as all bars 744210284Sjmallett haven't been setup */ 745210284Sjmallett uint64_t write_address = (cvmx_pcie_get_mem_base_address(pcie_port) + 0x100000) | (1ull<<63); 746210284Sjmallett 747210284Sjmallett /* Make sure at least in_p_offset have been executed before we try and 748210284Sjmallett read in_fif_p_count */ 749210284Sjmallett i = in_p_offset; 750210284Sjmallett while (i--) 751210284Sjmallett { 752210284Sjmallett cvmx_write64_uint32(write_address, 0); 753210284Sjmallett cvmx_wait(10000); 754210284Sjmallett } 755210284Sjmallett 756210284Sjmallett /* Read the IN_FIF_P_COUNT from the debug select. IN_FIF_P_COUNT can be 757210284Sjmallett unstable sometimes so read it twice with a write between the reads. 758210284Sjmallett This way we can tell the value is good as it will increment by one 759210284Sjmallett due to the write */ 760210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd7fc : 0xcffc); 761210284Sjmallett cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); 762210284Sjmallett do 763210284Sjmallett { 764210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 765210284Sjmallett old_in_fif_p_count = dbg_data.s.data & 0xff; 766210284Sjmallett cvmx_write64_uint32(write_address, 0); 767210284Sjmallett cvmx_wait(10000); 768210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 769210284Sjmallett in_fif_p_count = dbg_data.s.data & 0xff; 770210284Sjmallett } while (in_fif_p_count != ((old_in_fif_p_count+1) & 0xff)); 771210284Sjmallett 772210284Sjmallett /* Update in_fif_p_count for it's offset with respect to out_p_count */ 773210284Sjmallett in_fif_p_count = (in_fif_p_count + in_p_offset) & 0xff; 774210284Sjmallett 775210284Sjmallett /* Read the OUT_P_COUNT from the debug select */ 776210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd00f : 0xc80f); 777210284Sjmallett cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); 778210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 779210284Sjmallett out_p_count = (dbg_data.s.data>>1) & 0xff; 780210284Sjmallett 781210284Sjmallett /* Check that the two counters are aligned */ 782210284Sjmallett if (out_p_count != in_fif_p_count) 783210284Sjmallett { 784210284Sjmallett cvmx_dprintf("PCIe: Port %d aligning TLP counters as workaround to maintain ordering\n", pcie_port); 785210284Sjmallett while (in_fif_p_count != 0) 786210284Sjmallett { 787210284Sjmallett cvmx_write64_uint32(write_address, 0); 788210284Sjmallett cvmx_wait(10000); 789210284Sjmallett in_fif_p_count = (in_fif_p_count + 1) & 0xff; 790210284Sjmallett } 791210284Sjmallett /* The EBH5200 board swapped the PCIe reset lines on the board. This 792210284Sjmallett means we must bring both links down and up, which will cause the 793210284Sjmallett PCIe0 to need alignment again. Lots of messages will be displayed, 794210284Sjmallett but everything should work */ 795210284Sjmallett if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) && 796210284Sjmallett (pcie_port == 1)) 797210284Sjmallett cvmx_pcie_rc_initialize(0); 798210284Sjmallett /* Rety bringing this port up */ 799210284Sjmallett goto retry; 800210284Sjmallett } 801210284Sjmallett } 802210284Sjmallett 803210284Sjmallett /* Display the link status */ 804210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 805210284Sjmallett cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, pciercx_cfg032.s.nlw); 806210284Sjmallett 807210284Sjmallett return 0; 808210284Sjmallett} 809210284Sjmallett 810210284Sjmallett 811210284Sjmallett/** 812215990Sjmallett * @INTERNAL 813215990Sjmallett * Initialize a host mode PCIe gen 2 link. This function takes a PCIe 814215990Sjmallett * port from reset to a link up state. Software can then begin 815215990Sjmallett * configuring the rest of the link. 816215990Sjmallett * 817215990Sjmallett * @param pcie_port PCIe port to initialize 818215990Sjmallett * 819215990Sjmallett * @return Zero on success 820215990Sjmallett */ 821215990Sjmallettstatic int __cvmx_pcie_rc_initialize_link_gen2(int pcie_port) 822215990Sjmallett{ 823215990Sjmallett uint64_t start_cycle; 824215990Sjmallett cvmx_pemx_ctl_status_t pem_ctl_status; 825215990Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 826215990Sjmallett cvmx_pciercx_cfg448_t pciercx_cfg448; 827215990Sjmallett 828215990Sjmallett /* Bring up the link */ 829215990Sjmallett pem_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); 830215990Sjmallett pem_ctl_status.s.lnk_enb = 1; 831215990Sjmallett cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pem_ctl_status.u64); 832215990Sjmallett 833215990Sjmallett /* Wait for the link to come up */ 834215990Sjmallett start_cycle = cvmx_get_cycle(); 835215990Sjmallett do 836215990Sjmallett { 837215990Sjmallett if (cvmx_get_cycle() - start_cycle > cvmx_clock_get_rate(CVMX_CLOCK_CORE)) 838215990Sjmallett return -1; 839215990Sjmallett cvmx_wait(10000); 840215990Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 841215990Sjmallett } while (pciercx_cfg032.s.dlla == 0); 842215990Sjmallett 843215990Sjmallett /* Update the Replay Time Limit. Empirically, some PCIe devices take a 844215990Sjmallett little longer to respond than expected under load. As a workaround for 845215990Sjmallett this we configure the Replay Time Limit to the value expected for a 512 846215990Sjmallett byte MPS instead of our actual 256 byte MPS. The numbers below are 847215990Sjmallett directly from the PCIe spec table 3-4 */ 848215990Sjmallett pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); 849215990Sjmallett switch (pciercx_cfg032.s.nlw) 850215990Sjmallett { 851215990Sjmallett case 1: /* 1 lane */ 852215990Sjmallett pciercx_cfg448.s.rtl = 1677; 853215990Sjmallett break; 854215990Sjmallett case 2: /* 2 lanes */ 855215990Sjmallett pciercx_cfg448.s.rtl = 867; 856215990Sjmallett break; 857215990Sjmallett case 4: /* 4 lanes */ 858215990Sjmallett pciercx_cfg448.s.rtl = 462; 859215990Sjmallett break; 860215990Sjmallett case 8: /* 8 lanes */ 861215990Sjmallett pciercx_cfg448.s.rtl = 258; 862215990Sjmallett break; 863215990Sjmallett } 864215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); 865215990Sjmallett 866215990Sjmallett return 0; 867215990Sjmallett} 868215990Sjmallett 869215990Sjmallett 870215990Sjmallett/** 871215990Sjmallett * Initialize a PCIe gen 2 port for use in host(RC) mode. It doesn't enumerate 872215990Sjmallett * the bus. 873215990Sjmallett * 874215990Sjmallett * @param pcie_port PCIe port to initialize 875215990Sjmallett * 876215990Sjmallett * @return Zero on success 877215990Sjmallett */ 878215990Sjmallettstatic int __cvmx_pcie_rc_initialize_gen2(int pcie_port) 879215990Sjmallett{ 880215990Sjmallett int i; 881215990Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 882215990Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 883215990Sjmallett cvmx_pemx_bar_ctl_t pemx_bar_ctl; 884215990Sjmallett cvmx_pemx_ctl_status_t pemx_ctl_status; 885215990Sjmallett cvmx_pemx_bist_status_t pemx_bist_status; 886215990Sjmallett cvmx_pemx_bist_status2_t pemx_bist_status2; 887215990Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 888215990Sjmallett cvmx_pciercx_cfg515_t pciercx_cfg515; 889215990Sjmallett cvmx_sli_ctl_portx_t sli_ctl_portx; 890215990Sjmallett cvmx_sli_mem_access_ctl_t sli_mem_access_ctl; 891215990Sjmallett cvmx_sli_mem_access_subidx_t mem_access_subid; 892215990Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctlx; 893215990Sjmallett cvmx_sriox_status_reg_t sriox_status_reg; 894215990Sjmallett cvmx_pemx_bar1_indexx_t bar1_index; 895215990Sjmallett 896215990Sjmallett /* Make sure this interface isn't SRIO */ 897215990Sjmallett sriox_status_reg.u64 = cvmx_read_csr(CVMX_SRIOX_STATUS_REG(pcie_port)); 898215990Sjmallett if (sriox_status_reg.s.srio) 899215990Sjmallett { 900215990Sjmallett cvmx_dprintf("PCIe: Port %d is SRIO, skipping.\n", pcie_port); 901215990Sjmallett return -1; 902215990Sjmallett } 903215990Sjmallett 904215990Sjmallett /* Make sure we aren't trying to setup a target mode interface in host mode */ 905215990Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); 906215990Sjmallett if (!mio_rst_ctl.s.host_mode) 907215990Sjmallett { 908215990Sjmallett cvmx_dprintf("PCIe: Port %d in endpoint mode.\n", pcie_port); 909215990Sjmallett return -1; 910215990Sjmallett } 911215990Sjmallett 912215990Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ 913215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 914215990Sjmallett { 915215990Sjmallett if (pcie_port) 916215990Sjmallett { 917215990Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 918215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 919215990Sjmallett ciu_qlm.s.txbypass = 1; 920215990Sjmallett ciu_qlm.s.txdeemph = 5; 921215990Sjmallett ciu_qlm.s.txmargin = 0x17; 922215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 923215990Sjmallett } 924215990Sjmallett else 925215990Sjmallett { 926215990Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 927215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 928215990Sjmallett ciu_qlm.s.txbypass = 1; 929215990Sjmallett ciu_qlm.s.txdeemph = 5; 930215990Sjmallett ciu_qlm.s.txmargin = 0x17; 931215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 932215990Sjmallett } 933215990Sjmallett } 934215990Sjmallett 935215990Sjmallett /* Bring the PCIe out of reset */ 936215990Sjmallett if (pcie_port) 937215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 938215990Sjmallett else 939215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 940215990Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 941215990Sjmallett most likely someone is trying to init it again without a proper 942215990Sjmallett PCIe reset */ 943215990Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 944215990Sjmallett { 945215990Sjmallett /* Reset the port */ 946215990Sjmallett ciu_soft_prst.s.soft_prst = 1; 947215990Sjmallett if (pcie_port) 948215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 949215990Sjmallett else 950215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 951215990Sjmallett /* Wait until pcie resets the ports. */ 952215990Sjmallett cvmx_wait_usec(2000); 953215990Sjmallett } 954215990Sjmallett if (pcie_port) 955215990Sjmallett { 956215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 957215990Sjmallett ciu_soft_prst.s.soft_prst = 0; 958215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 959215990Sjmallett } 960215990Sjmallett else 961215990Sjmallett { 962215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 963215990Sjmallett ciu_soft_prst.s.soft_prst = 0; 964215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 965215990Sjmallett } 966215990Sjmallett 967215990Sjmallett /* Wait for PCIe reset to complete */ 968215990Sjmallett cvmx_wait_usec(1000); 969215990Sjmallett 970215990Sjmallett /* Check and make sure PCIe came out of reset. If it doesn't the board 971215990Sjmallett probably hasn't wired the clocks up and the interface should be 972215990Sjmallett skipped */ 973215990Sjmallett mio_rst_ctlx.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); 974215990Sjmallett if (!mio_rst_ctlx.s.rst_done) 975215990Sjmallett { 976215990Sjmallett cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); 977215990Sjmallett return -1; 978215990Sjmallett } 979215990Sjmallett 980215990Sjmallett /* Check BIST status */ 981215990Sjmallett pemx_bist_status.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS(pcie_port)); 982215990Sjmallett if (pemx_bist_status.u64) 983215990Sjmallett cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status.u64)); 984215990Sjmallett pemx_bist_status2.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS2(pcie_port)); 985215990Sjmallett if (pemx_bist_status2.u64) 986215990Sjmallett cvmx_dprintf("PCIe: BIST2 FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status2.u64)); 987215990Sjmallett 988215990Sjmallett /* Initialize the config space CSRs */ 989215990Sjmallett __cvmx_pcie_rc_initialize_config_space(pcie_port); 990215990Sjmallett 991215990Sjmallett /* Enable gen2 speed selection */ 992215990Sjmallett pciercx_cfg515.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG515(pcie_port)); 993215990Sjmallett pciercx_cfg515.s.dsc = 1; 994215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG515(pcie_port), pciercx_cfg515.u32); 995215990Sjmallett 996215990Sjmallett /* Bring the link up */ 997215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) 998215990Sjmallett { 999215990Sjmallett /* Some gen1 devices don't handle the gen 2 training correctly. Disable 1000215990Sjmallett gen2 and try again with only gen1 */ 1001215990Sjmallett cvmx_pciercx_cfg031_t pciercx_cfg031; 1002215990Sjmallett pciercx_cfg031.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG031(pcie_port)); 1003215990Sjmallett pciercx_cfg031.s.mls = 1; 1004215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG031(pcie_port), pciercx_cfg515.u32); 1005215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) 1006215990Sjmallett { 1007215990Sjmallett cvmx_dprintf("PCIe: Link timeout on port %d, probably the slot is empty\n", pcie_port); 1008215990Sjmallett return -1; 1009215990Sjmallett } 1010215990Sjmallett } 1011215990Sjmallett 1012215990Sjmallett /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ 1013215990Sjmallett sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL); 1014215990Sjmallett sli_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ 1015215990Sjmallett sli_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ 1016215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64); 1017215990Sjmallett 1018215990Sjmallett /* Setup Mem access SubDIDs */ 1019215990Sjmallett mem_access_subid.u64 = 0; 1020215990Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1021215990Sjmallett mem_access_subid.s.nmerge = 0; /* Allow merging as it works on CN6XXX. */ 1022215990Sjmallett mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ 1023215990Sjmallett mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ 1024215990Sjmallett mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1025215990Sjmallett mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1026215990Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 1027215990Sjmallett 1028215990Sjmallett /* Setup mem access 12-15 for port 0, 16-19 for port 1, supplying 36 bits of address space */ 1029215990Sjmallett for (i=12 + pcie_port*4; i<16 + pcie_port*4; i++) 1030215990Sjmallett { 1031215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); 1032215990Sjmallett mem_access_subid.s.ba += 1; /* Set each SUBID to extend the addressable range */ 1033215990Sjmallett } 1034215990Sjmallett 1035215990Sjmallett /* Disable the peer to peer forwarding register. This must be setup 1036215990Sjmallett by the OS after it enumerates the bus and assigns addresses to the 1037215990Sjmallett PCIe busses */ 1038215990Sjmallett for (i=0; i<4; i++) 1039215990Sjmallett { 1040215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2P_BARX_START(i, pcie_port), -1); 1041215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2P_BARX_END(i, pcie_port), -1); 1042215990Sjmallett } 1043215990Sjmallett 1044215990Sjmallett /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ 1045215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR0_START(pcie_port), 0); 1046215990Sjmallett 1047215990Sjmallett /* Set Octeon's BAR2 to decode 0-2^41. Bar0 and Bar1 take precedence 1048215990Sjmallett where they overlap. It also overlaps with the device addresses, so 1049215990Sjmallett make sure the peer to peer forwarding is set right */ 1050215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR2_START(pcie_port), 0); 1051215990Sjmallett 1052215990Sjmallett /* Setup BAR2 attributes */ 1053215990Sjmallett /* Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) */ 1054215990Sjmallett /* � PTLP_RO,CTLP_RO should normally be set (except for debug). */ 1055215990Sjmallett /* � WAIT_COM=0 will likely work for all applications. */ 1056215990Sjmallett /* Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]) */ 1057215990Sjmallett pemx_bar_ctl.u64 = cvmx_read_csr(CVMX_PEMX_BAR_CTL(pcie_port)); 1058215990Sjmallett pemx_bar_ctl.s.bar1_siz = 3; /* 256MB BAR1*/ 1059215990Sjmallett pemx_bar_ctl.s.bar2_enb = 1; 1060215990Sjmallett pemx_bar_ctl.s.bar2_esx = 1; 1061215990Sjmallett pemx_bar_ctl.s.bar2_cax = 0; 1062215990Sjmallett cvmx_write_csr(CVMX_PEMX_BAR_CTL(pcie_port), pemx_bar_ctl.u64); 1063215990Sjmallett sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port)); 1064215990Sjmallett sli_ctl_portx.s.ptlp_ro = 1; 1065215990Sjmallett sli_ctl_portx.s.ctlp_ro = 1; 1066215990Sjmallett sli_ctl_portx.s.wait_com = 0; 1067215990Sjmallett sli_ctl_portx.s.waitl_com = 0; 1068215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port), sli_ctl_portx.u64); 1069215990Sjmallett 1070215990Sjmallett /* BAR1 follows BAR2 */ 1071215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); 1072215990Sjmallett 1073215990Sjmallett bar1_index.u64 = 0; 1074215990Sjmallett bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); 1075215990Sjmallett bar1_index.s.ca = 1; /* Not Cached */ 1076215990Sjmallett bar1_index.s.end_swp = 1; /* Endian Swap mode */ 1077215990Sjmallett bar1_index.s.addr_v = 1; /* Valid entry */ 1078215990Sjmallett 1079215990Sjmallett for (i = 0; i < 16; i++) { 1080215990Sjmallett cvmx_write_csr(CVMX_PEMX_BAR1_INDEXX(i, pcie_port), bar1_index.u64); 1081215990Sjmallett /* 256MB / 16 >> 22 == 4 */ 1082215990Sjmallett bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); 1083215990Sjmallett } 1084215990Sjmallett 1085215990Sjmallett /* Allow config retries for 250ms. Count is based off the 5Ghz SERDES 1086215990Sjmallett clock */ 1087215990Sjmallett pemx_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); 1088215990Sjmallett pemx_ctl_status.s.cfg_rtry = 250 * 5000000 / 0x10000; 1089215990Sjmallett cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pemx_ctl_status.u64); 1090215990Sjmallett 1091215990Sjmallett /* Display the link status */ 1092215990Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 1093215990Sjmallett cvmx_dprintf("PCIe: Port %d link active, %d lanes, speed gen%d\n", pcie_port, pciercx_cfg032.s.nlw, pciercx_cfg032.s.ls); 1094215990Sjmallett 1095215990Sjmallett return 0; 1096215990Sjmallett} 1097215990Sjmallett 1098215990Sjmallett/** 1099215990Sjmallett * Initialize a PCIe port for use in host(RC) mode. It doesn't enumerate the bus. 1100215990Sjmallett * 1101215990Sjmallett * @param pcie_port PCIe port to initialize 1102215990Sjmallett * 1103215990Sjmallett * @return Zero on success 1104215990Sjmallett */ 1105215990Sjmallettint cvmx_pcie_rc_initialize(int pcie_port) 1106215990Sjmallett{ 1107215990Sjmallett int result; 1108215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1109215990Sjmallett result = __cvmx_pcie_rc_initialize_gen1(pcie_port); 1110215990Sjmallett else 1111215990Sjmallett result = __cvmx_pcie_rc_initialize_gen2(pcie_port); 1112215990Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) || defined(CONFIG_CAVIUM_DECODE_RSL) 1113215990Sjmallett if (result == 0) 1114215990Sjmallett cvmx_error_enable_group(CVMX_ERROR_GROUP_PCI, pcie_port); 1115215990Sjmallett#endif 1116215990Sjmallett return result; 1117215990Sjmallett} 1118215990Sjmallett 1119215990Sjmallett 1120215990Sjmallett/** 1121210284Sjmallett * Shutdown a PCIe port and put it in reset 1122210284Sjmallett * 1123210284Sjmallett * @param pcie_port PCIe port to shutdown 1124210284Sjmallett * 1125210284Sjmallett * @return Zero on success 1126210284Sjmallett */ 1127210284Sjmallettint cvmx_pcie_rc_shutdown(int pcie_port) 1128210284Sjmallett{ 1129215990Sjmallett#if !defined(CVMX_BUILD_FOR_LINUX_KERNEL) || defined(CONFIG_CAVIUM_DECODE_RSL) 1130215990Sjmallett cvmx_error_disable_group(CVMX_ERROR_GROUP_PCI, pcie_port); 1131215990Sjmallett#endif 1132210284Sjmallett /* Wait for all pending operations to complete */ 1133215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1134215990Sjmallett { 1135215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CPL_LUT_VALID(pcie_port), cvmx_pescx_cpl_lut_valid_t, tag, ==, 0, 2000)) 1136215990Sjmallett cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); 1137215990Sjmallett } 1138215990Sjmallett else 1139215990Sjmallett { 1140215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PEMX_CPL_LUT_VALID(pcie_port), cvmx_pemx_cpl_lut_valid_t, tag, ==, 0, 2000)) 1141215990Sjmallett cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); 1142215990Sjmallett } 1143210284Sjmallett 1144210284Sjmallett /* Force reset */ 1145210284Sjmallett if (pcie_port) 1146210284Sjmallett { 1147210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 1148210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 1149210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 1150210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 1151210284Sjmallett } 1152210284Sjmallett else 1153210284Sjmallett { 1154210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 1155210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 1156210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 1157210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 1158210284Sjmallett } 1159210284Sjmallett return 0; 1160210284Sjmallett} 1161210284Sjmallett 1162210284Sjmallett 1163210284Sjmallett/** 1164210284Sjmallett * @INTERNAL 1165210284Sjmallett * Build a PCIe config space request address for a device 1166210284Sjmallett * 1167210284Sjmallett * @param pcie_port PCIe port to access 1168210284Sjmallett * @param bus Sub bus 1169210284Sjmallett * @param dev Device ID 1170210284Sjmallett * @param fn Device sub function 1171210284Sjmallett * @param reg Register to access 1172210284Sjmallett * 1173210284Sjmallett * @return 64bit Octeon IO address 1174210284Sjmallett */ 1175210284Sjmallettstatic inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, int dev, int fn, int reg) 1176210284Sjmallett{ 1177210284Sjmallett cvmx_pcie_address_t pcie_addr; 1178210284Sjmallett cvmx_pciercx_cfg006_t pciercx_cfg006; 1179210284Sjmallett 1180210284Sjmallett pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); 1181210284Sjmallett if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) 1182210284Sjmallett return 0; 1183210284Sjmallett 1184210284Sjmallett pcie_addr.u64 = 0; 1185210284Sjmallett pcie_addr.config.upper = 2; 1186210284Sjmallett pcie_addr.config.io = 1; 1187210284Sjmallett pcie_addr.config.did = 3; 1188210284Sjmallett pcie_addr.config.subdid = 1; 1189210284Sjmallett pcie_addr.config.es = 1; 1190210284Sjmallett pcie_addr.config.port = pcie_port; 1191210284Sjmallett pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); 1192210284Sjmallett pcie_addr.config.bus = bus; 1193210284Sjmallett pcie_addr.config.dev = dev; 1194210284Sjmallett pcie_addr.config.func = fn; 1195210284Sjmallett pcie_addr.config.reg = reg; 1196210284Sjmallett return pcie_addr.u64; 1197210284Sjmallett} 1198210284Sjmallett 1199210284Sjmallett 1200210284Sjmallett/** 1201210284Sjmallett * Read 8bits from a Device's config space 1202210284Sjmallett * 1203210284Sjmallett * @param pcie_port PCIe port the device is on 1204210284Sjmallett * @param bus Sub bus 1205210284Sjmallett * @param dev Device ID 1206210284Sjmallett * @param fn Device sub function 1207210284Sjmallett * @param reg Register to access 1208210284Sjmallett * 1209210284Sjmallett * @return Result of the read 1210210284Sjmallett */ 1211210284Sjmallettuint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, int fn, int reg) 1212210284Sjmallett{ 1213210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1214210284Sjmallett if (address) 1215210284Sjmallett return cvmx_read64_uint8(address); 1216210284Sjmallett else 1217210284Sjmallett return 0xff; 1218210284Sjmallett} 1219210284Sjmallett 1220210284Sjmallett 1221210284Sjmallett/** 1222210284Sjmallett * Read 16bits from a Device's config space 1223210284Sjmallett * 1224210284Sjmallett * @param pcie_port PCIe port the device is on 1225210284Sjmallett * @param bus Sub bus 1226210284Sjmallett * @param dev Device ID 1227210284Sjmallett * @param fn Device sub function 1228210284Sjmallett * @param reg Register to access 1229210284Sjmallett * 1230210284Sjmallett * @return Result of the read 1231210284Sjmallett */ 1232210284Sjmallettuint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, int reg) 1233210284Sjmallett{ 1234210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1235210284Sjmallett if (address) 1236210284Sjmallett return cvmx_le16_to_cpu(cvmx_read64_uint16(address)); 1237210284Sjmallett else 1238210284Sjmallett return 0xffff; 1239210284Sjmallett} 1240210284Sjmallett 1241210284Sjmallett 1242210284Sjmallett/** 1243210284Sjmallett * Read 32bits from a Device's config space 1244210284Sjmallett * 1245210284Sjmallett * @param pcie_port PCIe port the device is on 1246210284Sjmallett * @param bus Sub bus 1247210284Sjmallett * @param dev Device ID 1248210284Sjmallett * @param fn Device sub function 1249210284Sjmallett * @param reg Register to access 1250210284Sjmallett * 1251210284Sjmallett * @return Result of the read 1252210284Sjmallett */ 1253210284Sjmallettuint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, int reg) 1254210284Sjmallett{ 1255210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1256210284Sjmallett if (address) 1257210284Sjmallett return cvmx_le32_to_cpu(cvmx_read64_uint32(address)); 1258210284Sjmallett else 1259210284Sjmallett return 0xffffffff; 1260210284Sjmallett} 1261210284Sjmallett 1262210284Sjmallett 1263210284Sjmallett/** 1264210284Sjmallett * Write 8bits to a Device's config space 1265210284Sjmallett * 1266210284Sjmallett * @param pcie_port PCIe port the device is on 1267210284Sjmallett * @param bus Sub bus 1268210284Sjmallett * @param dev Device ID 1269210284Sjmallett * @param fn Device sub function 1270210284Sjmallett * @param reg Register to access 1271210284Sjmallett * @param val Value to write 1272210284Sjmallett */ 1273210284Sjmallettvoid cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, int reg, uint8_t val) 1274210284Sjmallett{ 1275210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1276210284Sjmallett if (address) 1277210284Sjmallett cvmx_write64_uint8(address, val); 1278210284Sjmallett} 1279210284Sjmallett 1280210284Sjmallett 1281210284Sjmallett/** 1282210284Sjmallett * Write 16bits to a Device's config space 1283210284Sjmallett * 1284210284Sjmallett * @param pcie_port PCIe port the device is on 1285210284Sjmallett * @param bus Sub bus 1286210284Sjmallett * @param dev Device ID 1287210284Sjmallett * @param fn Device sub function 1288210284Sjmallett * @param reg Register to access 1289210284Sjmallett * @param val Value to write 1290210284Sjmallett */ 1291210284Sjmallettvoid cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, int reg, uint16_t val) 1292210284Sjmallett{ 1293210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1294210284Sjmallett if (address) 1295210284Sjmallett cvmx_write64_uint16(address, cvmx_cpu_to_le16(val)); 1296210284Sjmallett} 1297210284Sjmallett 1298210284Sjmallett 1299210284Sjmallett/** 1300210284Sjmallett * Write 32bits to a Device's config space 1301210284Sjmallett * 1302210284Sjmallett * @param pcie_port PCIe port the device is on 1303210284Sjmallett * @param bus Sub bus 1304210284Sjmallett * @param dev Device ID 1305210284Sjmallett * @param fn Device sub function 1306210284Sjmallett * @param reg Register to access 1307210284Sjmallett * @param val Value to write 1308210284Sjmallett */ 1309210284Sjmallettvoid cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, int reg, uint32_t val) 1310210284Sjmallett{ 1311210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1312210284Sjmallett if (address) 1313210284Sjmallett cvmx_write64_uint32(address, cvmx_cpu_to_le32(val)); 1314210284Sjmallett} 1315210284Sjmallett 1316210284Sjmallett 1317210284Sjmallett/** 1318210284Sjmallett * Read a PCIe config space register indirectly. This is used for 1319210284Sjmallett * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. 1320210284Sjmallett * 1321210284Sjmallett * @param pcie_port PCIe port to read from 1322210284Sjmallett * @param cfg_offset Address to read 1323210284Sjmallett * 1324210284Sjmallett * @return Value read 1325210284Sjmallett */ 1326210284Sjmallettuint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) 1327210284Sjmallett{ 1328215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1329215990Sjmallett { 1330215990Sjmallett cvmx_pescx_cfg_rd_t pescx_cfg_rd; 1331215990Sjmallett pescx_cfg_rd.u64 = 0; 1332215990Sjmallett pescx_cfg_rd.s.addr = cfg_offset; 1333215990Sjmallett cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); 1334215990Sjmallett pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); 1335215990Sjmallett return pescx_cfg_rd.s.data; 1336215990Sjmallett } 1337215990Sjmallett else 1338215990Sjmallett { 1339215990Sjmallett cvmx_pemx_cfg_rd_t pemx_cfg_rd; 1340215990Sjmallett pemx_cfg_rd.u64 = 0; 1341215990Sjmallett pemx_cfg_rd.s.addr = cfg_offset; 1342215990Sjmallett cvmx_write_csr(CVMX_PEMX_CFG_RD(pcie_port), pemx_cfg_rd.u64); 1343215990Sjmallett pemx_cfg_rd.u64 = cvmx_read_csr(CVMX_PEMX_CFG_RD(pcie_port)); 1344215990Sjmallett return pemx_cfg_rd.s.data; 1345215990Sjmallett } 1346210284Sjmallett} 1347210284Sjmallett 1348210284Sjmallett 1349210284Sjmallett/** 1350210284Sjmallett * Write a PCIe config space register indirectly. This is used for 1351210284Sjmallett * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. 1352210284Sjmallett * 1353210284Sjmallett * @param pcie_port PCIe port to write to 1354210284Sjmallett * @param cfg_offset Address to write 1355210284Sjmallett * @param val Value to write 1356210284Sjmallett */ 1357210284Sjmallettvoid cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) 1358210284Sjmallett{ 1359215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1360215990Sjmallett { 1361215990Sjmallett cvmx_pescx_cfg_wr_t pescx_cfg_wr; 1362215990Sjmallett pescx_cfg_wr.u64 = 0; 1363215990Sjmallett pescx_cfg_wr.s.addr = cfg_offset; 1364215990Sjmallett pescx_cfg_wr.s.data = val; 1365215990Sjmallett cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); 1366215990Sjmallett } 1367215990Sjmallett else 1368215990Sjmallett { 1369215990Sjmallett cvmx_pemx_cfg_wr_t pemx_cfg_wr; 1370215990Sjmallett pemx_cfg_wr.u64 = 0; 1371215990Sjmallett pemx_cfg_wr.s.addr = cfg_offset; 1372215990Sjmallett pemx_cfg_wr.s.data = val; 1373215990Sjmallett cvmx_write_csr(CVMX_PEMX_CFG_WR(pcie_port), pemx_cfg_wr.u64); 1374215990Sjmallett } 1375210284Sjmallett} 1376210284Sjmallett 1377210284Sjmallett 1378210284Sjmallett/** 1379210284Sjmallett * Initialize a PCIe port for use in target(EP) mode. 1380210284Sjmallett * 1381215990Sjmallett * @param pcie_port PCIe port to initialize 1382215990Sjmallett * 1383210284Sjmallett * @return Zero on success 1384210284Sjmallett */ 1385215990Sjmallettint cvmx_pcie_ep_initialize(int pcie_port) 1386210284Sjmallett{ 1387215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1388215990Sjmallett { 1389215990Sjmallett cvmx_npei_ctl_status_t npei_ctl_status; 1390215990Sjmallett npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); 1391215990Sjmallett if (npei_ctl_status.s.host_mode) 1392215990Sjmallett return -1; 1393215990Sjmallett } 1394215990Sjmallett else 1395215990Sjmallett { 1396215990Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 1397215990Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); 1398215990Sjmallett if (mio_rst_ctl.s.host_mode) 1399215990Sjmallett return -1; 1400215990Sjmallett } 1401210284Sjmallett 1402215990Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ 1403215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 1404215990Sjmallett { 1405215990Sjmallett if (pcie_port) 1406215990Sjmallett { 1407215990Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 1408215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 1409215990Sjmallett ciu_qlm.s.txbypass = 1; 1410215990Sjmallett ciu_qlm.s.txdeemph = 5; 1411215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1412215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 1413215990Sjmallett } 1414215990Sjmallett else 1415215990Sjmallett { 1416215990Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 1417215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 1418215990Sjmallett ciu_qlm.s.txbypass = 1; 1419215990Sjmallett ciu_qlm.s.txdeemph = 5; 1420215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1421215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 1422215990Sjmallett } 1423215990Sjmallett } 1424210284Sjmallett 1425210284Sjmallett /* Enable bus master and memory */ 1426215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEPX_CFG001(pcie_port), 0x6); 1427210284Sjmallett 1428210284Sjmallett /* Max Payload Size (PCIE*_CFG030[MPS]) */ 1429210284Sjmallett /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ 1430210284Sjmallett /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ 1431210284Sjmallett /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ 1432210284Sjmallett { 1433215990Sjmallett cvmx_pcieepx_cfg030_t pcieepx_cfg030; 1434215990Sjmallett pcieepx_cfg030.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIEEPX_CFG030(pcie_port)); 1435215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) 1436215990Sjmallett { 1437215990Sjmallett pcieepx_cfg030.s.mps = MPS_CN5XXX; 1438215990Sjmallett pcieepx_cfg030.s.mrrs = MRRS_CN5XXX; 1439215990Sjmallett } 1440215990Sjmallett else 1441215990Sjmallett { 1442215990Sjmallett pcieepx_cfg030.s.mps = MPS_CN6XXX; 1443215990Sjmallett pcieepx_cfg030.s.mrrs = MRRS_CN6XXX; 1444215990Sjmallett } 1445215990Sjmallett pcieepx_cfg030.s.ro_en = 1; /* Enable relaxed ordering. */ 1446215990Sjmallett pcieepx_cfg030.s.ns_en = 1; /* Enable no snoop. */ 1447215990Sjmallett pcieepx_cfg030.s.ce_en = 1; /* Correctable error reporting enable. */ 1448215990Sjmallett pcieepx_cfg030.s.nfe_en = 1; /* Non-fatal error reporting enable. */ 1449215990Sjmallett pcieepx_cfg030.s.fe_en = 1; /* Fatal error reporting enable. */ 1450215990Sjmallett pcieepx_cfg030.s.ur_en = 1; /* Unsupported request reporting enable. */ 1451215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEPX_CFG030(pcie_port), pcieepx_cfg030.u32); 1452210284Sjmallett } 1453210284Sjmallett 1454215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1455210284Sjmallett { 1456215990Sjmallett /* Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match PCIE*_CFG030[MPS] */ 1457215990Sjmallett /* Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 1458210284Sjmallett cvmx_npei_ctl_status2_t npei_ctl_status2; 1459210284Sjmallett npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); 1460215990Sjmallett npei_ctl_status2.s.mps = MPS_CN5XXX; /* Max payload size = 128 bytes (Limit of most PCs) */ 1461215990Sjmallett npei_ctl_status2.s.mrrs = MRRS_CN5XXX; /* Max read request size = 128 bytes for best Octeon DMA performance */ 1462210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); 1463210284Sjmallett } 1464215990Sjmallett else 1465215990Sjmallett { 1466215990Sjmallett /* Max Payload Size (DPI_SLI_PRTX_CFG[MPS]) must match PCIE*_CFG030[MPS] */ 1467215990Sjmallett /* Max Read Request Size (DPI_SLI_PRTX_CFG[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 1468215990Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 1469215990Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 1470215990Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port)); 1471215990Sjmallett prt_cfg.s.mps = MPS_CN6XXX; 1472215990Sjmallett prt_cfg.s.mrrs = MRRS_CN6XXX; 1473215990Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port), prt_cfg.u64); 1474210284Sjmallett 1475215990Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port)); 1476215990Sjmallett sli_s2m_portx_ctl.s.mrrs = MRRS_CN6XXX; 1477215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port), sli_s2m_portx_ctl.u64); 1478215990Sjmallett } 1479215990Sjmallett 1480210284Sjmallett /* Setup Mem access SubDID 12 to access Host memory */ 1481215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1482210284Sjmallett { 1483210284Sjmallett cvmx_npei_mem_access_subidx_t mem_access_subid; 1484210284Sjmallett mem_access_subid.u64 = 0; 1485210284Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1486215990Sjmallett mem_access_subid.s.nmerge = 1; /* Merging is not allowed in this window. */ 1487210284Sjmallett mem_access_subid.s.esr = 0; /* Endian-swap for Reads. */ 1488210284Sjmallett mem_access_subid.s.esw = 0; /* Endian-swap for Writes. */ 1489210284Sjmallett mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ 1490210284Sjmallett mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ 1491210284Sjmallett mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ 1492210284Sjmallett mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ 1493210284Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 1494210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(12), mem_access_subid.u64); 1495210284Sjmallett } 1496215990Sjmallett else 1497215990Sjmallett { 1498215990Sjmallett cvmx_sli_mem_access_subidx_t mem_access_subid; 1499215990Sjmallett mem_access_subid.u64 = 0; 1500215990Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1501215990Sjmallett mem_access_subid.s.nmerge = 0; /* Merging is allowed in this window. */ 1502215990Sjmallett mem_access_subid.s.esr = 0; /* Endian-swap for Reads. */ 1503215990Sjmallett mem_access_subid.s.esw = 0; /* Endian-swap for Writes. */ 1504215990Sjmallett mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1505215990Sjmallett mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1506215990Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 1507215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(12 + pcie_port*4), mem_access_subid.u64); 1508215990Sjmallett } 1509210284Sjmallett return 0; 1510210284Sjmallett} 1511210284Sjmallett 1512210284Sjmallett 1513210284Sjmallett/** 1514210284Sjmallett * Wait for posted PCIe read/writes to reach the other side of 1515210284Sjmallett * the internal PCIe switch. This will insure that core 1516210284Sjmallett * read/writes are posted before anything after this function 1517210284Sjmallett * is called. This may be necessary when writing to memory that 1518210284Sjmallett * will later be read using the DMA/PKT engines. 1519210284Sjmallett * 1520210284Sjmallett * @param pcie_port PCIe port to wait for 1521210284Sjmallett */ 1522210284Sjmallettvoid cvmx_pcie_wait_for_pending(int pcie_port) 1523210284Sjmallett{ 1524215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1525215990Sjmallett { 1526215990Sjmallett cvmx_npei_data_out_cnt_t npei_data_out_cnt; 1527215990Sjmallett int a; 1528215990Sjmallett int b; 1529215990Sjmallett int c; 1530210284Sjmallett 1531215990Sjmallett /* See section 9.8, PCIe Core-initiated Requests, in the manual for a 1532215990Sjmallett description of how this code works */ 1533215990Sjmallett npei_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DATA_OUT_CNT); 1534215990Sjmallett if (pcie_port) 1535215990Sjmallett { 1536215990Sjmallett if (!npei_data_out_cnt.s.p1_fcnt) 1537215990Sjmallett return; 1538215990Sjmallett a = npei_data_out_cnt.s.p1_ucnt; 1539215990Sjmallett b = (a + npei_data_out_cnt.s.p1_fcnt-1) & 0xffff; 1540215990Sjmallett } 1541215990Sjmallett else 1542215990Sjmallett { 1543215990Sjmallett if (!npei_data_out_cnt.s.p0_fcnt) 1544215990Sjmallett return; 1545215990Sjmallett a = npei_data_out_cnt.s.p0_ucnt; 1546215990Sjmallett b = (a + npei_data_out_cnt.s.p0_fcnt-1) & 0xffff; 1547215990Sjmallett } 1548215990Sjmallett 1549215990Sjmallett while (1) 1550215990Sjmallett { 1551215990Sjmallett npei_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DATA_OUT_CNT); 1552215990Sjmallett c = (pcie_port) ? npei_data_out_cnt.s.p1_ucnt : npei_data_out_cnt.s.p0_ucnt; 1553215990Sjmallett if (a<=b) 1554215990Sjmallett { 1555215990Sjmallett if ((c<a) || (c>b)) 1556215990Sjmallett return; 1557215990Sjmallett } 1558215990Sjmallett else 1559215990Sjmallett { 1560215990Sjmallett if ((c>b) && (c<a)) 1561215990Sjmallett return; 1562215990Sjmallett } 1563215990Sjmallett } 1564210284Sjmallett } 1565210284Sjmallett else 1566210284Sjmallett { 1567215990Sjmallett cvmx_sli_data_out_cnt_t sli_data_out_cnt; 1568215990Sjmallett int a; 1569215990Sjmallett int b; 1570215990Sjmallett int c; 1571210284Sjmallett 1572215990Sjmallett sli_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_SLI_DATA_OUT_CNT); 1573215990Sjmallett if (pcie_port) 1574210284Sjmallett { 1575215990Sjmallett if (!sli_data_out_cnt.s.p1_fcnt) 1576210284Sjmallett return; 1577215990Sjmallett a = sli_data_out_cnt.s.p1_ucnt; 1578215990Sjmallett b = (a + sli_data_out_cnt.s.p1_fcnt-1) & 0xffff; 1579210284Sjmallett } 1580210284Sjmallett else 1581210284Sjmallett { 1582215990Sjmallett if (!sli_data_out_cnt.s.p0_fcnt) 1583210284Sjmallett return; 1584215990Sjmallett a = sli_data_out_cnt.s.p0_ucnt; 1585215990Sjmallett b = (a + sli_data_out_cnt.s.p0_fcnt-1) & 0xffff; 1586210284Sjmallett } 1587215990Sjmallett 1588215990Sjmallett while (1) 1589215990Sjmallett { 1590215990Sjmallett sli_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_SLI_DATA_OUT_CNT); 1591215990Sjmallett c = (pcie_port) ? sli_data_out_cnt.s.p1_ucnt : sli_data_out_cnt.s.p0_ucnt; 1592215990Sjmallett if (a<=b) 1593215990Sjmallett { 1594215990Sjmallett if ((c<a) || (c>b)) 1595215990Sjmallett return; 1596215990Sjmallett } 1597215990Sjmallett else 1598215990Sjmallett { 1599215990Sjmallett if ((c>b) && (c<a)) 1600215990Sjmallett return; 1601215990Sjmallett } 1602215990Sjmallett } 1603210284Sjmallett } 1604210284Sjmallett} 1605