1210284Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2011 Cavium, Inc. <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 18232812Sjmallett * * Neither the name of Cavium Inc. 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" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. 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 * @file 42210284Sjmallett * 43210284Sjmallett * Interface to PCIe as a host(RC) or target(EP) 44210284Sjmallett * 45232812Sjmallett * <hr>$Revision: 70030 $<hr> 46210284Sjmallett */ 47215990Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 48215990Sjmallett#include <asm/octeon/cvmx.h> 49215990Sjmallett#include <asm/octeon/cvmx-config.h> 50215990Sjmallett#include <asm/octeon/cvmx-clock.h> 51215990Sjmallett#include <asm/octeon/cvmx-ciu-defs.h> 52215990Sjmallett#include <asm/octeon/cvmx-dpi-defs.h> 53232812Sjmallett#include <asm/octeon/cvmx-mio-defs.h> 54215990Sjmallett#include <asm/octeon/cvmx-npi-defs.h> 55215990Sjmallett#include <asm/octeon/cvmx-npei-defs.h> 56215990Sjmallett#include <asm/octeon/cvmx-pci-defs.h> 57215990Sjmallett#include <asm/octeon/cvmx-pcieepx-defs.h> 58215990Sjmallett#include <asm/octeon/cvmx-pciercx-defs.h> 59215990Sjmallett#include <asm/octeon/cvmx-pemx-defs.h> 60215990Sjmallett#include <asm/octeon/cvmx-pexp-defs.h> 61215990Sjmallett#include <asm/octeon/cvmx-pescx-defs.h> 62215990Sjmallett#include <asm/octeon/cvmx-sli-defs.h> 63215990Sjmallett#include <asm/octeon/cvmx-sriox-defs.h> 64232812Sjmallett#include <asm/octeon/cvmx-helper-jtag.h> 65215990Sjmallett 66215990Sjmallett#ifdef CONFIG_CAVIUM_DECODE_RSL 67215990Sjmallett#include <asm/octeon/cvmx-error.h> 68215990Sjmallett#endif 69215990Sjmallett#include <asm/octeon/cvmx-helper.h> 70215990Sjmallett#include <asm/octeon/cvmx-helper-board.h> 71215990Sjmallett#include <asm/octeon/cvmx-helper-errata.h> 72232812Sjmallett#include <asm/octeon/cvmx-qlm.h> 73215990Sjmallett#include <asm/octeon/cvmx-pcie.h> 74215990Sjmallett#include <asm/octeon/cvmx-sysinfo.h> 75215990Sjmallett#include <asm/octeon/cvmx-swap.h> 76215990Sjmallett#include <asm/octeon/cvmx-wqe.h> 77215990Sjmallett#else 78210284Sjmallett#include "cvmx.h" 79232915Sjmallett#if !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 80210284Sjmallett#include "cvmx-csr-db.h" 81232915Sjmallett#endif 82210284Sjmallett#include "cvmx-pcie.h" 83210284Sjmallett#include "cvmx-sysinfo.h" 84210284Sjmallett#include "cvmx-swap.h" 85210284Sjmallett#include "cvmx-wqe.h" 86232816Sjmallett#if !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL) 87215990Sjmallett#include "cvmx-error.h" 88232816Sjmallett#endif 89210284Sjmallett#include "cvmx-helper-errata.h" 90232812Sjmallett#include "cvmx-qlm.h" 91215990Sjmallett#endif 92210284Sjmallett 93215990Sjmallett#define MRRS_CN5XXX 0 /* 128 byte Max Read Request Size */ 94215990Sjmallett#define MPS_CN5XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ 95215990Sjmallett#define MRRS_CN6XXX 3 /* 1024 byte Max Read Request Size */ 96215990Sjmallett#define MPS_CN6XXX 0 /* 128 byte Max Packet Size (Limit of most PCs) */ 97210284Sjmallett 98210284Sjmallett/** 99210284Sjmallett * Return the Core virtual base address for PCIe IO access. IOs are 100210284Sjmallett * read/written as an offset from this address. 101210284Sjmallett * 102210284Sjmallett * @param pcie_port PCIe port the IO is for 103210284Sjmallett * 104210284Sjmallett * @return 64bit Octeon IO base address for read/write 105210284Sjmallett */ 106210284Sjmallettuint64_t cvmx_pcie_get_io_base_address(int pcie_port) 107210284Sjmallett{ 108210284Sjmallett cvmx_pcie_address_t pcie_addr; 109210284Sjmallett pcie_addr.u64 = 0; 110210284Sjmallett pcie_addr.io.upper = 0; 111210284Sjmallett pcie_addr.io.io = 1; 112210284Sjmallett pcie_addr.io.did = 3; 113210284Sjmallett pcie_addr.io.subdid = 2; 114210284Sjmallett pcie_addr.io.es = 1; 115210284Sjmallett pcie_addr.io.port = pcie_port; 116210284Sjmallett return pcie_addr.u64; 117210284Sjmallett} 118210284Sjmallett 119210284Sjmallett 120210284Sjmallett/** 121210284Sjmallett * Size of the IO address region returned at address 122210284Sjmallett * cvmx_pcie_get_io_base_address() 123210284Sjmallett * 124210284Sjmallett * @param pcie_port PCIe port the IO is for 125210284Sjmallett * 126210284Sjmallett * @return Size of the IO window 127210284Sjmallett */ 128210284Sjmallettuint64_t cvmx_pcie_get_io_size(int pcie_port) 129210284Sjmallett{ 130210284Sjmallett return 1ull<<32; 131210284Sjmallett} 132210284Sjmallett 133210284Sjmallett 134210284Sjmallett/** 135210284Sjmallett * Return the Core virtual base address for PCIe MEM access. Memory is 136210284Sjmallett * read/written as an offset from this address. 137210284Sjmallett * 138210284Sjmallett * @param pcie_port PCIe port the IO is for 139210284Sjmallett * 140210284Sjmallett * @return 64bit Octeon IO base address for read/write 141210284Sjmallett */ 142210284Sjmallettuint64_t cvmx_pcie_get_mem_base_address(int pcie_port) 143210284Sjmallett{ 144210284Sjmallett cvmx_pcie_address_t pcie_addr; 145210284Sjmallett pcie_addr.u64 = 0; 146210284Sjmallett pcie_addr.mem.upper = 0; 147210284Sjmallett pcie_addr.mem.io = 1; 148210284Sjmallett pcie_addr.mem.did = 3; 149210284Sjmallett pcie_addr.mem.subdid = 3 + pcie_port; 150210284Sjmallett return pcie_addr.u64; 151210284Sjmallett} 152210284Sjmallett 153210284Sjmallett 154210284Sjmallett/** 155210284Sjmallett * Size of the Mem address region returned at address 156210284Sjmallett * cvmx_pcie_get_mem_base_address() 157210284Sjmallett * 158210284Sjmallett * @param pcie_port PCIe port the IO is for 159210284Sjmallett * 160210284Sjmallett * @return Size of the Mem window 161210284Sjmallett */ 162210284Sjmallettuint64_t cvmx_pcie_get_mem_size(int pcie_port) 163210284Sjmallett{ 164210284Sjmallett return 1ull<<36; 165210284Sjmallett} 166210284Sjmallett 167210284Sjmallett 168210284Sjmallett/** 169210284Sjmallett * @INTERNAL 170210284Sjmallett * Initialize the RC config space CSRs 171210284Sjmallett * 172210284Sjmallett * @param pcie_port PCIe port to initialize 173210284Sjmallett */ 174210284Sjmallettstatic void __cvmx_pcie_rc_initialize_config_space(int pcie_port) 175210284Sjmallett{ 176210284Sjmallett /* Max Payload Size (PCIE*_CFG030[MPS]) */ 177210284Sjmallett /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ 178210284Sjmallett /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ 179210284Sjmallett /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ 180210284Sjmallett { 181210284Sjmallett cvmx_pciercx_cfg030_t pciercx_cfg030; 182210284Sjmallett pciercx_cfg030.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG030(pcie_port)); 183215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) 184215990Sjmallett { 185215990Sjmallett pciercx_cfg030.s.mps = MPS_CN5XXX; 186215990Sjmallett pciercx_cfg030.s.mrrs = MRRS_CN5XXX; 187215990Sjmallett } 188215990Sjmallett else 189215990Sjmallett { 190215990Sjmallett pciercx_cfg030.s.mps = MPS_CN6XXX; 191215990Sjmallett pciercx_cfg030.s.mrrs = MRRS_CN6XXX; 192215990Sjmallett } 193210284Sjmallett pciercx_cfg030.s.ro_en = 1; /* Enable relaxed order processing. This will allow devices to affect read response ordering */ 194210284Sjmallett pciercx_cfg030.s.ns_en = 1; /* Enable no snoop processing. Not used by Octeon */ 195210284Sjmallett pciercx_cfg030.s.ce_en = 1; /* Correctable error reporting enable. */ 196210284Sjmallett pciercx_cfg030.s.nfe_en = 1; /* Non-fatal error reporting enable. */ 197210284Sjmallett pciercx_cfg030.s.fe_en = 1; /* Fatal error reporting enable. */ 198210284Sjmallett pciercx_cfg030.s.ur_en = 1; /* Unsupported request reporting enable. */ 199210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG030(pcie_port), pciercx_cfg030.u32); 200210284Sjmallett } 201210284Sjmallett 202215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 203210284Sjmallett { 204215990Sjmallett /* Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match PCIE*_CFG030[MPS] */ 205215990Sjmallett /* Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 206210284Sjmallett cvmx_npei_ctl_status2_t npei_ctl_status2; 207210284Sjmallett npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); 208215990Sjmallett npei_ctl_status2.s.mps = MPS_CN5XXX; /* Max payload size = 128 bytes for best Octeon DMA performance */ 209215990Sjmallett npei_ctl_status2.s.mrrs = MRRS_CN5XXX; /* Max read request size = 128 bytes for best Octeon DMA performance */ 210215990Sjmallett if (pcie_port) 211215990Sjmallett npei_ctl_status2.s.c1_b1_s = 3; /* Port1 BAR1 Size 256MB */ 212215990Sjmallett else 213215990Sjmallett npei_ctl_status2.s.c0_b1_s = 3; /* Port0 BAR1 Size 256MB */ 214215990Sjmallett 215210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); 216210284Sjmallett } 217215990Sjmallett else 218215990Sjmallett { 219215990Sjmallett /* Max Payload Size (DPI_SLI_PRTX_CFG[MPS]) must match PCIE*_CFG030[MPS] */ 220215990Sjmallett /* Max Read Request Size (DPI_SLI_PRTX_CFG[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 221215990Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 222215990Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 223215990Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port)); 224215990Sjmallett prt_cfg.s.mps = MPS_CN6XXX; 225215990Sjmallett prt_cfg.s.mrrs = MRRS_CN6XXX; 226232812Sjmallett /* Max outstanding load request. */ 227232812Sjmallett prt_cfg.s.molr = 32; 228215990Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port), prt_cfg.u64); 229210284Sjmallett 230215990Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port)); 231215990Sjmallett sli_s2m_portx_ctl.s.mrrs = MRRS_CN6XXX; 232215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port), sli_s2m_portx_ctl.u64); 233215990Sjmallett } 234215990Sjmallett 235210284Sjmallett /* ECRC Generation (PCIE*_CFG070[GE,CE]) */ 236210284Sjmallett { 237210284Sjmallett cvmx_pciercx_cfg070_t pciercx_cfg070; 238210284Sjmallett pciercx_cfg070.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG070(pcie_port)); 239210284Sjmallett pciercx_cfg070.s.ge = 1; /* ECRC generation enable. */ 240210284Sjmallett pciercx_cfg070.s.ce = 1; /* ECRC check enable. */ 241210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG070(pcie_port), pciercx_cfg070.u32); 242210284Sjmallett } 243210284Sjmallett 244210284Sjmallett /* Access Enables (PCIE*_CFG001[MSAE,ME]) */ 245210284Sjmallett /* ME and MSAE should always be set. */ 246210284Sjmallett /* Interrupt Disable (PCIE*_CFG001[I_DIS]) */ 247210284Sjmallett /* System Error Message Enable (PCIE*_CFG001[SEE]) */ 248210284Sjmallett { 249210284Sjmallett cvmx_pciercx_cfg001_t pciercx_cfg001; 250210284Sjmallett pciercx_cfg001.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG001(pcie_port)); 251210284Sjmallett pciercx_cfg001.s.msae = 1; /* Memory space enable. */ 252210284Sjmallett pciercx_cfg001.s.me = 1; /* Bus master enable. */ 253210284Sjmallett pciercx_cfg001.s.i_dis = 1; /* INTx assertion disable. */ 254210284Sjmallett pciercx_cfg001.s.see = 1; /* SERR# enable */ 255210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG001(pcie_port), pciercx_cfg001.u32); 256210284Sjmallett } 257210284Sjmallett 258210284Sjmallett 259210284Sjmallett /* Advanced Error Recovery Message Enables */ 260210284Sjmallett /* (PCIE*_CFG066,PCIE*_CFG067,PCIE*_CFG069) */ 261210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG066(pcie_port), 0); 262210284Sjmallett /* Use CVMX_PCIERCX_CFG067 hardware default */ 263210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG069(pcie_port), 0); 264210284Sjmallett 265210284Sjmallett 266210284Sjmallett /* Active State Power Management (PCIE*_CFG032[ASLPC]) */ 267210284Sjmallett { 268210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 269210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 270210284Sjmallett pciercx_cfg032.s.aslpc = 0; /* Active state Link PM control. */ 271210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG032(pcie_port), pciercx_cfg032.u32); 272210284Sjmallett } 273210284Sjmallett 274210284Sjmallett /* Link Width Mode (PCIERCn_CFG452[LME]) - Set during cvmx_pcie_rc_initialize_link() */ 275210284Sjmallett /* Primary Bus Number (PCIERCn_CFG006[PBNUM]) */ 276210284Sjmallett { 277210284Sjmallett /* We set the primary bus number to 1 so IDT bridges are happy. They don't like zero */ 278210284Sjmallett cvmx_pciercx_cfg006_t pciercx_cfg006; 279210284Sjmallett pciercx_cfg006.u32 = 0; 280210284Sjmallett pciercx_cfg006.s.pbnum = 1; 281210284Sjmallett pciercx_cfg006.s.sbnum = 1; 282210284Sjmallett pciercx_cfg006.s.subbnum = 1; 283210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG006(pcie_port), pciercx_cfg006.u32); 284210284Sjmallett } 285210284Sjmallett 286210284Sjmallett /* Memory-mapped I/O BAR (PCIERCn_CFG008) */ 287210284Sjmallett /* Most applications should disable the memory-mapped I/O BAR by */ 288210284Sjmallett /* setting PCIERCn_CFG008[ML_ADDR] < PCIERCn_CFG008[MB_ADDR] */ 289210284Sjmallett { 290210284Sjmallett cvmx_pciercx_cfg008_t pciercx_cfg008; 291210284Sjmallett pciercx_cfg008.u32 = 0; 292210284Sjmallett pciercx_cfg008.s.mb_addr = 0x100; 293210284Sjmallett pciercx_cfg008.s.ml_addr = 0; 294210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG008(pcie_port), pciercx_cfg008.u32); 295210284Sjmallett } 296210284Sjmallett 297210284Sjmallett /* Prefetchable BAR (PCIERCn_CFG009,PCIERCn_CFG010,PCIERCn_CFG011) */ 298210284Sjmallett /* Most applications should disable the prefetchable BAR by setting */ 299210284Sjmallett /* PCIERCn_CFG011[UMEM_LIMIT],PCIERCn_CFG009[LMEM_LIMIT] < */ 300210284Sjmallett /* PCIERCn_CFG010[UMEM_BASE],PCIERCn_CFG009[LMEM_BASE] */ 301210284Sjmallett { 302210284Sjmallett cvmx_pciercx_cfg009_t pciercx_cfg009; 303210284Sjmallett cvmx_pciercx_cfg010_t pciercx_cfg010; 304210284Sjmallett cvmx_pciercx_cfg011_t pciercx_cfg011; 305210284Sjmallett pciercx_cfg009.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG009(pcie_port)); 306210284Sjmallett pciercx_cfg010.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG010(pcie_port)); 307210284Sjmallett pciercx_cfg011.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG011(pcie_port)); 308210284Sjmallett pciercx_cfg009.s.lmem_base = 0x100; 309210284Sjmallett pciercx_cfg009.s.lmem_limit = 0; 310210284Sjmallett pciercx_cfg010.s.umem_base = 0x100; 311210284Sjmallett pciercx_cfg011.s.umem_limit = 0; 312210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG009(pcie_port), pciercx_cfg009.u32); 313210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG010(pcie_port), pciercx_cfg010.u32); 314210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG011(pcie_port), pciercx_cfg011.u32); 315210284Sjmallett } 316210284Sjmallett 317210284Sjmallett /* System Error Interrupt Enables (PCIERCn_CFG035[SECEE,SEFEE,SENFEE]) */ 318210284Sjmallett /* PME Interrupt Enables (PCIERCn_CFG035[PMEIE]) */ 319210284Sjmallett { 320210284Sjmallett cvmx_pciercx_cfg035_t pciercx_cfg035; 321210284Sjmallett pciercx_cfg035.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG035(pcie_port)); 322210284Sjmallett pciercx_cfg035.s.secee = 1; /* System error on correctable error enable. */ 323210284Sjmallett pciercx_cfg035.s.sefee = 1; /* System error on fatal error enable. */ 324210284Sjmallett pciercx_cfg035.s.senfee = 1; /* System error on non-fatal error enable. */ 325210284Sjmallett pciercx_cfg035.s.pmeie = 1; /* PME interrupt enable. */ 326210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG035(pcie_port), pciercx_cfg035.u32); 327210284Sjmallett } 328210284Sjmallett 329210284Sjmallett /* Advanced Error Recovery Interrupt Enables */ 330210284Sjmallett /* (PCIERCn_CFG075[CERE,NFERE,FERE]) */ 331210284Sjmallett { 332210284Sjmallett cvmx_pciercx_cfg075_t pciercx_cfg075; 333210284Sjmallett pciercx_cfg075.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG075(pcie_port)); 334210284Sjmallett pciercx_cfg075.s.cere = 1; /* Correctable error reporting enable. */ 335210284Sjmallett pciercx_cfg075.s.nfere = 1; /* Non-fatal error reporting enable. */ 336210284Sjmallett pciercx_cfg075.s.fere = 1; /* Fatal error reporting enable. */ 337210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG075(pcie_port), pciercx_cfg075.u32); 338210284Sjmallett } 339210284Sjmallett 340210284Sjmallett /* HP Interrupt Enables (PCIERCn_CFG034[HPINT_EN], */ 341210284Sjmallett /* PCIERCn_CFG034[DLLS_EN,CCINT_EN]) */ 342210284Sjmallett { 343210284Sjmallett cvmx_pciercx_cfg034_t pciercx_cfg034; 344210284Sjmallett pciercx_cfg034.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG034(pcie_port)); 345210284Sjmallett pciercx_cfg034.s.hpint_en = 1; /* Hot-plug interrupt enable. */ 346210284Sjmallett pciercx_cfg034.s.dlls_en = 1; /* Data Link Layer state changed enable */ 347210284Sjmallett pciercx_cfg034.s.ccint_en = 1; /* Command completed interrupt enable. */ 348210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG034(pcie_port), pciercx_cfg034.u32); 349210284Sjmallett } 350210284Sjmallett} 351210284Sjmallett 352210284Sjmallett/** 353210284Sjmallett * @INTERNAL 354215990Sjmallett * Initialize a host mode PCIe gen 1 link. This function takes a PCIe 355210284Sjmallett * port from reset to a link up state. Software can then begin 356210284Sjmallett * configuring the rest of the link. 357210284Sjmallett * 358210284Sjmallett * @param pcie_port PCIe port to initialize 359210284Sjmallett * 360210284Sjmallett * @return Zero on success 361210284Sjmallett */ 362215990Sjmallettstatic int __cvmx_pcie_rc_initialize_link_gen1(int pcie_port) 363210284Sjmallett{ 364210284Sjmallett uint64_t start_cycle; 365210284Sjmallett cvmx_pescx_ctl_status_t pescx_ctl_status; 366210284Sjmallett cvmx_pciercx_cfg452_t pciercx_cfg452; 367210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 368210284Sjmallett cvmx_pciercx_cfg448_t pciercx_cfg448; 369210284Sjmallett 370210284Sjmallett /* Set the lane width */ 371210284Sjmallett pciercx_cfg452.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG452(pcie_port)); 372210284Sjmallett pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); 373210284Sjmallett if (pescx_ctl_status.s.qlm_cfg == 0) 374210284Sjmallett { 375210284Sjmallett /* We're in 8 lane (56XX) or 4 lane (54XX) mode */ 376210284Sjmallett pciercx_cfg452.s.lme = 0xf; 377210284Sjmallett } 378210284Sjmallett else 379210284Sjmallett { 380210284Sjmallett /* We're in 4 lane (56XX) or 2 lane (52XX) mode */ 381210284Sjmallett pciercx_cfg452.s.lme = 0x7; 382210284Sjmallett } 383210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG452(pcie_port), pciercx_cfg452.u32); 384210284Sjmallett 385210284Sjmallett /* CN52XX pass 1.x has an errata where length mismatches on UR responses can 386210284Sjmallett cause bus errors on 64bit memory reads. Turning off length error 387210284Sjmallett checking fixes this */ 388210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 389210284Sjmallett { 390210284Sjmallett cvmx_pciercx_cfg455_t pciercx_cfg455; 391210284Sjmallett pciercx_cfg455.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG455(pcie_port)); 392210284Sjmallett pciercx_cfg455.s.m_cpl_len_err = 1; 393210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG455(pcie_port), pciercx_cfg455.u32); 394210284Sjmallett } 395210284Sjmallett 396210284Sjmallett /* Lane swap needs to be manually enabled for CN52XX */ 397210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX) && (pcie_port == 1)) 398210284Sjmallett { 399216476Sjmallett switch (cvmx_sysinfo_get()->board_type) 400216476Sjmallett { 401216476Sjmallett#if defined(OCTEON_VENDOR_LANNER) 402216476Sjmallett case CVMX_BOARD_TYPE_CUST_LANNER_MR730: 403216476Sjmallett break; 404216476Sjmallett#endif 405216476Sjmallett default: 406216476Sjmallett pescx_ctl_status.s.lane_swp = 1; 407216476Sjmallett break; 408216476Sjmallett } 409210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port),pescx_ctl_status.u64); 410210284Sjmallett } 411210284Sjmallett 412210284Sjmallett /* Bring up the link */ 413210284Sjmallett pescx_ctl_status.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS(pcie_port)); 414210284Sjmallett pescx_ctl_status.s.lnk_enb = 1; 415210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS(pcie_port), pescx_ctl_status.u64); 416210284Sjmallett 417210284Sjmallett /* CN52XX pass 1.0: Due to a bug in 2nd order CDR, it needs to be disabled */ 418210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_0)) 419210284Sjmallett __cvmx_helper_errata_qlm_disable_2nd_order_cdr(0); 420210284Sjmallett 421210284Sjmallett /* Wait for the link to come up */ 422210284Sjmallett start_cycle = cvmx_get_cycle(); 423210284Sjmallett do 424210284Sjmallett { 425250428Simp if (cvmx_get_cycle() - start_cycle > 100*cvmx_clock_get_rate(CVMX_CLOCK_CORE)) 426210284Sjmallett { 427210284Sjmallett cvmx_dprintf("PCIe: Port %d link timeout\n", pcie_port); 428210284Sjmallett return -1; 429210284Sjmallett } 430250428Simp cvmx_wait(50000); 431210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 432210284Sjmallett } while (pciercx_cfg032.s.dlla == 0); 433210284Sjmallett 434215990Sjmallett /* Clear all pending errors */ 435215990Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_INT_SUM, cvmx_read_csr(CVMX_PEXP_NPEI_INT_SUM)); 436215990Sjmallett 437210284Sjmallett /* Update the Replay Time Limit. Empirically, some PCIe devices take a 438210284Sjmallett little longer to respond than expected under load. As a workaround for 439210284Sjmallett this we configure the Replay Time Limit to the value expected for a 512 440210284Sjmallett byte MPS instead of our actual 256 byte MPS. The numbers below are 441210284Sjmallett directly from the PCIe spec table 3-4 */ 442210284Sjmallett pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); 443210284Sjmallett switch (pciercx_cfg032.s.nlw) 444210284Sjmallett { 445210284Sjmallett case 1: /* 1 lane */ 446210284Sjmallett pciercx_cfg448.s.rtl = 1677; 447210284Sjmallett break; 448210284Sjmallett case 2: /* 2 lanes */ 449210284Sjmallett pciercx_cfg448.s.rtl = 867; 450210284Sjmallett break; 451210284Sjmallett case 4: /* 4 lanes */ 452210284Sjmallett pciercx_cfg448.s.rtl = 462; 453210284Sjmallett break; 454210284Sjmallett case 8: /* 8 lanes */ 455210284Sjmallett pciercx_cfg448.s.rtl = 258; 456210284Sjmallett break; 457210284Sjmallett } 458210284Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); 459210284Sjmallett 460210284Sjmallett return 0; 461210284Sjmallett} 462210284Sjmallett 463232812Sjmallettstatic inline void __cvmx_increment_ba(cvmx_sli_mem_access_subidx_t *pmas) 464232812Sjmallett{ 465232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 466232812Sjmallett pmas->cn68xx.ba++; 467232812Sjmallett else 468232812Sjmallett pmas->cn63xx.ba++; 469232812Sjmallett} 470210284Sjmallett 471210284Sjmallett/** 472215990Sjmallett * Initialize a PCIe gen 1 port for use in host(RC) mode. It doesn't enumerate 473215990Sjmallett * the bus. 474210284Sjmallett * 475210284Sjmallett * @param pcie_port PCIe port to initialize 476210284Sjmallett * 477210284Sjmallett * @return Zero on success 478210284Sjmallett */ 479215990Sjmallettstatic int __cvmx_pcie_rc_initialize_gen1(int pcie_port) 480210284Sjmallett{ 481210284Sjmallett int i; 482215990Sjmallett int base; 483215990Sjmallett uint64_t addr_swizzle; 484210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 485210284Sjmallett cvmx_pescx_bist_status_t pescx_bist_status; 486210284Sjmallett cvmx_pescx_bist_status2_t pescx_bist_status2; 487210284Sjmallett cvmx_npei_ctl_status_t npei_ctl_status; 488210284Sjmallett cvmx_npei_mem_access_ctl_t npei_mem_access_ctl; 489210284Sjmallett cvmx_npei_mem_access_subidx_t mem_access_subid; 490210284Sjmallett cvmx_npei_dbg_data_t npei_dbg_data; 491210284Sjmallett cvmx_pescx_ctl_status2_t pescx_ctl_status2; 492210284Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 493215990Sjmallett cvmx_npei_bar1_indexx_t bar1_index; 494210284Sjmallett 495210284Sjmallettretry: 496210284Sjmallett /* Make sure we aren't trying to setup a target mode interface in host mode */ 497210284Sjmallett npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); 498210284Sjmallett if ((pcie_port==0) && !npei_ctl_status.s.host_mode) 499210284Sjmallett { 500215990Sjmallett cvmx_dprintf("PCIe: Port %d in endpoint mode\n", pcie_port); 501210284Sjmallett return -1; 502210284Sjmallett } 503210284Sjmallett 504210284Sjmallett /* Make sure a CN52XX isn't trying to bring up port 1 when it is disabled */ 505210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX)) 506210284Sjmallett { 507210284Sjmallett npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 508210284Sjmallett if ((pcie_port==1) && npei_dbg_data.cn52xx.qlm0_link_width) 509210284Sjmallett { 510210284Sjmallett cvmx_dprintf("PCIe: ERROR: cvmx_pcie_rc_initialize() called on port1, but port1 is disabled\n"); 511210284Sjmallett return -1; 512210284Sjmallett } 513210284Sjmallett } 514210284Sjmallett 515230040Sgonzo /* Make sure a CN56XX pass 1 isn't trying to do anything; errata for PASS 1 */ 516230040Sgonzo if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) { 517230040Sgonzo cvmx_dprintf ("PCIe port %d: CN56XX_PASS_1, skipping\n", pcie_port); 518230040Sgonzo return -1; 519230040Sgonzo } 520230040Sgonzo 521210284Sjmallett /* PCIe switch arbitration mode. '0' == fixed priority NPEI, PCIe0, then PCIe1. '1' == round robin. */ 522210284Sjmallett npei_ctl_status.s.arb = 1; 523210284Sjmallett /* Allow up to 0x20 config retries */ 524210284Sjmallett npei_ctl_status.s.cfg_rtry = 0x20; 525210284Sjmallett /* CN52XX pass1.x has an errata where P0_NTAGS and P1_NTAGS don't reset */ 526210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 527210284Sjmallett { 528210284Sjmallett npei_ctl_status.s.p0_ntags = 0x20; 529210284Sjmallett npei_ctl_status.s.p1_ntags = 0x20; 530210284Sjmallett } 531210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS, npei_ctl_status.u64); 532210284Sjmallett 533210284Sjmallett /* Bring the PCIe out of reset */ 534210284Sjmallett if (cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) 535210284Sjmallett { 536210284Sjmallett /* The EBH5200 board swapped the PCIe reset lines on the board. As a 537210284Sjmallett workaround for this bug, we bring both PCIe ports out of reset at 538210284Sjmallett the same time instead of on separate calls. So for port 0, we bring 539210284Sjmallett both out of reset and do nothing on port 1 */ 540210284Sjmallett if (pcie_port == 0) 541210284Sjmallett { 542210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 543210284Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 544210284Sjmallett most likely someone is trying to init it again without a proper 545210284Sjmallett PCIe reset */ 546210284Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 547210284Sjmallett { 548210284Sjmallett /* Reset the ports */ 549210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 550210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 551210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 552210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 553210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 554210284Sjmallett /* Wait until pcie resets the ports. */ 555210284Sjmallett cvmx_wait_usec(2000); 556210284Sjmallett } 557210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 558210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 559210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 560210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 561210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 562210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 563210284Sjmallett } 564210284Sjmallett } 565210284Sjmallett else 566210284Sjmallett { 567210284Sjmallett /* The normal case: The PCIe ports are completely separate and can be 568210284Sjmallett brought out of reset independently */ 569210284Sjmallett if (pcie_port) 570210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 571210284Sjmallett else 572210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 573210284Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 574210284Sjmallett most likely someone is trying to init it again without a proper 575210284Sjmallett PCIe reset */ 576210284Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 577210284Sjmallett { 578210284Sjmallett /* Reset the port */ 579210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 580210284Sjmallett if (pcie_port) 581210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 582210284Sjmallett else 583210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 584210284Sjmallett /* Wait until pcie resets the ports. */ 585210284Sjmallett cvmx_wait_usec(2000); 586210284Sjmallett } 587210284Sjmallett if (pcie_port) 588210284Sjmallett { 589210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 590210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 591210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 592210284Sjmallett } 593210284Sjmallett else 594210284Sjmallett { 595210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 596210284Sjmallett ciu_soft_prst.s.soft_prst = 0; 597210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 598210284Sjmallett } 599210284Sjmallett } 600210284Sjmallett 601210284Sjmallett /* Wait for PCIe reset to complete. Due to errata PCIE-700, we don't poll 602210284Sjmallett PESCX_CTL_STATUS2[PCIERST], but simply wait a fixed number of cycles */ 603210284Sjmallett cvmx_wait(400000); 604210284Sjmallett 605210284Sjmallett /* PESCX_BIST_STATUS2[PCLK_RUN] was missing on pass 1 of CN56XX and 606210284Sjmallett CN52XX, so we only probe it on newer chips */ 607210284Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) && !OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 608210284Sjmallett { 609210284Sjmallett /* Clear PCLK_RUN so we can check if the clock is running */ 610210284Sjmallett pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); 611210284Sjmallett pescx_ctl_status2.s.pclk_run = 1; 612210284Sjmallett cvmx_write_csr(CVMX_PESCX_CTL_STATUS2(pcie_port), pescx_ctl_status2.u64); 613210284Sjmallett /* Now that we cleared PCLK_RUN, wait for it to be set again telling 614210284Sjmallett us the clock is running */ 615210284Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CTL_STATUS2(pcie_port), 616210284Sjmallett cvmx_pescx_ctl_status2_t, pclk_run, ==, 1, 10000)) 617210284Sjmallett { 618210284Sjmallett cvmx_dprintf("PCIe: Port %d isn't clocked, skipping.\n", pcie_port); 619210284Sjmallett return -1; 620210284Sjmallett } 621210284Sjmallett } 622210284Sjmallett 623210284Sjmallett /* Check and make sure PCIe came out of reset. If it doesn't the board 624210284Sjmallett probably hasn't wired the clocks up and the interface should be 625210284Sjmallett skipped */ 626210284Sjmallett pescx_ctl_status2.u64 = cvmx_read_csr(CVMX_PESCX_CTL_STATUS2(pcie_port)); 627210284Sjmallett if (pescx_ctl_status2.s.pcierst) 628210284Sjmallett { 629210284Sjmallett cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); 630210284Sjmallett return -1; 631210284Sjmallett } 632210284Sjmallett 633210284Sjmallett /* Check BIST2 status. If any bits are set skip this interface. This 634210284Sjmallett is an attempt to catch PCIE-813 on pass 1 parts */ 635210284Sjmallett pescx_bist_status2.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS2(pcie_port)); 636210284Sjmallett if (pescx_bist_status2.u64) 637210284Sjmallett { 638210284Sjmallett cvmx_dprintf("PCIe: Port %d BIST2 failed. Most likely this port isn't hooked up, skipping.\n", pcie_port); 639210284Sjmallett return -1; 640210284Sjmallett } 641210284Sjmallett 642210284Sjmallett /* Check BIST status */ 643210284Sjmallett pescx_bist_status.u64 = cvmx_read_csr(CVMX_PESCX_BIST_STATUS(pcie_port)); 644210284Sjmallett if (pescx_bist_status.u64) 645210284Sjmallett cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pescx_bist_status.u64)); 646210284Sjmallett 647210284Sjmallett /* Initialize the config space CSRs */ 648210284Sjmallett __cvmx_pcie_rc_initialize_config_space(pcie_port); 649210284Sjmallett 650210284Sjmallett /* Bring the link up */ 651215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen1(pcie_port)) 652210284Sjmallett { 653215990Sjmallett cvmx_dprintf("PCIe: Failed to initialize port %d, probably the slot is empty\n", pcie_port); 654210284Sjmallett return -1; 655210284Sjmallett } 656210284Sjmallett 657210284Sjmallett /* Store merge control (NPEI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ 658210284Sjmallett npei_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL); 659210284Sjmallett npei_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ 660210284Sjmallett npei_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ 661210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_CTL, npei_mem_access_ctl.u64); 662210284Sjmallett 663210284Sjmallett /* Setup Mem access SubDIDs */ 664210284Sjmallett mem_access_subid.u64 = 0; 665210284Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 666210284Sjmallett mem_access_subid.s.nmerge = 1; /* Due to an errata on pass 1 chips, no merging is allowed. */ 667210284Sjmallett mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ 668210284Sjmallett mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ 669210284Sjmallett mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ 670210284Sjmallett mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ 671210284Sjmallett mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ 672210284Sjmallett mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ 673210284Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 674210284Sjmallett 675210284Sjmallett /* Setup mem access 12-15 for port 0, 16-19 for port 1, supplying 36 bits of address space */ 676210284Sjmallett for (i=12 + pcie_port*4; i<16 + pcie_port*4; i++) 677210284Sjmallett { 678210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); 679210284Sjmallett mem_access_subid.s.ba += 1; /* Set each SUBID to extend the addressable range */ 680210284Sjmallett } 681210284Sjmallett 682210284Sjmallett /* Disable the peer to peer forwarding register. This must be setup 683210284Sjmallett by the OS after it enumerates the bus and assigns addresses to the 684210284Sjmallett PCIe busses */ 685210284Sjmallett for (i=0; i<4; i++) 686210284Sjmallett { 687210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2P_BARX_START(i, pcie_port), -1); 688210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2P_BARX_END(i, pcie_port), -1); 689210284Sjmallett } 690210284Sjmallett 691210284Sjmallett /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ 692210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR0_START(pcie_port), 0); 693210284Sjmallett 694215990Sjmallett /* BAR1 follows BAR2 with a gap so it has the same address as for gen2. */ 695215990Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); 696210284Sjmallett 697215990Sjmallett bar1_index.u32 = 0; 698215990Sjmallett bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); 699215990Sjmallett bar1_index.s.ca = 1; /* Not Cached */ 700215990Sjmallett bar1_index.s.end_swp = 1; /* Endian Swap mode */ 701215990Sjmallett bar1_index.s.addr_v = 1; /* Valid entry */ 702215990Sjmallett 703215990Sjmallett base = pcie_port ? 16 : 0; 704215990Sjmallett 705215990Sjmallett /* Big endian swizzle for 32-bit PEXP_NCB register. */ 706215990Sjmallett#ifdef __MIPSEB__ 707215990Sjmallett addr_swizzle = 4; 708215990Sjmallett#else 709215990Sjmallett addr_swizzle = 0; 710215990Sjmallett#endif 711215990Sjmallett for (i = 0; i < 16; i++) { 712215990Sjmallett cvmx_write64_uint32((CVMX_PEXP_NPEI_BAR1_INDEXX(base) ^ addr_swizzle), bar1_index.u32); 713215990Sjmallett base++; 714215990Sjmallett /* 256MB / 16 >> 22 == 4 */ 715215990Sjmallett bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); 716215990Sjmallett } 717215990Sjmallett 718210284Sjmallett /* Set Octeon's BAR2 to decode 0-2^39. Bar0 and Bar1 take precedence 719210284Sjmallett where they overlap. It also overlaps with the device addresses, so 720210284Sjmallett make sure the peer to peer forwarding is set right */ 721210284Sjmallett cvmx_write_csr(CVMX_PESCX_P2N_BAR2_START(pcie_port), 0); 722210284Sjmallett 723210284Sjmallett /* Setup BAR2 attributes */ 724210284Sjmallett /* Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) */ 725210284Sjmallett /* � PTLP_RO,CTLP_RO should normally be set (except for debug). */ 726210284Sjmallett /* � WAIT_COM=0 will likely work for all applications. */ 727210284Sjmallett /* Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]) */ 728210284Sjmallett if (pcie_port) 729210284Sjmallett { 730210284Sjmallett cvmx_npei_ctl_port1_t npei_ctl_port; 731210284Sjmallett npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT1); 732210284Sjmallett npei_ctl_port.s.bar2_enb = 1; 733210284Sjmallett npei_ctl_port.s.bar2_esx = 1; 734210284Sjmallett npei_ctl_port.s.bar2_cax = 0; 735210284Sjmallett npei_ctl_port.s.ptlp_ro = 1; 736210284Sjmallett npei_ctl_port.s.ctlp_ro = 1; 737210284Sjmallett npei_ctl_port.s.wait_com = 0; 738210284Sjmallett npei_ctl_port.s.waitl_com = 0; 739210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT1, npei_ctl_port.u64); 740210284Sjmallett } 741210284Sjmallett else 742210284Sjmallett { 743210284Sjmallett cvmx_npei_ctl_port0_t npei_ctl_port; 744210284Sjmallett npei_ctl_port.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_PORT0); 745210284Sjmallett npei_ctl_port.s.bar2_enb = 1; 746210284Sjmallett npei_ctl_port.s.bar2_esx = 1; 747210284Sjmallett npei_ctl_port.s.bar2_cax = 0; 748210284Sjmallett npei_ctl_port.s.ptlp_ro = 1; 749210284Sjmallett npei_ctl_port.s.ctlp_ro = 1; 750210284Sjmallett npei_ctl_port.s.wait_com = 0; 751210284Sjmallett npei_ctl_port.s.waitl_com = 0; 752210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_PORT0, npei_ctl_port.u64); 753210284Sjmallett } 754210284Sjmallett 755210284Sjmallett /* Both pass 1 and pass 2 of CN52XX and CN56XX have an errata that causes 756210284Sjmallett TLP ordering to not be preserved after multiple PCIe port resets. This 757210284Sjmallett code detects this fault and corrects it by aligning the TLP counters 758210284Sjmallett properly. Another link reset is then performed. See PCIE-13340 */ 759210284Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) || 760210284Sjmallett OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X)) 761210284Sjmallett { 762210284Sjmallett cvmx_npei_dbg_data_t dbg_data; 763210284Sjmallett int old_in_fif_p_count; 764210284Sjmallett int in_fif_p_count; 765210284Sjmallett int out_p_count; 766210284Sjmallett int in_p_offset = (OCTEON_IS_MODEL(OCTEON_CN52XX_PASS1_X) || OCTEON_IS_MODEL(OCTEON_CN56XX_PASS1_X)) ? 4 : 1; 767210284Sjmallett int i; 768210284Sjmallett 769210284Sjmallett /* Choose a write address of 1MB. It should be harmless as all bars 770210284Sjmallett haven't been setup */ 771210284Sjmallett uint64_t write_address = (cvmx_pcie_get_mem_base_address(pcie_port) + 0x100000) | (1ull<<63); 772210284Sjmallett 773210284Sjmallett /* Make sure at least in_p_offset have been executed before we try and 774210284Sjmallett read in_fif_p_count */ 775210284Sjmallett i = in_p_offset; 776210284Sjmallett while (i--) 777210284Sjmallett { 778210284Sjmallett cvmx_write64_uint32(write_address, 0); 779210284Sjmallett cvmx_wait(10000); 780210284Sjmallett } 781210284Sjmallett 782210284Sjmallett /* Read the IN_FIF_P_COUNT from the debug select. IN_FIF_P_COUNT can be 783210284Sjmallett unstable sometimes so read it twice with a write between the reads. 784210284Sjmallett This way we can tell the value is good as it will increment by one 785210284Sjmallett due to the write */ 786210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd7fc : 0xcffc); 787210284Sjmallett cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); 788210284Sjmallett do 789210284Sjmallett { 790210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 791210284Sjmallett old_in_fif_p_count = dbg_data.s.data & 0xff; 792210284Sjmallett cvmx_write64_uint32(write_address, 0); 793210284Sjmallett cvmx_wait(10000); 794210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 795210284Sjmallett in_fif_p_count = dbg_data.s.data & 0xff; 796210284Sjmallett } while (in_fif_p_count != ((old_in_fif_p_count+1) & 0xff)); 797210284Sjmallett 798210284Sjmallett /* Update in_fif_p_count for it's offset with respect to out_p_count */ 799210284Sjmallett in_fif_p_count = (in_fif_p_count + in_p_offset) & 0xff; 800210284Sjmallett 801210284Sjmallett /* Read the OUT_P_COUNT from the debug select */ 802210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_DBG_SELECT, (pcie_port) ? 0xd00f : 0xc80f); 803210284Sjmallett cvmx_read_csr(CVMX_PEXP_NPEI_DBG_SELECT); 804210284Sjmallett dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); 805210284Sjmallett out_p_count = (dbg_data.s.data>>1) & 0xff; 806210284Sjmallett 807210284Sjmallett /* Check that the two counters are aligned */ 808210284Sjmallett if (out_p_count != in_fif_p_count) 809210284Sjmallett { 810210284Sjmallett cvmx_dprintf("PCIe: Port %d aligning TLP counters as workaround to maintain ordering\n", pcie_port); 811210284Sjmallett while (in_fif_p_count != 0) 812210284Sjmallett { 813210284Sjmallett cvmx_write64_uint32(write_address, 0); 814210284Sjmallett cvmx_wait(10000); 815210284Sjmallett in_fif_p_count = (in_fif_p_count + 1) & 0xff; 816210284Sjmallett } 817210284Sjmallett /* The EBH5200 board swapped the PCIe reset lines on the board. This 818210284Sjmallett means we must bring both links down and up, which will cause the 819210284Sjmallett PCIe0 to need alignment again. Lots of messages will be displayed, 820210284Sjmallett but everything should work */ 821210284Sjmallett if ((cvmx_sysinfo_get()->board_type == CVMX_BOARD_TYPE_EBH5200) && 822210284Sjmallett (pcie_port == 1)) 823210284Sjmallett cvmx_pcie_rc_initialize(0); 824210284Sjmallett /* Rety bringing this port up */ 825210284Sjmallett goto retry; 826210284Sjmallett } 827210284Sjmallett } 828210284Sjmallett 829210284Sjmallett /* Display the link status */ 830210284Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 831210284Sjmallett cvmx_dprintf("PCIe: Port %d link active, %d lanes\n", pcie_port, pciercx_cfg032.s.nlw); 832210284Sjmallett 833210284Sjmallett return 0; 834210284Sjmallett} 835210284Sjmallett 836210284Sjmallett/** 837215990Sjmallett * @INTERNAL 838215990Sjmallett * Initialize a host mode PCIe gen 2 link. This function takes a PCIe 839215990Sjmallett * port from reset to a link up state. Software can then begin 840215990Sjmallett * configuring the rest of the link. 841215990Sjmallett * 842215990Sjmallett * @param pcie_port PCIe port to initialize 843215990Sjmallett * 844215990Sjmallett * @return Zero on success 845215990Sjmallett */ 846215990Sjmallettstatic int __cvmx_pcie_rc_initialize_link_gen2(int pcie_port) 847215990Sjmallett{ 848215990Sjmallett uint64_t start_cycle; 849215990Sjmallett cvmx_pemx_ctl_status_t pem_ctl_status; 850215990Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 851215990Sjmallett cvmx_pciercx_cfg448_t pciercx_cfg448; 852215990Sjmallett 853215990Sjmallett /* Bring up the link */ 854215990Sjmallett pem_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); 855215990Sjmallett pem_ctl_status.s.lnk_enb = 1; 856215990Sjmallett cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pem_ctl_status.u64); 857215990Sjmallett 858215990Sjmallett /* Wait for the link to come up */ 859215990Sjmallett start_cycle = cvmx_get_cycle(); 860215990Sjmallett do 861215990Sjmallett { 862215990Sjmallett if (cvmx_get_cycle() - start_cycle > cvmx_clock_get_rate(CVMX_CLOCK_CORE)) 863215990Sjmallett return -1; 864215990Sjmallett cvmx_wait(10000); 865215990Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 866232812Sjmallett } while ((pciercx_cfg032.s.dlla == 0) || (pciercx_cfg032.s.lt == 1)); 867215990Sjmallett 868215990Sjmallett /* Update the Replay Time Limit. Empirically, some PCIe devices take a 869215990Sjmallett little longer to respond than expected under load. As a workaround for 870215990Sjmallett this we configure the Replay Time Limit to the value expected for a 512 871215990Sjmallett byte MPS instead of our actual 256 byte MPS. The numbers below are 872215990Sjmallett directly from the PCIe spec table 3-4 */ 873215990Sjmallett pciercx_cfg448.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG448(pcie_port)); 874215990Sjmallett switch (pciercx_cfg032.s.nlw) 875215990Sjmallett { 876215990Sjmallett case 1: /* 1 lane */ 877215990Sjmallett pciercx_cfg448.s.rtl = 1677; 878215990Sjmallett break; 879215990Sjmallett case 2: /* 2 lanes */ 880215990Sjmallett pciercx_cfg448.s.rtl = 867; 881215990Sjmallett break; 882215990Sjmallett case 4: /* 4 lanes */ 883215990Sjmallett pciercx_cfg448.s.rtl = 462; 884215990Sjmallett break; 885215990Sjmallett case 8: /* 8 lanes */ 886215990Sjmallett pciercx_cfg448.s.rtl = 258; 887215990Sjmallett break; 888215990Sjmallett } 889215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG448(pcie_port), pciercx_cfg448.u32); 890215990Sjmallett 891215990Sjmallett return 0; 892215990Sjmallett} 893215990Sjmallett 894215990Sjmallett 895215990Sjmallett/** 896215990Sjmallett * Initialize a PCIe gen 2 port for use in host(RC) mode. It doesn't enumerate 897215990Sjmallett * the bus. 898215990Sjmallett * 899215990Sjmallett * @param pcie_port PCIe port to initialize 900215990Sjmallett * 901215990Sjmallett * @return Zero on success 902215990Sjmallett */ 903215990Sjmallettstatic int __cvmx_pcie_rc_initialize_gen2(int pcie_port) 904215990Sjmallett{ 905215990Sjmallett int i; 906215990Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 907215990Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 908215990Sjmallett cvmx_pemx_bar_ctl_t pemx_bar_ctl; 909215990Sjmallett cvmx_pemx_ctl_status_t pemx_ctl_status; 910215990Sjmallett cvmx_pemx_bist_status_t pemx_bist_status; 911215990Sjmallett cvmx_pemx_bist_status2_t pemx_bist_status2; 912215990Sjmallett cvmx_pciercx_cfg032_t pciercx_cfg032; 913215990Sjmallett cvmx_pciercx_cfg515_t pciercx_cfg515; 914215990Sjmallett cvmx_sli_ctl_portx_t sli_ctl_portx; 915215990Sjmallett cvmx_sli_mem_access_ctl_t sli_mem_access_ctl; 916215990Sjmallett cvmx_sli_mem_access_subidx_t mem_access_subid; 917215990Sjmallett cvmx_pemx_bar1_indexx_t bar1_index; 918232812Sjmallett int ep_mode; 919215990Sjmallett 920232812Sjmallett /* Make sure this interface is PCIe */ 921232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX) || OCTEON_IS_MODEL(OCTEON_CNF71XX)) 922215990Sjmallett { 923232812Sjmallett /* Requires reading the MIO_QLMX_CFG register to figure 924232812Sjmallett out the port type. */ 925232812Sjmallett int qlm = pcie_port; 926232812Sjmallett int status; 927232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 928232812Sjmallett qlm = 3 - (pcie_port * 2); 929232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CN61XX)) 930232812Sjmallett { 931232812Sjmallett cvmx_mio_qlmx_cfg_t qlm_cfg; 932232812Sjmallett qlm_cfg.u64 = cvmx_read_csr(CVMX_MIO_QLMX_CFG(1)); 933232812Sjmallett if (qlm_cfg.s.qlm_cfg == 1) 934232812Sjmallett qlm = 1; 935232812Sjmallett } 936232812Sjmallett /* PCIe is allowed only in QLM1, 1 PCIe port in x2 or 937232812Sjmallett 2 PCIe ports in x1 */ 938232812Sjmallett else if (OCTEON_IS_MODEL(OCTEON_CNF71XX)) 939232812Sjmallett qlm = 1; 940232812Sjmallett status = cvmx_qlm_get_status(qlm); 941232812Sjmallett if (status == 4 || status == 5) 942232812Sjmallett { 943232812Sjmallett cvmx_dprintf("PCIe: Port %d is SRIO, skipping.\n", pcie_port); 944232812Sjmallett return -1; 945232812Sjmallett } 946232812Sjmallett if (status == 1) 947232812Sjmallett { 948232812Sjmallett cvmx_dprintf("PCIe: Port %d is SGMII, skipping.\n", pcie_port); 949232812Sjmallett return -1; 950232812Sjmallett } 951232812Sjmallett if (status == 2) 952232812Sjmallett { 953232812Sjmallett cvmx_dprintf("PCIe: Port %d is XAUI, skipping.\n", pcie_port); 954232812Sjmallett return -1; 955232812Sjmallett } 956232812Sjmallett if (status == -1) 957232812Sjmallett { 958232812Sjmallett cvmx_dprintf("PCIe: Port %d is unknown, skipping.\n", pcie_port); 959232812Sjmallett return -1; 960232812Sjmallett } 961215990Sjmallett } 962215990Sjmallett 963232812Sjmallett#if 0 964232812Sjmallett /* This code is so that the PCIe analyzer is able to see 63XX traffic */ 965232812Sjmallett cvmx_dprintf("PCIE : init for pcie analyzer.\n"); 966232812Sjmallett cvmx_helper_qlm_jtag_init(); 967232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); 968232812Sjmallett cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); 969232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); 970232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); 971232812Sjmallett cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); 972232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); 973232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); 974232812Sjmallett cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); 975232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); 976232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 85); 977232812Sjmallett cvmx_helper_qlm_jtag_shift(pcie_port, 1, 1); 978232812Sjmallett cvmx_helper_qlm_jtag_shift_zeros(pcie_port, 300-86); 979232812Sjmallett cvmx_helper_qlm_jtag_update(pcie_port); 980232812Sjmallett#endif 981232812Sjmallett 982215990Sjmallett /* Make sure we aren't trying to setup a target mode interface in host mode */ 983215990Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); 984232812Sjmallett ep_mode = (OCTEON_IS_MODEL(OCTEON_CN61XX || OCTEON_IS_MODEL(OCTEON_CNF71XX)) ? (mio_rst_ctl.s.prtmode != 1) : (!mio_rst_ctl.s.host_mode)); 985232812Sjmallett if (ep_mode) 986215990Sjmallett { 987215990Sjmallett cvmx_dprintf("PCIe: Port %d in endpoint mode.\n", pcie_port); 988215990Sjmallett return -1; 989215990Sjmallett } 990215990Sjmallett 991215990Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ 992215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 993215990Sjmallett { 994215990Sjmallett if (pcie_port) 995215990Sjmallett { 996215990Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 997215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 998215990Sjmallett ciu_qlm.s.txbypass = 1; 999215990Sjmallett ciu_qlm.s.txdeemph = 5; 1000215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1001215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 1002215990Sjmallett } 1003215990Sjmallett else 1004215990Sjmallett { 1005215990Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 1006215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 1007215990Sjmallett ciu_qlm.s.txbypass = 1; 1008215990Sjmallett ciu_qlm.s.txdeemph = 5; 1009215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1010215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 1011215990Sjmallett } 1012215990Sjmallett } 1013215990Sjmallett /* Bring the PCIe out of reset */ 1014215990Sjmallett if (pcie_port) 1015215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 1016215990Sjmallett else 1017215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 1018215990Sjmallett /* After a chip reset the PCIe will also be in reset. If it isn't, 1019215990Sjmallett most likely someone is trying to init it again without a proper 1020215990Sjmallett PCIe reset */ 1021215990Sjmallett if (ciu_soft_prst.s.soft_prst == 0) 1022215990Sjmallett { 1023215990Sjmallett /* Reset the port */ 1024215990Sjmallett ciu_soft_prst.s.soft_prst = 1; 1025215990Sjmallett if (pcie_port) 1026215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 1027215990Sjmallett else 1028215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 1029215990Sjmallett /* Wait until pcie resets the ports. */ 1030215990Sjmallett cvmx_wait_usec(2000); 1031215990Sjmallett } 1032215990Sjmallett if (pcie_port) 1033215990Sjmallett { 1034215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 1035215990Sjmallett ciu_soft_prst.s.soft_prst = 0; 1036215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 1037215990Sjmallett } 1038215990Sjmallett else 1039215990Sjmallett { 1040215990Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 1041215990Sjmallett ciu_soft_prst.s.soft_prst = 0; 1042215990Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 1043215990Sjmallett } 1044215990Sjmallett 1045215990Sjmallett /* Wait for PCIe reset to complete */ 1046215990Sjmallett cvmx_wait_usec(1000); 1047215990Sjmallett 1048215990Sjmallett /* Check and make sure PCIe came out of reset. If it doesn't the board 1049215990Sjmallett probably hasn't wired the clocks up and the interface should be 1050215990Sjmallett skipped */ 1051232812Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_MIO_RST_CTLX(pcie_port), cvmx_mio_rst_ctlx_t, rst_done, ==, 1, 10000)) 1052215990Sjmallett { 1053215990Sjmallett cvmx_dprintf("PCIe: Port %d stuck in reset, skipping.\n", pcie_port); 1054215990Sjmallett return -1; 1055215990Sjmallett } 1056215990Sjmallett 1057215990Sjmallett /* Check BIST status */ 1058215990Sjmallett pemx_bist_status.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS(pcie_port)); 1059215990Sjmallett if (pemx_bist_status.u64) 1060215990Sjmallett cvmx_dprintf("PCIe: BIST FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status.u64)); 1061215990Sjmallett pemx_bist_status2.u64 = cvmx_read_csr(CVMX_PEMX_BIST_STATUS2(pcie_port)); 1062232812Sjmallett /* Errata PCIE-14766 may cause the lower 6 bits to be randomly set on CN63XXp1 */ 1063232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_X)) 1064232812Sjmallett pemx_bist_status2.u64 &= ~0x3full; 1065215990Sjmallett if (pemx_bist_status2.u64) 1066215990Sjmallett cvmx_dprintf("PCIe: BIST2 FAILED for port %d (0x%016llx)\n", pcie_port, CAST64(pemx_bist_status2.u64)); 1067215990Sjmallett 1068215990Sjmallett /* Initialize the config space CSRs */ 1069215990Sjmallett __cvmx_pcie_rc_initialize_config_space(pcie_port); 1070215990Sjmallett 1071215990Sjmallett /* Enable gen2 speed selection */ 1072215990Sjmallett pciercx_cfg515.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG515(pcie_port)); 1073215990Sjmallett pciercx_cfg515.s.dsc = 1; 1074215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG515(pcie_port), pciercx_cfg515.u32); 1075215990Sjmallett 1076215990Sjmallett /* Bring the link up */ 1077215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) 1078215990Sjmallett { 1079215990Sjmallett /* Some gen1 devices don't handle the gen 2 training correctly. Disable 1080215990Sjmallett gen2 and try again with only gen1 */ 1081215990Sjmallett cvmx_pciercx_cfg031_t pciercx_cfg031; 1082215990Sjmallett pciercx_cfg031.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG031(pcie_port)); 1083215990Sjmallett pciercx_cfg031.s.mls = 1; 1084232812Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIERCX_CFG031(pcie_port), pciercx_cfg031.u32); 1085215990Sjmallett if (__cvmx_pcie_rc_initialize_link_gen2(pcie_port)) 1086215990Sjmallett { 1087215990Sjmallett cvmx_dprintf("PCIe: Link timeout on port %d, probably the slot is empty\n", pcie_port); 1088215990Sjmallett return -1; 1089215990Sjmallett } 1090215990Sjmallett } 1091215990Sjmallett 1092215990Sjmallett /* Store merge control (SLI_MEM_ACCESS_CTL[TIMER,MAX_WORD]) */ 1093215990Sjmallett sli_mem_access_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL); 1094215990Sjmallett sli_mem_access_ctl.s.max_word = 0; /* Allow 16 words to combine */ 1095215990Sjmallett sli_mem_access_ctl.s.timer = 127; /* Wait up to 127 cycles for more data */ 1096215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_CTL, sli_mem_access_ctl.u64); 1097215990Sjmallett 1098215990Sjmallett /* Setup Mem access SubDIDs */ 1099215990Sjmallett mem_access_subid.u64 = 0; 1100215990Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1101215990Sjmallett mem_access_subid.s.nmerge = 0; /* Allow merging as it works on CN6XXX. */ 1102215990Sjmallett mem_access_subid.s.esr = 1; /* Endian-swap for Reads. */ 1103215990Sjmallett mem_access_subid.s.esw = 1; /* Endian-swap for Writes. */ 1104215990Sjmallett mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1105215990Sjmallett mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1106232812Sjmallett /* PCIe Adddress Bits <63:34>. */ 1107232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 1108232812Sjmallett mem_access_subid.cn68xx.ba = 0; 1109232812Sjmallett else 1110232812Sjmallett mem_access_subid.cn63xx.ba = 0; 1111215990Sjmallett 1112215990Sjmallett /* Setup mem access 12-15 for port 0, 16-19 for port 1, supplying 36 bits of address space */ 1113215990Sjmallett for (i=12 + pcie_port*4; i<16 + pcie_port*4; i++) 1114215990Sjmallett { 1115215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(i), mem_access_subid.u64); 1116232812Sjmallett /* Set each SUBID to extend the addressable range */ 1117232812Sjmallett __cvmx_increment_ba(&mem_access_subid); 1118215990Sjmallett } 1119215990Sjmallett 1120232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN61XX)) 1121215990Sjmallett { 1122232812Sjmallett /* Disable the peer to peer forwarding register. This must be setup 1123232812Sjmallett by the OS after it enumerates the bus and assigns addresses to the 1124232812Sjmallett PCIe busses */ 1125232812Sjmallett for (i=0; i<4; i++) 1126232812Sjmallett { 1127232812Sjmallett cvmx_write_csr(CVMX_PEMX_P2P_BARX_START(i, pcie_port), -1); 1128232812Sjmallett cvmx_write_csr(CVMX_PEMX_P2P_BARX_END(i, pcie_port), -1); 1129232812Sjmallett } 1130215990Sjmallett } 1131215990Sjmallett 1132215990Sjmallett /* Set Octeon's BAR0 to decode 0-16KB. It overlaps with Bar2 */ 1133215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR0_START(pcie_port), 0); 1134215990Sjmallett 1135215990Sjmallett /* Set Octeon's BAR2 to decode 0-2^41. Bar0 and Bar1 take precedence 1136215990Sjmallett where they overlap. It also overlaps with the device addresses, so 1137215990Sjmallett make sure the peer to peer forwarding is set right */ 1138215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR2_START(pcie_port), 0); 1139215990Sjmallett 1140215990Sjmallett /* Setup BAR2 attributes */ 1141215990Sjmallett /* Relaxed Ordering (NPEI_CTL_PORTn[PTLP_RO,CTLP_RO, WAIT_COM]) */ 1142215990Sjmallett /* � PTLP_RO,CTLP_RO should normally be set (except for debug). */ 1143215990Sjmallett /* � WAIT_COM=0 will likely work for all applications. */ 1144215990Sjmallett /* Load completion relaxed ordering (NPEI_CTL_PORTn[WAITL_COM]) */ 1145215990Sjmallett pemx_bar_ctl.u64 = cvmx_read_csr(CVMX_PEMX_BAR_CTL(pcie_port)); 1146215990Sjmallett pemx_bar_ctl.s.bar1_siz = 3; /* 256MB BAR1*/ 1147215990Sjmallett pemx_bar_ctl.s.bar2_enb = 1; 1148215990Sjmallett pemx_bar_ctl.s.bar2_esx = 1; 1149215990Sjmallett pemx_bar_ctl.s.bar2_cax = 0; 1150215990Sjmallett cvmx_write_csr(CVMX_PEMX_BAR_CTL(pcie_port), pemx_bar_ctl.u64); 1151215990Sjmallett sli_ctl_portx.u64 = cvmx_read_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port)); 1152215990Sjmallett sli_ctl_portx.s.ptlp_ro = 1; 1153215990Sjmallett sli_ctl_portx.s.ctlp_ro = 1; 1154215990Sjmallett sli_ctl_portx.s.wait_com = 0; 1155215990Sjmallett sli_ctl_portx.s.waitl_com = 0; 1156215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_CTL_PORTX(pcie_port), sli_ctl_portx.u64); 1157215990Sjmallett 1158215990Sjmallett /* BAR1 follows BAR2 */ 1159215990Sjmallett cvmx_write_csr(CVMX_PEMX_P2N_BAR1_START(pcie_port), CVMX_PCIE_BAR1_RC_BASE); 1160215990Sjmallett 1161215990Sjmallett bar1_index.u64 = 0; 1162215990Sjmallett bar1_index.s.addr_idx = (CVMX_PCIE_BAR1_PHYS_BASE >> 22); 1163215990Sjmallett bar1_index.s.ca = 1; /* Not Cached */ 1164215990Sjmallett bar1_index.s.end_swp = 1; /* Endian Swap mode */ 1165215990Sjmallett bar1_index.s.addr_v = 1; /* Valid entry */ 1166215990Sjmallett 1167215990Sjmallett for (i = 0; i < 16; i++) { 1168215990Sjmallett cvmx_write_csr(CVMX_PEMX_BAR1_INDEXX(i, pcie_port), bar1_index.u64); 1169215990Sjmallett /* 256MB / 16 >> 22 == 4 */ 1170215990Sjmallett bar1_index.s.addr_idx += (((1ull << 28) / 16ull) >> 22); 1171215990Sjmallett } 1172215990Sjmallett 1173215990Sjmallett /* Allow config retries for 250ms. Count is based off the 5Ghz SERDES 1174215990Sjmallett clock */ 1175215990Sjmallett pemx_ctl_status.u64 = cvmx_read_csr(CVMX_PEMX_CTL_STATUS(pcie_port)); 1176215990Sjmallett pemx_ctl_status.s.cfg_rtry = 250 * 5000000 / 0x10000; 1177215990Sjmallett cvmx_write_csr(CVMX_PEMX_CTL_STATUS(pcie_port), pemx_ctl_status.u64); 1178215990Sjmallett 1179215990Sjmallett /* Display the link status */ 1180215990Sjmallett pciercx_cfg032.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port)); 1181215990Sjmallett cvmx_dprintf("PCIe: Port %d link active, %d lanes, speed gen%d\n", pcie_port, pciercx_cfg032.s.nlw, pciercx_cfg032.s.ls); 1182215990Sjmallett 1183215990Sjmallett return 0; 1184215990Sjmallett} 1185215990Sjmallett 1186215990Sjmallett/** 1187215990Sjmallett * Initialize a PCIe port for use in host(RC) mode. It doesn't enumerate the bus. 1188215990Sjmallett * 1189215990Sjmallett * @param pcie_port PCIe port to initialize 1190215990Sjmallett * 1191215990Sjmallett * @return Zero on success 1192215990Sjmallett */ 1193215990Sjmallettint cvmx_pcie_rc_initialize(int pcie_port) 1194215990Sjmallett{ 1195215990Sjmallett int result; 1196215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1197215990Sjmallett result = __cvmx_pcie_rc_initialize_gen1(pcie_port); 1198215990Sjmallett else 1199215990Sjmallett result = __cvmx_pcie_rc_initialize_gen2(pcie_port); 1200232816Sjmallett#if (!defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL) 1201215990Sjmallett if (result == 0) 1202215990Sjmallett cvmx_error_enable_group(CVMX_ERROR_GROUP_PCI, pcie_port); 1203215990Sjmallett#endif 1204215990Sjmallett return result; 1205215990Sjmallett} 1206215990Sjmallett 1207215990Sjmallett 1208215990Sjmallett/** 1209210284Sjmallett * Shutdown a PCIe port and put it in reset 1210210284Sjmallett * 1211210284Sjmallett * @param pcie_port PCIe port to shutdown 1212210284Sjmallett * 1213210284Sjmallett * @return Zero on success 1214210284Sjmallett */ 1215210284Sjmallettint cvmx_pcie_rc_shutdown(int pcie_port) 1216210284Sjmallett{ 1217232816Sjmallett#if (!defined(CVMX_BUILD_FOR_LINUX_KERNEL) && !defined(CVMX_BUILD_FOR_FREEBSD_KERNEL)) || defined(CONFIG_CAVIUM_DECODE_RSL) 1218215990Sjmallett cvmx_error_disable_group(CVMX_ERROR_GROUP_PCI, pcie_port); 1219215990Sjmallett#endif 1220210284Sjmallett /* Wait for all pending operations to complete */ 1221215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1222215990Sjmallett { 1223215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PESCX_CPL_LUT_VALID(pcie_port), cvmx_pescx_cpl_lut_valid_t, tag, ==, 0, 2000)) 1224215990Sjmallett cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); 1225215990Sjmallett } 1226215990Sjmallett else 1227215990Sjmallett { 1228215990Sjmallett if (CVMX_WAIT_FOR_FIELD64(CVMX_PEMX_CPL_LUT_VALID(pcie_port), cvmx_pemx_cpl_lut_valid_t, tag, ==, 0, 2000)) 1229215990Sjmallett cvmx_dprintf("PCIe: Port %d shutdown timeout\n", pcie_port); 1230215990Sjmallett } 1231210284Sjmallett 1232210284Sjmallett /* Force reset */ 1233210284Sjmallett if (pcie_port) 1234210284Sjmallett { 1235210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 1236210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST1); 1237210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 1238210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST1, ciu_soft_prst.u64); 1239210284Sjmallett } 1240210284Sjmallett else 1241210284Sjmallett { 1242210284Sjmallett cvmx_ciu_soft_prst_t ciu_soft_prst; 1243210284Sjmallett ciu_soft_prst.u64 = cvmx_read_csr(CVMX_CIU_SOFT_PRST); 1244210284Sjmallett ciu_soft_prst.s.soft_prst = 1; 1245210284Sjmallett cvmx_write_csr(CVMX_CIU_SOFT_PRST, ciu_soft_prst.u64); 1246210284Sjmallett } 1247210284Sjmallett return 0; 1248210284Sjmallett} 1249210284Sjmallett 1250210284Sjmallett 1251210284Sjmallett/** 1252210284Sjmallett * @INTERNAL 1253210284Sjmallett * Build a PCIe config space request address for a device 1254210284Sjmallett * 1255210284Sjmallett * @param pcie_port PCIe port to access 1256210284Sjmallett * @param bus Sub bus 1257210284Sjmallett * @param dev Device ID 1258210284Sjmallett * @param fn Device sub function 1259210284Sjmallett * @param reg Register to access 1260210284Sjmallett * 1261210284Sjmallett * @return 64bit Octeon IO address 1262210284Sjmallett */ 1263210284Sjmallettstatic inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus, int dev, int fn, int reg) 1264210284Sjmallett{ 1265210284Sjmallett cvmx_pcie_address_t pcie_addr; 1266210284Sjmallett cvmx_pciercx_cfg006_t pciercx_cfg006; 1267210284Sjmallett 1268210284Sjmallett pciercx_cfg006.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port)); 1269210284Sjmallett if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0)) 1270210284Sjmallett return 0; 1271210284Sjmallett 1272210284Sjmallett pcie_addr.u64 = 0; 1273210284Sjmallett pcie_addr.config.upper = 2; 1274210284Sjmallett pcie_addr.config.io = 1; 1275210284Sjmallett pcie_addr.config.did = 3; 1276210284Sjmallett pcie_addr.config.subdid = 1; 1277210284Sjmallett pcie_addr.config.es = 1; 1278210284Sjmallett pcie_addr.config.port = pcie_port; 1279210284Sjmallett pcie_addr.config.ty = (bus > pciercx_cfg006.s.pbnum); 1280210284Sjmallett pcie_addr.config.bus = bus; 1281210284Sjmallett pcie_addr.config.dev = dev; 1282210284Sjmallett pcie_addr.config.func = fn; 1283210284Sjmallett pcie_addr.config.reg = reg; 1284210284Sjmallett return pcie_addr.u64; 1285210284Sjmallett} 1286210284Sjmallett 1287210284Sjmallett 1288210284Sjmallett/** 1289210284Sjmallett * Read 8bits from a Device's config space 1290210284Sjmallett * 1291210284Sjmallett * @param pcie_port PCIe port the device is on 1292210284Sjmallett * @param bus Sub bus 1293210284Sjmallett * @param dev Device ID 1294210284Sjmallett * @param fn Device sub function 1295210284Sjmallett * @param reg Register to access 1296210284Sjmallett * 1297210284Sjmallett * @return Result of the read 1298210284Sjmallett */ 1299210284Sjmallettuint8_t cvmx_pcie_config_read8(int pcie_port, int bus, int dev, int fn, int reg) 1300210284Sjmallett{ 1301210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1302210284Sjmallett if (address) 1303210284Sjmallett return cvmx_read64_uint8(address); 1304210284Sjmallett else 1305210284Sjmallett return 0xff; 1306210284Sjmallett} 1307210284Sjmallett 1308210284Sjmallett 1309210284Sjmallett/** 1310210284Sjmallett * Read 16bits from a Device's config space 1311210284Sjmallett * 1312210284Sjmallett * @param pcie_port PCIe port the device is on 1313210284Sjmallett * @param bus Sub bus 1314210284Sjmallett * @param dev Device ID 1315210284Sjmallett * @param fn Device sub function 1316210284Sjmallett * @param reg Register to access 1317210284Sjmallett * 1318210284Sjmallett * @return Result of the read 1319210284Sjmallett */ 1320210284Sjmallettuint16_t cvmx_pcie_config_read16(int pcie_port, int bus, int dev, int fn, int reg) 1321210284Sjmallett{ 1322210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1323210284Sjmallett if (address) 1324210284Sjmallett return cvmx_le16_to_cpu(cvmx_read64_uint16(address)); 1325210284Sjmallett else 1326210284Sjmallett return 0xffff; 1327210284Sjmallett} 1328210284Sjmallett 1329210284Sjmallett 1330210284Sjmallett/** 1331210284Sjmallett * Read 32bits from a Device's config space 1332210284Sjmallett * 1333210284Sjmallett * @param pcie_port PCIe port the device is on 1334210284Sjmallett * @param bus Sub bus 1335210284Sjmallett * @param dev Device ID 1336210284Sjmallett * @param fn Device sub function 1337210284Sjmallett * @param reg Register to access 1338210284Sjmallett * 1339210284Sjmallett * @return Result of the read 1340210284Sjmallett */ 1341210284Sjmallettuint32_t cvmx_pcie_config_read32(int pcie_port, int bus, int dev, int fn, int reg) 1342210284Sjmallett{ 1343250428Simp uint64_t address; 1344250428Simp 1345250428Simp address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1346210284Sjmallett if (address) 1347210284Sjmallett return cvmx_le32_to_cpu(cvmx_read64_uint32(address)); 1348210284Sjmallett else 1349210284Sjmallett return 0xffffffff; 1350210284Sjmallett} 1351210284Sjmallett 1352210284Sjmallett 1353210284Sjmallett/** 1354210284Sjmallett * Write 8bits to a Device's config space 1355210284Sjmallett * 1356210284Sjmallett * @param pcie_port PCIe port the device is on 1357210284Sjmallett * @param bus Sub bus 1358210284Sjmallett * @param dev Device ID 1359210284Sjmallett * @param fn Device sub function 1360210284Sjmallett * @param reg Register to access 1361210284Sjmallett * @param val Value to write 1362210284Sjmallett */ 1363210284Sjmallettvoid cvmx_pcie_config_write8(int pcie_port, int bus, int dev, int fn, int reg, uint8_t val) 1364210284Sjmallett{ 1365210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1366210284Sjmallett if (address) 1367210284Sjmallett cvmx_write64_uint8(address, val); 1368210284Sjmallett} 1369210284Sjmallett 1370210284Sjmallett 1371210284Sjmallett/** 1372210284Sjmallett * Write 16bits to a Device's config space 1373210284Sjmallett * 1374210284Sjmallett * @param pcie_port PCIe port the device is on 1375210284Sjmallett * @param bus Sub bus 1376210284Sjmallett * @param dev Device ID 1377210284Sjmallett * @param fn Device sub function 1378210284Sjmallett * @param reg Register to access 1379210284Sjmallett * @param val Value to write 1380210284Sjmallett */ 1381210284Sjmallettvoid cvmx_pcie_config_write16(int pcie_port, int bus, int dev, int fn, int reg, uint16_t val) 1382210284Sjmallett{ 1383210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1384210284Sjmallett if (address) 1385210284Sjmallett cvmx_write64_uint16(address, cvmx_cpu_to_le16(val)); 1386210284Sjmallett} 1387210284Sjmallett 1388210284Sjmallett 1389210284Sjmallett/** 1390210284Sjmallett * Write 32bits to a Device's config space 1391210284Sjmallett * 1392210284Sjmallett * @param pcie_port PCIe port the device is on 1393210284Sjmallett * @param bus Sub bus 1394210284Sjmallett * @param dev Device ID 1395210284Sjmallett * @param fn Device sub function 1396210284Sjmallett * @param reg Register to access 1397210284Sjmallett * @param val Value to write 1398210284Sjmallett */ 1399210284Sjmallettvoid cvmx_pcie_config_write32(int pcie_port, int bus, int dev, int fn, int reg, uint32_t val) 1400210284Sjmallett{ 1401210284Sjmallett uint64_t address = __cvmx_pcie_build_config_addr(pcie_port, bus, dev, fn, reg); 1402210284Sjmallett if (address) 1403210284Sjmallett cvmx_write64_uint32(address, cvmx_cpu_to_le32(val)); 1404210284Sjmallett} 1405210284Sjmallett 1406210284Sjmallett 1407210284Sjmallett/** 1408210284Sjmallett * Read a PCIe config space register indirectly. This is used for 1409210284Sjmallett * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. 1410210284Sjmallett * 1411210284Sjmallett * @param pcie_port PCIe port to read from 1412210284Sjmallett * @param cfg_offset Address to read 1413210284Sjmallett * 1414210284Sjmallett * @return Value read 1415210284Sjmallett */ 1416210284Sjmallettuint32_t cvmx_pcie_cfgx_read(int pcie_port, uint32_t cfg_offset) 1417210284Sjmallett{ 1418215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1419215990Sjmallett { 1420215990Sjmallett cvmx_pescx_cfg_rd_t pescx_cfg_rd; 1421215990Sjmallett pescx_cfg_rd.u64 = 0; 1422215990Sjmallett pescx_cfg_rd.s.addr = cfg_offset; 1423215990Sjmallett cvmx_write_csr(CVMX_PESCX_CFG_RD(pcie_port), pescx_cfg_rd.u64); 1424215990Sjmallett pescx_cfg_rd.u64 = cvmx_read_csr(CVMX_PESCX_CFG_RD(pcie_port)); 1425215990Sjmallett return pescx_cfg_rd.s.data; 1426215990Sjmallett } 1427215990Sjmallett else 1428215990Sjmallett { 1429215990Sjmallett cvmx_pemx_cfg_rd_t pemx_cfg_rd; 1430215990Sjmallett pemx_cfg_rd.u64 = 0; 1431215990Sjmallett pemx_cfg_rd.s.addr = cfg_offset; 1432215990Sjmallett cvmx_write_csr(CVMX_PEMX_CFG_RD(pcie_port), pemx_cfg_rd.u64); 1433215990Sjmallett pemx_cfg_rd.u64 = cvmx_read_csr(CVMX_PEMX_CFG_RD(pcie_port)); 1434215990Sjmallett return pemx_cfg_rd.s.data; 1435215990Sjmallett } 1436210284Sjmallett} 1437210284Sjmallett 1438210284Sjmallett 1439210284Sjmallett/** 1440210284Sjmallett * Write a PCIe config space register indirectly. This is used for 1441210284Sjmallett * registers of the form PCIEEP_CFG??? and PCIERC?_CFG???. 1442210284Sjmallett * 1443210284Sjmallett * @param pcie_port PCIe port to write to 1444210284Sjmallett * @param cfg_offset Address to write 1445210284Sjmallett * @param val Value to write 1446210284Sjmallett */ 1447210284Sjmallettvoid cvmx_pcie_cfgx_write(int pcie_port, uint32_t cfg_offset, uint32_t val) 1448210284Sjmallett{ 1449215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1450215990Sjmallett { 1451215990Sjmallett cvmx_pescx_cfg_wr_t pescx_cfg_wr; 1452215990Sjmallett pescx_cfg_wr.u64 = 0; 1453215990Sjmallett pescx_cfg_wr.s.addr = cfg_offset; 1454215990Sjmallett pescx_cfg_wr.s.data = val; 1455215990Sjmallett cvmx_write_csr(CVMX_PESCX_CFG_WR(pcie_port), pescx_cfg_wr.u64); 1456215990Sjmallett } 1457215990Sjmallett else 1458215990Sjmallett { 1459215990Sjmallett cvmx_pemx_cfg_wr_t pemx_cfg_wr; 1460215990Sjmallett pemx_cfg_wr.u64 = 0; 1461215990Sjmallett pemx_cfg_wr.s.addr = cfg_offset; 1462215990Sjmallett pemx_cfg_wr.s.data = val; 1463215990Sjmallett cvmx_write_csr(CVMX_PEMX_CFG_WR(pcie_port), pemx_cfg_wr.u64); 1464215990Sjmallett } 1465210284Sjmallett} 1466210284Sjmallett 1467210284Sjmallett 1468210284Sjmallett/** 1469210284Sjmallett * Initialize a PCIe port for use in target(EP) mode. 1470210284Sjmallett * 1471215990Sjmallett * @param pcie_port PCIe port to initialize 1472215990Sjmallett * 1473210284Sjmallett * @return Zero on success 1474210284Sjmallett */ 1475215990Sjmallettint cvmx_pcie_ep_initialize(int pcie_port) 1476210284Sjmallett{ 1477215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1478215990Sjmallett { 1479215990Sjmallett cvmx_npei_ctl_status_t npei_ctl_status; 1480215990Sjmallett npei_ctl_status.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS); 1481215990Sjmallett if (npei_ctl_status.s.host_mode) 1482215990Sjmallett return -1; 1483215990Sjmallett } 1484215990Sjmallett else 1485215990Sjmallett { 1486215990Sjmallett cvmx_mio_rst_ctlx_t mio_rst_ctl; 1487232812Sjmallett int ep_mode; 1488215990Sjmallett mio_rst_ctl.u64 = cvmx_read_csr(CVMX_MIO_RST_CTLX(pcie_port)); 1489232812Sjmallett ep_mode = (OCTEON_IS_MODEL(OCTEON_CN61XX) ? (mio_rst_ctl.s.prtmode != 0) : mio_rst_ctl.s.host_mode); 1490232812Sjmallett if (ep_mode) 1491215990Sjmallett return -1; 1492215990Sjmallett } 1493210284Sjmallett 1494215990Sjmallett /* CN63XX Pass 1.0 errata G-14395 requires the QLM De-emphasis be programmed */ 1495215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX_PASS1_0)) 1496215990Sjmallett { 1497215990Sjmallett if (pcie_port) 1498215990Sjmallett { 1499215990Sjmallett cvmx_ciu_qlm1_t ciu_qlm; 1500215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM1); 1501215990Sjmallett ciu_qlm.s.txbypass = 1; 1502215990Sjmallett ciu_qlm.s.txdeemph = 5; 1503215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1504215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM1, ciu_qlm.u64); 1505215990Sjmallett } 1506215990Sjmallett else 1507215990Sjmallett { 1508215990Sjmallett cvmx_ciu_qlm0_t ciu_qlm; 1509215990Sjmallett ciu_qlm.u64 = cvmx_read_csr(CVMX_CIU_QLM0); 1510215990Sjmallett ciu_qlm.s.txbypass = 1; 1511215990Sjmallett ciu_qlm.s.txdeemph = 5; 1512215990Sjmallett ciu_qlm.s.txmargin = 0x17; 1513215990Sjmallett cvmx_write_csr(CVMX_CIU_QLM0, ciu_qlm.u64); 1514215990Sjmallett } 1515215990Sjmallett } 1516210284Sjmallett 1517210284Sjmallett /* Enable bus master and memory */ 1518215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEPX_CFG001(pcie_port), 0x6); 1519210284Sjmallett 1520210284Sjmallett /* Max Payload Size (PCIE*_CFG030[MPS]) */ 1521210284Sjmallett /* Max Read Request Size (PCIE*_CFG030[MRRS]) */ 1522210284Sjmallett /* Relaxed-order, no-snoop enables (PCIE*_CFG030[RO_EN,NS_EN] */ 1523210284Sjmallett /* Error Message Enables (PCIE*_CFG030[CE_EN,NFE_EN,FE_EN,UR_EN]) */ 1524210284Sjmallett { 1525215990Sjmallett cvmx_pcieepx_cfg030_t pcieepx_cfg030; 1526215990Sjmallett pcieepx_cfg030.u32 = cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIEEPX_CFG030(pcie_port)); 1527215990Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN5XXX)) 1528215990Sjmallett { 1529215990Sjmallett pcieepx_cfg030.s.mps = MPS_CN5XXX; 1530215990Sjmallett pcieepx_cfg030.s.mrrs = MRRS_CN5XXX; 1531215990Sjmallett } 1532215990Sjmallett else 1533215990Sjmallett { 1534215990Sjmallett pcieepx_cfg030.s.mps = MPS_CN6XXX; 1535215990Sjmallett pcieepx_cfg030.s.mrrs = MRRS_CN6XXX; 1536215990Sjmallett } 1537215990Sjmallett pcieepx_cfg030.s.ro_en = 1; /* Enable relaxed ordering. */ 1538215990Sjmallett pcieepx_cfg030.s.ns_en = 1; /* Enable no snoop. */ 1539215990Sjmallett pcieepx_cfg030.s.ce_en = 1; /* Correctable error reporting enable. */ 1540215990Sjmallett pcieepx_cfg030.s.nfe_en = 1; /* Non-fatal error reporting enable. */ 1541215990Sjmallett pcieepx_cfg030.s.fe_en = 1; /* Fatal error reporting enable. */ 1542215990Sjmallett pcieepx_cfg030.s.ur_en = 1; /* Unsupported request reporting enable. */ 1543215990Sjmallett cvmx_pcie_cfgx_write(pcie_port, CVMX_PCIEEPX_CFG030(pcie_port), pcieepx_cfg030.u32); 1544210284Sjmallett } 1545210284Sjmallett 1546215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1547210284Sjmallett { 1548215990Sjmallett /* Max Payload Size (NPEI_CTL_STATUS2[MPS]) must match PCIE*_CFG030[MPS] */ 1549215990Sjmallett /* Max Read Request Size (NPEI_CTL_STATUS2[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 1550210284Sjmallett cvmx_npei_ctl_status2_t npei_ctl_status2; 1551210284Sjmallett npei_ctl_status2.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_CTL_STATUS2); 1552215990Sjmallett npei_ctl_status2.s.mps = MPS_CN5XXX; /* Max payload size = 128 bytes (Limit of most PCs) */ 1553215990Sjmallett npei_ctl_status2.s.mrrs = MRRS_CN5XXX; /* Max read request size = 128 bytes for best Octeon DMA performance */ 1554210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_CTL_STATUS2, npei_ctl_status2.u64); 1555210284Sjmallett } 1556215990Sjmallett else 1557215990Sjmallett { 1558215990Sjmallett /* Max Payload Size (DPI_SLI_PRTX_CFG[MPS]) must match PCIE*_CFG030[MPS] */ 1559215990Sjmallett /* Max Read Request Size (DPI_SLI_PRTX_CFG[MRRS]) must not exceed PCIE*_CFG030[MRRS] */ 1560215990Sjmallett cvmx_dpi_sli_prtx_cfg_t prt_cfg; 1561215990Sjmallett cvmx_sli_s2m_portx_ctl_t sli_s2m_portx_ctl; 1562215990Sjmallett prt_cfg.u64 = cvmx_read_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port)); 1563215990Sjmallett prt_cfg.s.mps = MPS_CN6XXX; 1564215990Sjmallett prt_cfg.s.mrrs = MRRS_CN6XXX; 1565232812Sjmallett /* Max outstanding load request. */ 1566232812Sjmallett prt_cfg.s.molr = 32; 1567215990Sjmallett cvmx_write_csr(CVMX_DPI_SLI_PRTX_CFG(pcie_port), prt_cfg.u64); 1568210284Sjmallett 1569215990Sjmallett sli_s2m_portx_ctl.u64 = cvmx_read_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port)); 1570215990Sjmallett sli_s2m_portx_ctl.s.mrrs = MRRS_CN6XXX; 1571215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_S2M_PORTX_CTL(pcie_port), sli_s2m_portx_ctl.u64); 1572215990Sjmallett } 1573215990Sjmallett 1574210284Sjmallett /* Setup Mem access SubDID 12 to access Host memory */ 1575215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1576210284Sjmallett { 1577210284Sjmallett cvmx_npei_mem_access_subidx_t mem_access_subid; 1578210284Sjmallett mem_access_subid.u64 = 0; 1579210284Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1580215990Sjmallett mem_access_subid.s.nmerge = 1; /* Merging is not allowed in this window. */ 1581210284Sjmallett mem_access_subid.s.esr = 0; /* Endian-swap for Reads. */ 1582210284Sjmallett mem_access_subid.s.esw = 0; /* Endian-swap for Writes. */ 1583210284Sjmallett mem_access_subid.s.nsr = 0; /* Enable Snooping for Reads. Octeon doesn't care, but devices might want this more conservative setting */ 1584210284Sjmallett mem_access_subid.s.nsw = 0; /* Enable Snoop for Writes. */ 1585210284Sjmallett mem_access_subid.s.ror = 0; /* Disable Relaxed Ordering for Reads. */ 1586210284Sjmallett mem_access_subid.s.row = 0; /* Disable Relaxed Ordering for Writes. */ 1587210284Sjmallett mem_access_subid.s.ba = 0; /* PCIe Adddress Bits <63:34>. */ 1588210284Sjmallett cvmx_write_csr(CVMX_PEXP_NPEI_MEM_ACCESS_SUBIDX(12), mem_access_subid.u64); 1589210284Sjmallett } 1590215990Sjmallett else 1591215990Sjmallett { 1592215990Sjmallett cvmx_sli_mem_access_subidx_t mem_access_subid; 1593215990Sjmallett mem_access_subid.u64 = 0; 1594215990Sjmallett mem_access_subid.s.port = pcie_port; /* Port the request is sent to. */ 1595215990Sjmallett mem_access_subid.s.nmerge = 0; /* Merging is allowed in this window. */ 1596215990Sjmallett mem_access_subid.s.esr = 0; /* Endian-swap for Reads. */ 1597215990Sjmallett mem_access_subid.s.esw = 0; /* Endian-swap for Writes. */ 1598215990Sjmallett mem_access_subid.s.wtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1599215990Sjmallett mem_access_subid.s.rtype = 0; /* "No snoop" and "Relaxed ordering" are not set */ 1600232812Sjmallett /* PCIe Adddress Bits <63:34>. */ 1601232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN68XX)) 1602232812Sjmallett mem_access_subid.cn68xx.ba = 0; 1603232812Sjmallett else 1604232812Sjmallett mem_access_subid.cn63xx.ba = 0; 1605215990Sjmallett cvmx_write_csr(CVMX_PEXP_SLI_MEM_ACCESS_SUBIDX(12 + pcie_port*4), mem_access_subid.u64); 1606215990Sjmallett } 1607210284Sjmallett return 0; 1608210284Sjmallett} 1609210284Sjmallett 1610210284Sjmallett 1611210284Sjmallett/** 1612210284Sjmallett * Wait for posted PCIe read/writes to reach the other side of 1613210284Sjmallett * the internal PCIe switch. This will insure that core 1614210284Sjmallett * read/writes are posted before anything after this function 1615210284Sjmallett * is called. This may be necessary when writing to memory that 1616210284Sjmallett * will later be read using the DMA/PKT engines. 1617210284Sjmallett * 1618210284Sjmallett * @param pcie_port PCIe port to wait for 1619210284Sjmallett */ 1620210284Sjmallettvoid cvmx_pcie_wait_for_pending(int pcie_port) 1621210284Sjmallett{ 1622215990Sjmallett if (octeon_has_feature(OCTEON_FEATURE_NPEI)) 1623215990Sjmallett { 1624215990Sjmallett cvmx_npei_data_out_cnt_t npei_data_out_cnt; 1625215990Sjmallett int a; 1626215990Sjmallett int b; 1627215990Sjmallett int c; 1628210284Sjmallett 1629215990Sjmallett /* See section 9.8, PCIe Core-initiated Requests, in the manual for a 1630215990Sjmallett description of how this code works */ 1631215990Sjmallett npei_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DATA_OUT_CNT); 1632215990Sjmallett if (pcie_port) 1633215990Sjmallett { 1634215990Sjmallett if (!npei_data_out_cnt.s.p1_fcnt) 1635215990Sjmallett return; 1636215990Sjmallett a = npei_data_out_cnt.s.p1_ucnt; 1637215990Sjmallett b = (a + npei_data_out_cnt.s.p1_fcnt-1) & 0xffff; 1638215990Sjmallett } 1639215990Sjmallett else 1640215990Sjmallett { 1641215990Sjmallett if (!npei_data_out_cnt.s.p0_fcnt) 1642215990Sjmallett return; 1643215990Sjmallett a = npei_data_out_cnt.s.p0_ucnt; 1644215990Sjmallett b = (a + npei_data_out_cnt.s.p0_fcnt-1) & 0xffff; 1645215990Sjmallett } 1646215990Sjmallett 1647215990Sjmallett while (1) 1648215990Sjmallett { 1649215990Sjmallett npei_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DATA_OUT_CNT); 1650215990Sjmallett c = (pcie_port) ? npei_data_out_cnt.s.p1_ucnt : npei_data_out_cnt.s.p0_ucnt; 1651215990Sjmallett if (a<=b) 1652215990Sjmallett { 1653215990Sjmallett if ((c<a) || (c>b)) 1654215990Sjmallett return; 1655215990Sjmallett } 1656215990Sjmallett else 1657215990Sjmallett { 1658215990Sjmallett if ((c>b) && (c<a)) 1659215990Sjmallett return; 1660215990Sjmallett } 1661215990Sjmallett } 1662210284Sjmallett } 1663210284Sjmallett else 1664210284Sjmallett { 1665215990Sjmallett cvmx_sli_data_out_cnt_t sli_data_out_cnt; 1666215990Sjmallett int a; 1667215990Sjmallett int b; 1668215990Sjmallett int c; 1669210284Sjmallett 1670215990Sjmallett sli_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_SLI_DATA_OUT_CNT); 1671215990Sjmallett if (pcie_port) 1672210284Sjmallett { 1673215990Sjmallett if (!sli_data_out_cnt.s.p1_fcnt) 1674210284Sjmallett return; 1675215990Sjmallett a = sli_data_out_cnt.s.p1_ucnt; 1676215990Sjmallett b = (a + sli_data_out_cnt.s.p1_fcnt-1) & 0xffff; 1677210284Sjmallett } 1678210284Sjmallett else 1679210284Sjmallett { 1680215990Sjmallett if (!sli_data_out_cnt.s.p0_fcnt) 1681210284Sjmallett return; 1682215990Sjmallett a = sli_data_out_cnt.s.p0_ucnt; 1683215990Sjmallett b = (a + sli_data_out_cnt.s.p0_fcnt-1) & 0xffff; 1684210284Sjmallett } 1685215990Sjmallett 1686215990Sjmallett while (1) 1687215990Sjmallett { 1688215990Sjmallett sli_data_out_cnt.u64 = cvmx_read_csr(CVMX_PEXP_SLI_DATA_OUT_CNT); 1689215990Sjmallett c = (pcie_port) ? sli_data_out_cnt.s.p1_ucnt : sli_data_out_cnt.s.p0_ucnt; 1690215990Sjmallett if (a<=b) 1691215990Sjmallett { 1692215990Sjmallett if ((c<a) || (c>b)) 1693215990Sjmallett return; 1694215990Sjmallett } 1695215990Sjmallett else 1696215990Sjmallett { 1697215990Sjmallett if ((c>b) && (c<a)) 1698215990Sjmallett return; 1699215990Sjmallett } 1700215990Sjmallett } 1701210284Sjmallett } 1702210284Sjmallett} 1703