193a686eeSJean-Christophe PLAGNIOL-VILLARD /* 2505f3e6fSMinghuan Lian * Copyright 2007-2012 Freescale Semiconductor, Inc. 393a686eeSJean-Christophe PLAGNIOL-VILLARD * 41a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 593a686eeSJean-Christophe PLAGNIOL-VILLARD */ 693a686eeSJean-Christophe PLAGNIOL-VILLARD 793a686eeSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 8a4aafcc9SKumar Gala #include <malloc.h> 9a4aafcc9SKumar Gala #include <asm/fsl_serdes.h> 1093a686eeSJean-Christophe PLAGNIOL-VILLARD 11b9a1fa97SKumar Gala DECLARE_GLOBAL_DATA_PTR; 12b9a1fa97SKumar Gala 1393a686eeSJean-Christophe PLAGNIOL-VILLARD /* 1493a686eeSJean-Christophe PLAGNIOL-VILLARD * PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's 1593a686eeSJean-Christophe PLAGNIOL-VILLARD * 1693a686eeSJean-Christophe PLAGNIOL-VILLARD * Initialize controller and call the common driver/pci pci_hose_scan to 1793a686eeSJean-Christophe PLAGNIOL-VILLARD * scan for bridges and devices. 1893a686eeSJean-Christophe PLAGNIOL-VILLARD * 1993a686eeSJean-Christophe PLAGNIOL-VILLARD * Hose fields which need to be pre-initialized by board specific code: 2093a686eeSJean-Christophe PLAGNIOL-VILLARD * regions[] 2193a686eeSJean-Christophe PLAGNIOL-VILLARD * first_busno 2293a686eeSJean-Christophe PLAGNIOL-VILLARD * 2393a686eeSJean-Christophe PLAGNIOL-VILLARD * Fields updated: 2493a686eeSJean-Christophe PLAGNIOL-VILLARD * last_busno 2593a686eeSJean-Christophe PLAGNIOL-VILLARD */ 2693a686eeSJean-Christophe PLAGNIOL-VILLARD 2793a686eeSJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 28ad19e7a5SKumar Gala #include <asm/io.h> 29c8514622SKumar Gala #include <asm/fsl_pci.h> 3093a686eeSJean-Christophe PLAGNIOL-VILLARD 31b9a1fa97SKumar Gala #ifndef CONFIG_SYS_PCI_MEMORY_BUS 32b9a1fa97SKumar Gala #define CONFIG_SYS_PCI_MEMORY_BUS 0 33b9a1fa97SKumar Gala #endif 34b9a1fa97SKumar Gala 35b9a1fa97SKumar Gala #ifndef CONFIG_SYS_PCI_MEMORY_PHYS 36b9a1fa97SKumar Gala #define CONFIG_SYS_PCI_MEMORY_PHYS 0 37b9a1fa97SKumar Gala #endif 38b9a1fa97SKumar Gala 39b9a1fa97SKumar Gala #if defined(CONFIG_SYS_PCI_64BIT) && !defined(CONFIG_SYS_PCI64_MEMORY_BUS) 40b9a1fa97SKumar Gala #define CONFIG_SYS_PCI64_MEMORY_BUS (64ull*1024*1024*1024) 41b9a1fa97SKumar Gala #endif 42b9a1fa97SKumar Gala 43ad19e7a5SKumar Gala /* Setup one inbound ATMU window. 44ad19e7a5SKumar Gala * 45ad19e7a5SKumar Gala * We let the caller decide what the window size should be 46ad19e7a5SKumar Gala */ 47ad19e7a5SKumar Gala static void set_inbound_window(volatile pit_t *pi, 48ad19e7a5SKumar Gala struct pci_region *r, 49ad19e7a5SKumar Gala u64 size) 50b9a1fa97SKumar Gala { 51ad19e7a5SKumar Gala u32 sz = (__ilog2_u64(size) - 1); 52f1a96ec1SChunhe Lan #ifdef CONFIG_SYS_FSL_ERRATUM_A005434 53f1a96ec1SChunhe Lan u32 flag = 0; 54f1a96ec1SChunhe Lan #else 55f1a96ec1SChunhe Lan u32 flag = PIWAR_LOCAL; 56f1a96ec1SChunhe Lan #endif 57f1a96ec1SChunhe Lan 58f1a96ec1SChunhe Lan flag |= PIWAR_EN | PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; 59ad19e7a5SKumar Gala 60ad19e7a5SKumar Gala out_be32(&pi->pitar, r->phys_start >> 12); 61ad19e7a5SKumar Gala out_be32(&pi->piwbar, r->bus_start >> 12); 62ad19e7a5SKumar Gala #ifdef CONFIG_SYS_PCI_64BIT 63ad19e7a5SKumar Gala out_be32(&pi->piwbear, r->bus_start >> 44); 64ad19e7a5SKumar Gala #else 65ad19e7a5SKumar Gala out_be32(&pi->piwbear, 0); 66ad19e7a5SKumar Gala #endif 67ad19e7a5SKumar Gala if (r->flags & PCI_REGION_PREFETCH) 68ad19e7a5SKumar Gala flag |= PIWAR_PF; 69ad19e7a5SKumar Gala out_be32(&pi->piwar, flag | sz); 70ad19e7a5SKumar Gala } 71ad19e7a5SKumar Gala 72ee53650dSKumar Gala int fsl_setup_hose(struct pci_controller *hose, unsigned long addr) 73ee53650dSKumar Gala { 74ee53650dSKumar Gala volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) addr; 75ee53650dSKumar Gala 7696d61603SJohn Schmoller /* Reset hose to make sure its in a clean state */ 7796d61603SJohn Schmoller memset(hose, 0, sizeof(struct pci_controller)); 7896d61603SJohn Schmoller 79ee53650dSKumar Gala pci_setup_indirect(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data); 80ee53650dSKumar Gala 81ee53650dSKumar Gala return fsl_is_pci_agent(hose); 82ee53650dSKumar Gala } 83ee53650dSKumar Gala 84ad19e7a5SKumar Gala static int fsl_pci_setup_inbound_windows(struct pci_controller *hose, 85ad19e7a5SKumar Gala u64 out_lo, u8 pcie_cap, 86ad19e7a5SKumar Gala volatile pit_t *pi) 87ad19e7a5SKumar Gala { 88ad19e7a5SKumar Gala struct pci_region *r = hose->regions + hose->region_count; 89ad19e7a5SKumar Gala u64 sz = min((u64)gd->ram_size, (1ull << 32)); 90b9a1fa97SKumar Gala 91b9a1fa97SKumar Gala phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS; 92b9a1fa97SKumar Gala pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS; 93ad19e7a5SKumar Gala pci_size_t pci_sz; 94b9a1fa97SKumar Gala 95ad19e7a5SKumar Gala /* we have no space available for inbound memory mapping */ 96ad19e7a5SKumar Gala if (bus_start > out_lo) { 97ad19e7a5SKumar Gala printf ("no space for inbound mapping of memory\n"); 98ad19e7a5SKumar Gala return 0; 99ad19e7a5SKumar Gala } 100ad19e7a5SKumar Gala 101ad19e7a5SKumar Gala /* limit size */ 102ad19e7a5SKumar Gala if ((bus_start + sz) > out_lo) { 103ad19e7a5SKumar Gala sz = out_lo - bus_start; 104ad19e7a5SKumar Gala debug ("limiting size to %llx\n", sz); 105ad19e7a5SKumar Gala } 106ad19e7a5SKumar Gala 107ad19e7a5SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 108ad19e7a5SKumar Gala /* 109ad19e7a5SKumar Gala * we can overlap inbound/outbound windows on PCI-E since RX & TX 110ad19e7a5SKumar Gala * links a separate 111ad19e7a5SKumar Gala */ 112ad19e7a5SKumar Gala if ((pcie_cap == PCI_CAP_ID_EXP) && (pci_sz < sz)) { 113b9a1fa97SKumar Gala debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n", 114ad19e7a5SKumar Gala (u64)bus_start, (u64)phys_start, (u64)sz); 115ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, sz, 116ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 117b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 118b9a1fa97SKumar Gala 119ad19e7a5SKumar Gala /* if we aren't an exact power of two match, pci_sz is smaller 120ad19e7a5SKumar Gala * round it up to the next power of two. We report the actual 121ad19e7a5SKumar Gala * size to pci region tracking. 122ad19e7a5SKumar Gala */ 123ad19e7a5SKumar Gala if (pci_sz != sz) 124ad19e7a5SKumar Gala sz = 2ull << __ilog2_u64(sz); 125ad19e7a5SKumar Gala 126ad19e7a5SKumar Gala set_inbound_window(pi--, r++, sz); 127ad19e7a5SKumar Gala sz = 0; /* make sure we dont set the R2 window */ 128ad19e7a5SKumar Gala } else { 129ad19e7a5SKumar Gala debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n", 130ad19e7a5SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 131ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 132ad19e7a5SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 133ad19e7a5SKumar Gala PCI_REGION_PREFETCH); 134ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 135ad19e7a5SKumar Gala 136b9a1fa97SKumar Gala sz -= pci_sz; 137b9a1fa97SKumar Gala bus_start += pci_sz; 138b9a1fa97SKumar Gala phys_start += pci_sz; 139b9a1fa97SKumar Gala 140b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 141b9a1fa97SKumar Gala if (sz) { 142b9a1fa97SKumar Gala debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n", 143b9a1fa97SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 144ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 145ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 146b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 147ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 148b9a1fa97SKumar Gala sz -= pci_sz; 149b9a1fa97SKumar Gala bus_start += pci_sz; 150b9a1fa97SKumar Gala phys_start += pci_sz; 151b9a1fa97SKumar Gala } 152ad19e7a5SKumar Gala } 153b9a1fa97SKumar Gala 154b9a1fa97SKumar Gala #if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT) 155cd425162SBecky Bruce /* 156cd425162SBecky Bruce * On 64-bit capable systems, set up a mapping for all of DRAM 157cd425162SBecky Bruce * in high pci address space. 158cd425162SBecky Bruce */ 159b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(gd->ram_size); 160b9a1fa97SKumar Gala /* round up to the next largest power of two */ 161b9a1fa97SKumar Gala if (gd->ram_size > pci_sz) 162cd425162SBecky Bruce pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1); 163b9a1fa97SKumar Gala debug ("R64 bus_start: %llx phys_start: %llx size: %llx\n", 164cd425162SBecky Bruce (u64)CONFIG_SYS_PCI64_MEMORY_BUS, 165b9a1fa97SKumar Gala (u64)CONFIG_SYS_PCI_MEMORY_PHYS, 166b9a1fa97SKumar Gala (u64)pci_sz); 167ad19e7a5SKumar Gala pci_set_region(r, 168cd425162SBecky Bruce CONFIG_SYS_PCI64_MEMORY_BUS, 169b9a1fa97SKumar Gala CONFIG_SYS_PCI_MEMORY_PHYS, 170b9a1fa97SKumar Gala pci_sz, 171ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 172b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 173ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 174b9a1fa97SKumar Gala #else 175b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 176b9a1fa97SKumar Gala if (sz) { 177b9a1fa97SKumar Gala debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n", 178b9a1fa97SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 179ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 180ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 181b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 182b9a1fa97SKumar Gala sz -= pci_sz; 183b9a1fa97SKumar Gala bus_start += pci_sz; 184b9a1fa97SKumar Gala phys_start += pci_sz; 185ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 186b9a1fa97SKumar Gala } 187b9a1fa97SKumar Gala #endif 188b9a1fa97SKumar Gala 1894c253fdbSKumar Gala #ifdef CONFIG_PHYS_64BIT 190b9a1fa97SKumar Gala if (sz && (((u64)gd->ram_size) < (1ull << 32))) 191b9a1fa97SKumar Gala printf("Was not able to map all of memory via " 192b9a1fa97SKumar Gala "inbound windows -- %lld remaining\n", sz); 1934c253fdbSKumar Gala #endif 194b9a1fa97SKumar Gala 195ad19e7a5SKumar Gala hose->region_count = r - hose->regions; 196ad19e7a5SKumar Gala 197ad19e7a5SKumar Gala return 1; 198b9a1fa97SKumar Gala } 199b9a1fa97SKumar Gala 200c8b28152SLiu Gang #ifdef CONFIG_SRIO_PCIE_BOOT_MASTER 201b5f7c873SLiu Gang static void fsl_pcie_boot_master(pit_t *pi) 202b5f7c873SLiu Gang { 203b5f7c873SLiu Gang /* configure inbound window for slave's u-boot image */ 204b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's image; " 205b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 206b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 207b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, 208b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 209b5f7c873SLiu Gang struct pci_region r_inbound; 210b5f7c873SLiu Gang u32 sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE) 211b5f7c873SLiu Gang - 1; 212b5f7c873SLiu Gang pci_set_region(&r_inbound, 213b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, 214b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 215b5f7c873SLiu Gang sz_inbound, 216b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 217b5f7c873SLiu Gang 218b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 219b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 220b5f7c873SLiu Gang 221b5f7c873SLiu Gang /* configure inbound window for slave's u-boot image */ 222b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's image; " 223b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 224b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 225b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, 226b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 227b5f7c873SLiu Gang pci_set_region(&r_inbound, 228b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, 229b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 230b5f7c873SLiu Gang sz_inbound, 231b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 232b5f7c873SLiu Gang 233b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 234b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 235b5f7c873SLiu Gang 236b5f7c873SLiu Gang /* configure inbound window for slave's ucode and ENV */ 237b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's " 238b5f7c873SLiu Gang "ucode and ENV; " 239b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 240b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, 241b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, 242b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); 243b5f7c873SLiu Gang sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE) 244b5f7c873SLiu Gang - 1; 245b5f7c873SLiu Gang pci_set_region(&r_inbound, 246b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, 247b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, 248b5f7c873SLiu Gang sz_inbound, 249b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 250b5f7c873SLiu Gang 251b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 252b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); 253b5f7c873SLiu Gang } 254b5f7c873SLiu Gang 255b5f7c873SLiu Gang static void fsl_pcie_boot_master_release_slave(int port) 256b5f7c873SLiu Gang { 257b5f7c873SLiu Gang unsigned long release_addr; 258b5f7c873SLiu Gang 259b5f7c873SLiu Gang /* now release slave's core 0 */ 260b5f7c873SLiu Gang switch (port) { 261b5f7c873SLiu Gang case 1: 262b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE1_MEM_VIRT 263b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 264b5f7c873SLiu Gang break; 265a1e4318cSYork Sun #ifdef CONFIG_SYS_PCIE2_MEM_VIRT 266b5f7c873SLiu Gang case 2: 267b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE2_MEM_VIRT 268b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 269b5f7c873SLiu Gang break; 270a1e4318cSYork Sun #endif 271a1e4318cSYork Sun #ifdef CONFIG_SYS_PCIE3_MEM_VIRT 272b5f7c873SLiu Gang case 3: 273b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE3_MEM_VIRT 274b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 275b5f7c873SLiu Gang break; 276a1e4318cSYork Sun #endif 277b5f7c873SLiu Gang default: 278b5f7c873SLiu Gang release_addr = 0; 279b5f7c873SLiu Gang break; 280b5f7c873SLiu Gang } 281b5f7c873SLiu Gang if (release_addr != 0) { 282b5f7c873SLiu Gang out_be32((void *)release_addr, 283b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); 284b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 285b5f7c873SLiu Gang "Release slave successfully! Now the slave should start up!\n"); 286b5f7c873SLiu Gang } else { 287b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 288b5f7c873SLiu Gang "Release slave failed!\n"); 289b5f7c873SLiu Gang } 290b5f7c873SLiu Gang } 291b5f7c873SLiu Gang #endif 292b5f7c873SLiu Gang 293213ac73eSPeter Tyser void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info) 29493a686eeSJean-Christophe PLAGNIOL-VILLARD { 295213ac73eSPeter Tyser u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr; 296213ac73eSPeter Tyser u32 cfg_data = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_data; 29793a686eeSJean-Christophe PLAGNIOL-VILLARD u16 temp16; 29893a686eeSJean-Christophe PLAGNIOL-VILLARD u32 temp32; 299b6ccd2c9SPrabhakar Kushwaha u32 block_rev; 3008295b944SKumar Gala int enabled, r, inbound = 0; 30193a686eeSJean-Christophe PLAGNIOL-VILLARD u16 ltssm; 3028295b944SKumar Gala u8 temp8, pcie_cap; 303287df01eSZhao Qiang int pcie_cap_pos; 304287df01eSZhao Qiang int pci_dcr; 305287df01eSZhao Qiang int pci_dsr; 306287df01eSZhao Qiang int pci_lsr; 307287df01eSZhao Qiang 308287df01eSZhao Qiang #if defined(CONFIG_FSL_PCIE_DISABLE_ASPM) 309287df01eSZhao Qiang int pci_lcr; 310287df01eSZhao Qiang #endif 311287df01eSZhao Qiang 312fb3143b3SKumar Gala volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr; 313cb151aa2SKumar Gala struct pci_region *reg = hose->regions + hose->region_count; 3148295b944SKumar Gala pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 31593a686eeSJean-Christophe PLAGNIOL-VILLARD 31693a686eeSJean-Christophe PLAGNIOL-VILLARD /* Initialize ATMU registers based on hose regions and flags */ 31793a686eeSJean-Christophe PLAGNIOL-VILLARD volatile pot_t *po = &pci->pot[1]; /* skip 0 */ 318b6ccd2c9SPrabhakar Kushwaha volatile pit_t *pi; 319ad19e7a5SKumar Gala 320ad19e7a5SKumar Gala u64 out_hi = 0, out_lo = -1ULL; 321ad19e7a5SKumar Gala u32 pcicsrbar, pcicsrbar_sz; 32293a686eeSJean-Christophe PLAGNIOL-VILLARD 323fb3143b3SKumar Gala pci_setup_indirect(hose, cfg_addr, cfg_data); 324fb3143b3SKumar Gala 325b6ccd2c9SPrabhakar Kushwaha block_rev = in_be32(&pci->block_rev1); 326b6ccd2c9SPrabhakar Kushwaha if (PEX_IP_BLK_REV_2_2 <= block_rev) { 327b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[2]; /* 0xDC0 */ 328b6ccd2c9SPrabhakar Kushwaha } else { 329b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[3]; /* 0xDE0 */ 330b6ccd2c9SPrabhakar Kushwaha } 331b6ccd2c9SPrabhakar Kushwaha 332ad19e7a5SKumar Gala /* Handle setup of outbound windows first */ 33393a686eeSJean-Christophe PLAGNIOL-VILLARD for (r = 0; r < hose->region_count; r++) { 334ad19e7a5SKumar Gala unsigned long flags = hose->regions[r].flags; 335612ea010SKumar Gala u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1); 336ad19e7a5SKumar Gala 337ad19e7a5SKumar Gala flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE; 338ad19e7a5SKumar Gala if (flags != PCI_REGION_SYS_MEMORY) { 339ad19e7a5SKumar Gala u64 start = hose->regions[r].bus_start; 340ad19e7a5SKumar Gala u64 end = start + hose->regions[r].size; 341ad19e7a5SKumar Gala 342ad19e7a5SKumar Gala out_be32(&po->powbar, hose->regions[r].phys_start >> 12); 343ad19e7a5SKumar Gala out_be32(&po->potar, start >> 12); 344612ea010SKumar Gala #ifdef CONFIG_SYS_PCI_64BIT 345ad19e7a5SKumar Gala out_be32(&po->potear, start >> 44); 346612ea010SKumar Gala #else 347ad19e7a5SKumar Gala out_be32(&po->potear, 0); 348612ea010SKumar Gala #endif 349ad19e7a5SKumar Gala if (hose->regions[r].flags & PCI_REGION_IO) { 350ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 351ad19e7a5SKumar Gala POWAR_IO_READ | POWAR_IO_WRITE); 352ad19e7a5SKumar Gala } else { 353ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 354ad19e7a5SKumar Gala POWAR_MEM_READ | POWAR_MEM_WRITE); 355ad19e7a5SKumar Gala out_lo = min(start, out_lo); 356ad19e7a5SKumar Gala out_hi = max(end, out_hi); 357ad19e7a5SKumar Gala } 35893a686eeSJean-Christophe PLAGNIOL-VILLARD po++; 35993a686eeSJean-Christophe PLAGNIOL-VILLARD } 36093a686eeSJean-Christophe PLAGNIOL-VILLARD } 361ad19e7a5SKumar Gala debug("Outbound memory range: %llx:%llx\n", out_lo, out_hi); 362ad19e7a5SKumar Gala 363ad19e7a5SKumar Gala /* setup PCSRBAR/PEXCSRBAR */ 364ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff); 365ad19e7a5SKumar Gala pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pcicsrbar_sz); 366ad19e7a5SKumar Gala pcicsrbar_sz = ~pcicsrbar_sz + 1; 367ad19e7a5SKumar Gala 368ad19e7a5SKumar Gala if (out_hi < (0x100000000ull - pcicsrbar_sz) || 369ad19e7a5SKumar Gala (out_lo > 0x100000000ull)) 370ad19e7a5SKumar Gala pcicsrbar = 0x100000000ull - pcicsrbar_sz; 371ad19e7a5SKumar Gala else 372ad19e7a5SKumar Gala pcicsrbar = (out_lo - pcicsrbar_sz) & -pcicsrbar_sz; 373ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, pcicsrbar); 374ad19e7a5SKumar Gala 375ad19e7a5SKumar Gala out_lo = min(out_lo, (u64)pcicsrbar); 376ad19e7a5SKumar Gala 377ad19e7a5SKumar Gala debug("PCICSRBAR @ 0x%x\n", pcicsrbar); 378ad19e7a5SKumar Gala 379ad19e7a5SKumar Gala pci_set_region(reg++, pcicsrbar, CONFIG_SYS_CCSRBAR_PHYS, 380ad19e7a5SKumar Gala pcicsrbar_sz, PCI_REGION_SYS_MEMORY); 381ad19e7a5SKumar Gala hose->region_count++; 38293a686eeSJean-Christophe PLAGNIOL-VILLARD 3838295b944SKumar Gala /* see if we are a PCIe or PCI controller */ 384287df01eSZhao Qiang pcie_cap_pos = pci_hose_find_capability(hose, dev, PCI_CAP_ID_EXP); 385287df01eSZhao Qiang pci_dcr = pcie_cap_pos + 0x08; 386287df01eSZhao Qiang pci_dsr = pcie_cap_pos + 0x0a; 387287df01eSZhao Qiang pci_lsr = pcie_cap_pos + 0x12; 388287df01eSZhao Qiang 389287df01eSZhao Qiang pci_hose_read_config_byte(hose, dev, pcie_cap_pos, &pcie_cap); 3908295b944SKumar Gala 391c8b28152SLiu Gang #ifdef CONFIG_SRIO_PCIE_BOOT_MASTER 392b5f7c873SLiu Gang /* boot from PCIE --master */ 39300caae6dSSimon Glass char *s = env_get("bootmaster"); 394b5f7c873SLiu Gang char pcie[6]; 395b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 396b5f7c873SLiu Gang 397b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) { 398b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Master port [ %d ] for pcie boot.\n", 399b5f7c873SLiu Gang pci_info->pci_num); 400b5f7c873SLiu Gang fsl_pcie_boot_master((pit_t *)pi); 401b5f7c873SLiu Gang } else { 402b5f7c873SLiu Gang /* inbound */ 403b5f7c873SLiu Gang inbound = fsl_pci_setup_inbound_windows(hose, 404b5f7c873SLiu Gang out_lo, pcie_cap, pi); 405b5f7c873SLiu Gang } 406b5f7c873SLiu Gang #else 407ad19e7a5SKumar Gala /* inbound */ 408ad19e7a5SKumar Gala inbound = fsl_pci_setup_inbound_windows(hose, out_lo, pcie_cap, pi); 409b5f7c873SLiu Gang #endif 410ad19e7a5SKumar Gala 411ad19e7a5SKumar Gala for (r = 0; r < hose->region_count; r++) 412d015df8fSMarek Vasut debug("PCI reg:%d %016llx:%016llx %016llx %08lx\n", r, 413ad19e7a5SKumar Gala (u64)hose->regions[r].phys_start, 414d015df8fSMarek Vasut (u64)hose->regions[r].bus_start, 415d015df8fSMarek Vasut (u64)hose->regions[r].size, 416ad19e7a5SKumar Gala hose->regions[r].flags); 417ad19e7a5SKumar Gala 41893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_register_hose(hose); 41993a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_config_init(hose); /* grab pci_{mem,prefetch,io} */ 42093a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno = hose->first_busno; 42193a686eeSJean-Christophe PLAGNIOL-VILLARD 422ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); /* Clear any errors */ 42316263087SMike Williams out_be32(&pci->peer, ~0x20140); /* Enable All Error Interrupts except 42493a686eeSJean-Christophe PLAGNIOL-VILLARD * - Master abort (pci) 42593a686eeSJean-Christophe PLAGNIOL-VILLARD * - Master PERR (pci) 42693a686eeSJean-Christophe PLAGNIOL-VILLARD * - ICCA (PCIe) 42793a686eeSJean-Christophe PLAGNIOL-VILLARD */ 428287df01eSZhao Qiang pci_hose_read_config_dword(hose, dev, pci_dcr, &temp32); 42993a686eeSJean-Christophe PLAGNIOL-VILLARD temp32 |= 0xf000e; /* set URR, FER, NFER (but not CER) */ 430287df01eSZhao Qiang pci_hose_write_config_dword(hose, dev, pci_dcr, temp32); 43193a686eeSJean-Christophe PLAGNIOL-VILLARD 432b03a466dSPrabhakar Kushwaha #if defined(CONFIG_FSL_PCIE_DISABLE_ASPM) 433287df01eSZhao Qiang pci_lcr = pcie_cap_pos + 0x10; 434b03a466dSPrabhakar Kushwaha temp32 = 0; 435287df01eSZhao Qiang pci_hose_read_config_dword(hose, dev, pci_lcr, &temp32); 436b03a466dSPrabhakar Kushwaha temp32 &= ~0x03; /* Disable ASPM */ 437287df01eSZhao Qiang pci_hose_write_config_dword(hose, dev, pci_lcr, temp32); 438b03a466dSPrabhakar Kushwaha udelay(1); 439b03a466dSPrabhakar Kushwaha #endif 4408295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 4417b4e5844SZang Roy-R61911 if (block_rev >= PEX_IP_BLK_REV_3_0) { 4427b4e5844SZang Roy-R61911 #define PEX_CSR0_LTSSM_MASK 0xFC 4437b4e5844SZang Roy-R61911 #define PEX_CSR0_LTSSM_SHIFT 2 4447b4e5844SZang Roy-R61911 ltssm = (in_be32(&pci->pex_csr0) 4457b4e5844SZang Roy-R61911 & PEX_CSR0_LTSSM_MASK) >> PEX_CSR0_LTSSM_SHIFT; 4467b4e5844SZang Roy-R61911 enabled = (ltssm == 0x11) ? 1 : 0; 4475066e628SZhao Qiang #ifdef CONFIG_FSL_PCIE_RESET 4485066e628SZhao Qiang int i; 4495066e628SZhao Qiang /* assert PCIe reset */ 4505066e628SZhao Qiang setbits_be32(&pci->pdb_stat, 0x08000000); 4515066e628SZhao Qiang (void) in_be32(&pci->pdb_stat); 4525066e628SZhao Qiang udelay(1000); 4535066e628SZhao Qiang /* clear PCIe reset */ 4545066e628SZhao Qiang clrbits_be32(&pci->pdb_stat, 0x08000000); 4555066e628SZhao Qiang asm("sync;isync"); 4565066e628SZhao Qiang for (i = 0; i < 100 && ltssm < PCI_LTSSM_L0; i++) { 4575066e628SZhao Qiang pci_hose_read_config_word(hose, dev, PCI_LTSSM, 4585066e628SZhao Qiang <ssm); 4595066e628SZhao Qiang udelay(1000); 4605066e628SZhao Qiang } 4615066e628SZhao Qiang #endif 4627b4e5844SZang Roy-R61911 } else { 4637b4e5844SZang Roy-R61911 /* pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); */ 4647b4e5844SZang Roy-R61911 /* enabled = ltssm >= PCI_LTSSM_L0; */ 46593a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); 46693a686eeSJean-Christophe PLAGNIOL-VILLARD enabled = ltssm >= PCI_LTSSM_L0; 46793a686eeSJean-Christophe PLAGNIOL-VILLARD 4688ff3de61SKumar Gala #ifdef CONFIG_FSL_PCIE_RESET 4698ff3de61SKumar Gala if (ltssm == 1) { 4708ff3de61SKumar Gala int i; 471ad19e7a5SKumar Gala debug("....PCIe link error. " "LTSSM=0x%02x.", ltssm); 472ad19e7a5SKumar Gala /* assert PCIe reset */ 473ad19e7a5SKumar Gala setbits_be32(&pci->pdb_stat, 0x08000000); 474ad19e7a5SKumar Gala (void) in_be32(&pci->pdb_stat); 4758ff3de61SKumar Gala udelay(100); 476d015df8fSMarek Vasut debug(" Asserting PCIe reset @%p = %x\n", 477ad19e7a5SKumar Gala &pci->pdb_stat, in_be32(&pci->pdb_stat)); 478ad19e7a5SKumar Gala /* clear PCIe reset */ 479ad19e7a5SKumar Gala clrbits_be32(&pci->pdb_stat, 0x08000000); 4808ff3de61SKumar Gala asm("sync;isync"); 4818ff3de61SKumar Gala for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) { 4828ff3de61SKumar Gala pci_hose_read_config_word(hose, dev, PCI_LTSSM, 4838ff3de61SKumar Gala <ssm); 4848ff3de61SKumar Gala udelay(1000); 4858ff3de61SKumar Gala debug("....PCIe link error. " 4868ff3de61SKumar Gala "LTSSM=0x%02x.\n", ltssm); 4878ff3de61SKumar Gala } 4888ff3de61SKumar Gala enabled = ltssm >= PCI_LTSSM_L0; 489ad19e7a5SKumar Gala 490ad19e7a5SKumar Gala /* we need to re-write the bar0 since a reset will 491ad19e7a5SKumar Gala * clear it 492ad19e7a5SKumar Gala */ 493ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, 494ad19e7a5SKumar Gala PCI_BASE_ADDRESS_0, pcicsrbar); 4958ff3de61SKumar Gala } 4968ff3de61SKumar Gala #endif 4977b4e5844SZang Roy-R61911 } 4988ff3de61SKumar Gala 499c0a4e6b8SYuanquan Chen #ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003 500c0a4e6b8SYuanquan Chen if (enabled == 0) { 501c0a4e6b8SYuanquan Chen serdes_corenet_t *srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; 502c0a4e6b8SYuanquan Chen temp32 = in_be32(&srds_regs->srdspccr0); 503c0a4e6b8SYuanquan Chen 504c0a4e6b8SYuanquan Chen if ((temp32 >> 28) == 3) { 505c0a4e6b8SYuanquan Chen int i; 506c0a4e6b8SYuanquan Chen 507c0a4e6b8SYuanquan Chen out_be32(&srds_regs->srdspccr0, 2 << 28); 508c0a4e6b8SYuanquan Chen setbits_be32(&pci->pdb_stat, 0x08000000); 509c0a4e6b8SYuanquan Chen in_be32(&pci->pdb_stat); 510c0a4e6b8SYuanquan Chen udelay(100); 511c0a4e6b8SYuanquan Chen clrbits_be32(&pci->pdb_stat, 0x08000000); 512c0a4e6b8SYuanquan Chen asm("sync;isync"); 513c0a4e6b8SYuanquan Chen for (i=0; i < 100 && ltssm < PCI_LTSSM_L0; i++) { 514c0a4e6b8SYuanquan Chen pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); 515c0a4e6b8SYuanquan Chen udelay(1000); 516c0a4e6b8SYuanquan Chen } 517c0a4e6b8SYuanquan Chen enabled = ltssm >= PCI_LTSSM_L0; 518c0a4e6b8SYuanquan Chen } 519c0a4e6b8SYuanquan Chen } 520c0a4e6b8SYuanquan Chen #endif 52193a686eeSJean-Christophe PLAGNIOL-VILLARD if (!enabled) { 52232514d25SZang Roy-R61911 /* Let the user know there's no PCIe link for root 52332514d25SZang Roy-R61911 * complex. for endpoint, the link may not setup, so 52432514d25SZang Roy-R61911 * print undetermined. 52532514d25SZang Roy-R61911 */ 52632514d25SZang Roy-R61911 if (fsl_is_pci_agent(hose)) 52732514d25SZang Roy-R61911 printf("undetermined, regs @ 0x%lx\n", pci_info->regs); 52832514d25SZang Roy-R61911 else 529213ac73eSPeter Tyser printf("no link, regs @ 0x%lx\n", pci_info->regs); 53093a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->first_busno; 53193a686eeSJean-Christophe PLAGNIOL-VILLARD return; 53293a686eeSJean-Christophe PLAGNIOL-VILLARD } 53393a686eeSJean-Christophe PLAGNIOL-VILLARD 534ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 535ad19e7a5SKumar Gala out_be32(&pci->pme_msg_int_en, 0xffffffff); 536213ac73eSPeter Tyser 537213ac73eSPeter Tyser /* Print the negotiated PCIe link width */ 538287df01eSZhao Qiang pci_hose_read_config_word(hose, dev, pci_lsr, &temp16); 539aceea941SPrabhakar Kushwaha printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, 540aceea941SPrabhakar Kushwaha (temp16 & 0xf), pci_info->regs); 541213ac73eSPeter Tyser 54293a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno++; /* Start scan with secondary */ 54393a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); 54493a686eeSJean-Christophe PLAGNIOL-VILLARD } 54593a686eeSJean-Christophe PLAGNIOL-VILLARD 54609bfd962STony O'Brien #ifdef CONFIG_SYS_FSL_ERRATUM_A007815 54709bfd962STony O'Brien /* The Read-Only Write Enable bit defaults to 1 instead of 0. 54809bfd962STony O'Brien * Set to 0 to protect the read-only registers. 54909bfd962STony O'Brien */ 55009bfd962STony O'Brien clrbits_be32(&pci->dbi_ro_wr_en, 0x01); 55109bfd962STony O'Brien #endif 55209bfd962STony O'Brien 55393a686eeSJean-Christophe PLAGNIOL-VILLARD /* Use generic setup_device to initialize standard pci regs, 55493a686eeSJean-Christophe PLAGNIOL-VILLARD * but do not allocate any windows since any BAR found (such 55593a686eeSJean-Christophe PLAGNIOL-VILLARD * as PCSRBAR) is not in this cpu's memory space. 55693a686eeSJean-Christophe PLAGNIOL-VILLARD */ 55793a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_setup_device(hose, dev, 0, hose->pci_mem, 55893a686eeSJean-Christophe PLAGNIOL-VILLARD hose->pci_prefetch, hose->pci_io); 55993a686eeSJean-Christophe PLAGNIOL-VILLARD 56093a686eeSJean-Christophe PLAGNIOL-VILLARD if (inbound) { 56193a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_COMMAND, &temp16); 56293a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_COMMAND, 56393a686eeSJean-Christophe PLAGNIOL-VILLARD temp16 | PCI_COMMAND_MEMORY); 56493a686eeSJean-Christophe PLAGNIOL-VILLARD } 56593a686eeSJean-Christophe PLAGNIOL-VILLARD 56693a686eeSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_PCI_NOSCAN 567505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) { 56837d03fceSPeter Tyser debug(" Scanning PCI bus %02x\n", 5696df0efd5SEd Swarthout hose->current_busno); 57093a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = pci_hose_scan_bus(hose, hose->current_busno); 5716df0efd5SEd Swarthout } else { 5726df0efd5SEd Swarthout debug(" Not scanning PCI bus %02x. PI=%x\n", 5736df0efd5SEd Swarthout hose->current_busno, temp8); 5746df0efd5SEd Swarthout hose->last_busno = hose->current_busno; 5756df0efd5SEd Swarthout } 57693a686eeSJean-Christophe PLAGNIOL-VILLARD 5778295b944SKumar Gala /* if we are PCIe - update limit regs and subordinate busno 5788295b944SKumar Gala * for the virtual P2P bridge 5798295b944SKumar Gala */ 5808295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 58193a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_postscan_setup_bridge(hose, dev, hose->last_busno); 58293a686eeSJean-Christophe PLAGNIOL-VILLARD } 58393a686eeSJean-Christophe PLAGNIOL-VILLARD #else 58493a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->current_busno; 58593a686eeSJean-Christophe PLAGNIOL-VILLARD #endif 58693a686eeSJean-Christophe PLAGNIOL-VILLARD 58793a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear all error indications */ 5888295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) 589ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 590ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); 59193a686eeSJean-Christophe PLAGNIOL-VILLARD 592287df01eSZhao Qiang pci_hose_read_config_word(hose, dev, pci_dsr, &temp16); 59393a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 594287df01eSZhao Qiang pci_hose_write_config_word(hose, dev, pci_dsr, 0xffff); 59593a686eeSJean-Christophe PLAGNIOL-VILLARD } 59693a686eeSJean-Christophe PLAGNIOL-VILLARD 59793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16); 59893a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 59993a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff); 60093a686eeSJean-Christophe PLAGNIOL-VILLARD } 60193a686eeSJean-Christophe PLAGNIOL-VILLARD } 602a2aab460SKumar Gala 603715d8f76SEd Swarthout int fsl_is_pci_agent(struct pci_controller *hose) 604715d8f76SEd Swarthout { 605287df01eSZhao Qiang int pcie_cap_pos; 606505f3e6fSMinghuan Lian u8 pcie_cap; 607715d8f76SEd Swarthout pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 608715d8f76SEd Swarthout 609287df01eSZhao Qiang pcie_cap_pos = pci_hose_find_capability(hose, dev, PCI_CAP_ID_EXP); 610287df01eSZhao Qiang pci_hose_read_config_byte(hose, dev, pcie_cap_pos, &pcie_cap); 611505f3e6fSMinghuan Lian if (pcie_cap == PCI_CAP_ID_EXP) { 612505f3e6fSMinghuan Lian u8 header_type; 613715d8f76SEd Swarthout 614505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, 615505f3e6fSMinghuan Lian &header_type); 616505f3e6fSMinghuan Lian return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; 617505f3e6fSMinghuan Lian } else { 618505f3e6fSMinghuan Lian u8 prog_if; 619505f3e6fSMinghuan Lian 620505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); 6217b4e5844SZang Roy-R61911 /* Programming Interface (PCI_CLASS_PROG) 6227b4e5844SZang Roy-R61911 * 0 == pci host or pcie root-complex, 6237b4e5844SZang Roy-R61911 * 1 == pci agent or pcie end-point 6247b4e5844SZang Roy-R61911 */ 625715d8f76SEd Swarthout return (prog_if == FSL_PROG_IF_AGENT); 626715d8f76SEd Swarthout } 627505f3e6fSMinghuan Lian } 628715d8f76SEd Swarthout 6290d3d68b2SPoonam Aggrwal int fsl_pci_init_port(struct fsl_pci_info *pci_info, 63001471d53SKumar Gala struct pci_controller *hose, int busno) 6310d3d68b2SPoonam Aggrwal { 6320d3d68b2SPoonam Aggrwal volatile ccsr_fsl_pci_t *pci; 6330d3d68b2SPoonam Aggrwal struct pci_region *r; 634a72dbae2SPeter Tyser pci_dev_t dev = PCI_BDF(busno,0,0); 635287df01eSZhao Qiang int pcie_cap_pos; 636a72dbae2SPeter Tyser u8 pcie_cap; 6370d3d68b2SPoonam Aggrwal 6380d3d68b2SPoonam Aggrwal pci = (ccsr_fsl_pci_t *) pci_info->regs; 6390d3d68b2SPoonam Aggrwal 6400d3d68b2SPoonam Aggrwal /* on non-PCIe controllers we don't have pme_msg_det so this code 6410d3d68b2SPoonam Aggrwal * should do nothing since the read will return 0 6420d3d68b2SPoonam Aggrwal */ 6430d3d68b2SPoonam Aggrwal if (in_be32(&pci->pme_msg_det)) { 6440d3d68b2SPoonam Aggrwal out_be32(&pci->pme_msg_det, 0xffffffff); 6450d3d68b2SPoonam Aggrwal debug (" with errors. Clearing. Now 0x%08x", 6460d3d68b2SPoonam Aggrwal pci->pme_msg_det); 6470d3d68b2SPoonam Aggrwal } 6480d3d68b2SPoonam Aggrwal 6490d3d68b2SPoonam Aggrwal r = hose->regions + hose->region_count; 6500d3d68b2SPoonam Aggrwal 6510d3d68b2SPoonam Aggrwal /* outbound memory */ 6520d3d68b2SPoonam Aggrwal pci_set_region(r++, 6530d3d68b2SPoonam Aggrwal pci_info->mem_bus, 6540d3d68b2SPoonam Aggrwal pci_info->mem_phys, 6550d3d68b2SPoonam Aggrwal pci_info->mem_size, 6560d3d68b2SPoonam Aggrwal PCI_REGION_MEM); 6570d3d68b2SPoonam Aggrwal 6580d3d68b2SPoonam Aggrwal /* outbound io */ 6590d3d68b2SPoonam Aggrwal pci_set_region(r++, 6600d3d68b2SPoonam Aggrwal pci_info->io_bus, 6610d3d68b2SPoonam Aggrwal pci_info->io_phys, 6620d3d68b2SPoonam Aggrwal pci_info->io_size, 6630d3d68b2SPoonam Aggrwal PCI_REGION_IO); 6640d3d68b2SPoonam Aggrwal 6650d3d68b2SPoonam Aggrwal hose->region_count = r - hose->regions; 6660d3d68b2SPoonam Aggrwal hose->first_busno = busno; 6670d3d68b2SPoonam Aggrwal 668213ac73eSPeter Tyser fsl_pci_init(hose, pci_info); 6690d3d68b2SPoonam Aggrwal 670715d8f76SEd Swarthout if (fsl_is_pci_agent(hose)) { 671715d8f76SEd Swarthout fsl_pci_config_unlock(hose); 672715d8f76SEd Swarthout hose->last_busno = hose->first_busno; 673c8b28152SLiu Gang #ifdef CONFIG_SRIO_PCIE_BOOT_MASTER 674b5f7c873SLiu Gang } else { 675b5f7c873SLiu Gang /* boot from PCIE --master releases slave's core 0 */ 67600caae6dSSimon Glass char *s = env_get("bootmaster"); 677b5f7c873SLiu Gang char pcie[6]; 678b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 679b5f7c873SLiu Gang 680b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) 681b5f7c873SLiu Gang fsl_pcie_boot_master_release_slave(pci_info->pci_num); 682b5f7c873SLiu Gang #endif 683715d8f76SEd Swarthout } 684715d8f76SEd Swarthout 685287df01eSZhao Qiang pcie_cap_pos = pci_hose_find_capability(hose, dev, PCI_CAP_ID_EXP); 686287df01eSZhao Qiang pci_hose_read_config_byte(hose, dev, pcie_cap_pos, &pcie_cap); 6878ca78f2cSPeter Tyser printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ? 688213ac73eSPeter Tyser "e" : "", pci_info->pci_num, 6890d3d68b2SPoonam Aggrwal hose->first_busno, hose->last_busno); 6900d3d68b2SPoonam Aggrwal return(hose->last_busno + 1); 6910d3d68b2SPoonam Aggrwal } 6920d3d68b2SPoonam Aggrwal 6937a897959SPeter Tyser /* Enable inbound PCI config cycles for agent/endpoint interface */ 6947a897959SPeter Tyser void fsl_pci_config_unlock(struct pci_controller *hose) 6957a897959SPeter Tyser { 6967a897959SPeter Tyser pci_dev_t dev = PCI_BDF(hose->first_busno,0,0); 697287df01eSZhao Qiang int pcie_cap_pos; 6987a897959SPeter Tyser u8 pcie_cap; 6997a897959SPeter Tyser u16 pbfr; 7007a897959SPeter Tyser 701505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) 7027a897959SPeter Tyser return; 7037a897959SPeter Tyser 704287df01eSZhao Qiang pcie_cap_pos = pci_hose_find_capability(hose, dev, PCI_CAP_ID_EXP); 705287df01eSZhao Qiang pci_hose_read_config_byte(hose, dev, pcie_cap_pos, &pcie_cap); 7067a897959SPeter Tyser if (pcie_cap != 0x0) { 7071d0b59a9SMinghuan Lian ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)hose->cfg_addr; 7081d0b59a9SMinghuan Lian u32 block_rev = in_be32(&pci->block_rev1); 7097a897959SPeter Tyser /* PCIe - set CFG_READY bit of Configuration Ready Register */ 7101d0b59a9SMinghuan Lian if (block_rev >= PEX_IP_BLK_REV_3_0) 7111d0b59a9SMinghuan Lian setbits_be32(&pci->config, FSL_PCIE_V3_CFG_RDY); 7121d0b59a9SMinghuan Lian else 7131d0b59a9SMinghuan Lian pci_hose_write_config_byte(hose, dev, 7141d0b59a9SMinghuan Lian FSL_PCIE_CFG_RDY, 0x1); 7157a897959SPeter Tyser } else { 7167a897959SPeter Tyser /* PCI - clear ACL bit of PBFR */ 7177a897959SPeter Tyser pci_hose_read_config_word(hose, dev, FSL_PCI_PBFR, &pbfr); 7187a897959SPeter Tyser pbfr &= ~0x20; 7197a897959SPeter Tyser pci_hose_write_config_word(hose, dev, FSL_PCI_PBFR, pbfr); 7207a897959SPeter Tyser } 7217a897959SPeter Tyser } 7227a897959SPeter Tyser 723a4aafcc9SKumar Gala #if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \ 724a4aafcc9SKumar Gala defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) 725a4aafcc9SKumar Gala int fsl_configure_pcie(struct fsl_pci_info *info, 726a4aafcc9SKumar Gala struct pci_controller *hose, 727a4aafcc9SKumar Gala const char *connected, int busno) 728a4aafcc9SKumar Gala { 729a4aafcc9SKumar Gala int is_endpoint; 730a4aafcc9SKumar Gala 731a4aafcc9SKumar Gala set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); 732a4aafcc9SKumar Gala set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); 733213ac73eSPeter Tyser 734a4aafcc9SKumar Gala is_endpoint = fsl_setup_hose(hose, info->regs); 735213ac73eSPeter Tyser printf("PCIe%u: %s", info->pci_num, 736213ac73eSPeter Tyser is_endpoint ? "Endpoint" : "Root Complex"); 737213ac73eSPeter Tyser if (connected) 738213ac73eSPeter Tyser printf(" of %s", connected); 739213ac73eSPeter Tyser puts(", "); 740213ac73eSPeter Tyser 741a4aafcc9SKumar Gala return fsl_pci_init_port(info, hose, busno); 742a4aafcc9SKumar Gala } 743a4aafcc9SKumar Gala 744a4aafcc9SKumar Gala #if defined(CONFIG_FSL_CORENET) 7459e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 7469e758758SYork Sun #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR3_PCIE1 7479e758758SYork Sun #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR3_PCIE2 7489e758758SYork Sun #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR3_PCIE3 7499e758758SYork Sun #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR3_PCIE4 7509e758758SYork Sun #else 751a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1 752a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2 753a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3 754a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4 7559e758758SYork Sun #endif 756a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 757a4aafcc9SKumar Gala #elif defined(CONFIG_MPC85xx) 758a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE 759a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2 760a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3 761a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 762a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 763a4aafcc9SKumar Gala #elif defined(CONFIG_MPC86xx) 764a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1 765a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2 766a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 0 767a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 768a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ 769a4aafcc9SKumar Gala (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) 770a4aafcc9SKumar Gala #else 771a4aafcc9SKumar Gala #error "No defines for DEVDISR_PCIE" 772a4aafcc9SKumar Gala #endif 773a4aafcc9SKumar Gala 774a4aafcc9SKumar Gala /* Implement a dummy function for those platforms w/o SERDES */ 775a4aafcc9SKumar Gala static const char *__board_serdes_name(enum srds_prtcl device) 776a4aafcc9SKumar Gala { 777a4aafcc9SKumar Gala switch (device) { 778a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE1_NAME 779a4aafcc9SKumar Gala case PCIE1: 780a4aafcc9SKumar Gala return CONFIG_SYS_PCIE1_NAME; 781a4aafcc9SKumar Gala #endif 782a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE2_NAME 783a4aafcc9SKumar Gala case PCIE2: 784a4aafcc9SKumar Gala return CONFIG_SYS_PCIE2_NAME; 785a4aafcc9SKumar Gala #endif 786a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE3_NAME 787a4aafcc9SKumar Gala case PCIE3: 788a4aafcc9SKumar Gala return CONFIG_SYS_PCIE3_NAME; 789a4aafcc9SKumar Gala #endif 790a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE4_NAME 791a4aafcc9SKumar Gala case PCIE4: 792a4aafcc9SKumar Gala return CONFIG_SYS_PCIE4_NAME; 793a4aafcc9SKumar Gala #endif 794a4aafcc9SKumar Gala default: 795a4aafcc9SKumar Gala return NULL; 796a4aafcc9SKumar Gala } 797a4aafcc9SKumar Gala 798a4aafcc9SKumar Gala return NULL; 799a4aafcc9SKumar Gala } 800a4aafcc9SKumar Gala 801a4aafcc9SKumar Gala __attribute__((weak, alias("__board_serdes_name"))) const char * 802a4aafcc9SKumar Gala board_serdes_name(enum srds_prtcl device); 803a4aafcc9SKumar Gala 804a4aafcc9SKumar Gala static u32 devdisr_mask[] = { 805a4aafcc9SKumar Gala _DEVDISR_PCIE1, 806a4aafcc9SKumar Gala _DEVDISR_PCIE2, 807a4aafcc9SKumar Gala _DEVDISR_PCIE3, 808a4aafcc9SKumar Gala _DEVDISR_PCIE4, 809a4aafcc9SKumar Gala }; 810a4aafcc9SKumar Gala 811a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 812a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 813a4aafcc9SKumar Gala { 814a4aafcc9SKumar Gala struct pci_controller *hose; 815a4aafcc9SKumar Gala int num = dev - PCIE1; 816a4aafcc9SKumar Gala 817a4aafcc9SKumar Gala hose = calloc(1, sizeof(struct pci_controller)); 818a4aafcc9SKumar Gala if (!hose) 819a4aafcc9SKumar Gala return busno; 820a4aafcc9SKumar Gala 821a4aafcc9SKumar Gala if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) { 822a4aafcc9SKumar Gala busno = fsl_configure_pcie(pci_info, hose, 823a4aafcc9SKumar Gala board_serdes_name(dev), busno); 824a4aafcc9SKumar Gala } else { 825213ac73eSPeter Tyser printf("PCIe%d: disabled\n", num + 1); 826a4aafcc9SKumar Gala } 827a4aafcc9SKumar Gala 828a4aafcc9SKumar Gala return busno; 829a4aafcc9SKumar Gala } 830a4aafcc9SKumar Gala 831a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 832a4aafcc9SKumar Gala { 833a4aafcc9SKumar Gala struct fsl_pci_info pci_info; 834a4aafcc9SKumar Gala ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; 8359e758758SYork Sun u32 devdisr; 8369e758758SYork Sun u32 *addr; 8379e758758SYork Sun 8389e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 8399e758758SYork Sun addr = &gur->devdisr3; 8409e758758SYork Sun #else 8419e758758SYork Sun addr = &gur->devdisr; 8429e758758SYork Sun #endif 8439e758758SYork Sun devdisr = in_be32(addr); 844a4aafcc9SKumar Gala 845a4aafcc9SKumar Gala #ifdef CONFIG_PCIE1 846a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 1); 847a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info); 848a4aafcc9SKumar Gala #else 8499e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE1); /* disable */ 850a4aafcc9SKumar Gala #endif 851a4aafcc9SKumar Gala 852a4aafcc9SKumar Gala #ifdef CONFIG_PCIE2 853a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 2); 854a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info); 855a4aafcc9SKumar Gala #else 8569e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE2); /* disable */ 857a4aafcc9SKumar Gala #endif 858a4aafcc9SKumar Gala 859a4aafcc9SKumar Gala #ifdef CONFIG_PCIE3 860a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 3); 861a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info); 862a4aafcc9SKumar Gala #else 8639e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE3); /* disable */ 864a4aafcc9SKumar Gala #endif 865a4aafcc9SKumar Gala 866a4aafcc9SKumar Gala #ifdef CONFIG_PCIE4 867a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 4); 868a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info); 869a4aafcc9SKumar Gala #else 8709e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE4); /* disable */ 871a4aafcc9SKumar Gala #endif 872a4aafcc9SKumar Gala 873a4aafcc9SKumar Gala return busno; 874a4aafcc9SKumar Gala } 875a4aafcc9SKumar Gala #else 876a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 877a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 878a4aafcc9SKumar Gala { 879a4aafcc9SKumar Gala return busno; 880a4aafcc9SKumar Gala } 881a4aafcc9SKumar Gala 882a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 883a4aafcc9SKumar Gala { 884a4aafcc9SKumar Gala return busno; 885a4aafcc9SKumar Gala } 886a4aafcc9SKumar Gala #endif 887a4aafcc9SKumar Gala 888a2aab460SKumar Gala #ifdef CONFIG_OF_BOARD_SETUP 889*b08c8c48SMasahiro Yamada #include <linux/libfdt.h> 890a2aab460SKumar Gala #include <fdt_support.h> 891a2aab460SKumar Gala 8926525d51fSKumar Gala void ft_fsl_pci_setup(void *blob, const char *pci_compat, 8933a0e3c27SKumar Gala unsigned long ctrl_addr) 894a2aab460SKumar Gala { 8956525d51fSKumar Gala int off; 896a2aab460SKumar Gala u32 bus_range[2]; 8976525d51fSKumar Gala phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr; 8983a0e3c27SKumar Gala struct pci_controller *hose; 8993a0e3c27SKumar Gala 9003a0e3c27SKumar Gala hose = find_hose_by_cfg_addr((void *)(ctrl_addr)); 9016525d51fSKumar Gala 9026525d51fSKumar Gala /* convert ctrl_addr to true physical address */ 9036525d51fSKumar Gala p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR; 9046525d51fSKumar Gala p_ctrl_addr += CONFIG_SYS_CCSRBAR_PHYS; 9056525d51fSKumar Gala 9066525d51fSKumar Gala off = fdt_node_offset_by_compat_reg(blob, pci_compat, p_ctrl_addr); 907a2aab460SKumar Gala 9085a85a309SKumar Gala if (off < 0) 9095a85a309SKumar Gala return; 9105a85a309SKumar Gala 9115a85a309SKumar Gala /* We assume a cfg_addr not being set means we didn't setup the controller */ 9125a85a309SKumar Gala if ((hose == NULL) || (hose->cfg_addr == NULL)) { 9136525d51fSKumar Gala fdt_del_node(blob, off); 9145a85a309SKumar Gala } else { 915a2aab460SKumar Gala bus_range[0] = 0; 916a2aab460SKumar Gala bus_range[1] = hose->last_busno - hose->first_busno; 917a2aab460SKumar Gala fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4); 918a2aab460SKumar Gala fdt_pci_dma_ranges(blob, off, hose); 919a2aab460SKumar Gala } 920a2aab460SKumar Gala } 921a2aab460SKumar Gala #endif 922