193a686eeSJean-Christophe PLAGNIOL-VILLARD /* 2505f3e6fSMinghuan Lian * Copyright 2007-2012 Freescale Semiconductor, Inc. 393a686eeSJean-Christophe PLAGNIOL-VILLARD * 45a85a309SKumar Gala * This program is free software; you can redistribute it and/or modify it 55a85a309SKumar Gala * under the terms of the GNU General Public License as published by the Free 65a85a309SKumar Gala * Software Foundation; either version 2 of the License, or (at your option) 75a85a309SKumar Gala * any later version. 893a686eeSJean-Christophe PLAGNIOL-VILLARD * 993a686eeSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 1093a686eeSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 1193a686eeSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1293a686eeSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 1393a686eeSJean-Christophe PLAGNIOL-VILLARD * 1493a686eeSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 1593a686eeSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 1693a686eeSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 1793a686eeSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 1893a686eeSJean-Christophe PLAGNIOL-VILLARD */ 1993a686eeSJean-Christophe PLAGNIOL-VILLARD 2093a686eeSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 21a4aafcc9SKumar Gala #include <malloc.h> 22a4aafcc9SKumar Gala #include <asm/fsl_serdes.h> 2393a686eeSJean-Christophe PLAGNIOL-VILLARD 24b9a1fa97SKumar Gala DECLARE_GLOBAL_DATA_PTR; 25b9a1fa97SKumar Gala 2693a686eeSJean-Christophe PLAGNIOL-VILLARD /* 2793a686eeSJean-Christophe PLAGNIOL-VILLARD * PCI/PCIE Controller initialization for mpc85xx/mpc86xx soc's 2893a686eeSJean-Christophe PLAGNIOL-VILLARD * 2993a686eeSJean-Christophe PLAGNIOL-VILLARD * Initialize controller and call the common driver/pci pci_hose_scan to 3093a686eeSJean-Christophe PLAGNIOL-VILLARD * scan for bridges and devices. 3193a686eeSJean-Christophe PLAGNIOL-VILLARD * 3293a686eeSJean-Christophe PLAGNIOL-VILLARD * Hose fields which need to be pre-initialized by board specific code: 3393a686eeSJean-Christophe PLAGNIOL-VILLARD * regions[] 3493a686eeSJean-Christophe PLAGNIOL-VILLARD * first_busno 3593a686eeSJean-Christophe PLAGNIOL-VILLARD * 3693a686eeSJean-Christophe PLAGNIOL-VILLARD * Fields updated: 3793a686eeSJean-Christophe PLAGNIOL-VILLARD * last_busno 3893a686eeSJean-Christophe PLAGNIOL-VILLARD */ 3993a686eeSJean-Christophe PLAGNIOL-VILLARD 4093a686eeSJean-Christophe PLAGNIOL-VILLARD #include <pci.h> 41ad19e7a5SKumar Gala #include <asm/io.h> 42c8514622SKumar Gala #include <asm/fsl_pci.h> 4393a686eeSJean-Christophe PLAGNIOL-VILLARD 447a897959SPeter Tyser /* Freescale-specific PCI config registers */ 457a897959SPeter Tyser #define FSL_PCI_PBFR 0x44 467a897959SPeter Tyser #define FSL_PCIE_CAP_ID 0x4c 477a897959SPeter Tyser #define FSL_PCIE_CFG_RDY 0x4b0 48715d8f76SEd Swarthout #define FSL_PROG_IF_AGENT 0x1 497a897959SPeter Tyser 50b9a1fa97SKumar Gala #ifndef CONFIG_SYS_PCI_MEMORY_BUS 51b9a1fa97SKumar Gala #define CONFIG_SYS_PCI_MEMORY_BUS 0 52b9a1fa97SKumar Gala #endif 53b9a1fa97SKumar Gala 54b9a1fa97SKumar Gala #ifndef CONFIG_SYS_PCI_MEMORY_PHYS 55b9a1fa97SKumar Gala #define CONFIG_SYS_PCI_MEMORY_PHYS 0 56b9a1fa97SKumar Gala #endif 57b9a1fa97SKumar Gala 58b9a1fa97SKumar Gala #if defined(CONFIG_SYS_PCI_64BIT) && !defined(CONFIG_SYS_PCI64_MEMORY_BUS) 59b9a1fa97SKumar Gala #define CONFIG_SYS_PCI64_MEMORY_BUS (64ull*1024*1024*1024) 60b9a1fa97SKumar Gala #endif 61b9a1fa97SKumar Gala 62ad19e7a5SKumar Gala /* Setup one inbound ATMU window. 63ad19e7a5SKumar Gala * 64ad19e7a5SKumar Gala * We let the caller decide what the window size should be 65ad19e7a5SKumar Gala */ 66ad19e7a5SKumar Gala static void set_inbound_window(volatile pit_t *pi, 67ad19e7a5SKumar Gala struct pci_region *r, 68ad19e7a5SKumar Gala u64 size) 69b9a1fa97SKumar Gala { 70ad19e7a5SKumar Gala u32 sz = (__ilog2_u64(size) - 1); 71ad19e7a5SKumar Gala u32 flag = PIWAR_EN | PIWAR_LOCAL | 72ad19e7a5SKumar Gala PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP; 73ad19e7a5SKumar Gala 74ad19e7a5SKumar Gala out_be32(&pi->pitar, r->phys_start >> 12); 75ad19e7a5SKumar Gala out_be32(&pi->piwbar, r->bus_start >> 12); 76ad19e7a5SKumar Gala #ifdef CONFIG_SYS_PCI_64BIT 77ad19e7a5SKumar Gala out_be32(&pi->piwbear, r->bus_start >> 44); 78ad19e7a5SKumar Gala #else 79ad19e7a5SKumar Gala out_be32(&pi->piwbear, 0); 80ad19e7a5SKumar Gala #endif 81ad19e7a5SKumar Gala if (r->flags & PCI_REGION_PREFETCH) 82ad19e7a5SKumar Gala flag |= PIWAR_PF; 83ad19e7a5SKumar Gala out_be32(&pi->piwar, flag | sz); 84ad19e7a5SKumar Gala } 85ad19e7a5SKumar Gala 86ee53650dSKumar Gala int fsl_setup_hose(struct pci_controller *hose, unsigned long addr) 87ee53650dSKumar Gala { 88ee53650dSKumar Gala volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *) addr; 89ee53650dSKumar Gala 9096d61603SJohn Schmoller /* Reset hose to make sure its in a clean state */ 9196d61603SJohn Schmoller memset(hose, 0, sizeof(struct pci_controller)); 9296d61603SJohn Schmoller 93ee53650dSKumar Gala pci_setup_indirect(hose, (u32)&pci->cfg_addr, (u32)&pci->cfg_data); 94ee53650dSKumar Gala 95ee53650dSKumar Gala return fsl_is_pci_agent(hose); 96ee53650dSKumar Gala } 97ee53650dSKumar Gala 98ad19e7a5SKumar Gala static int fsl_pci_setup_inbound_windows(struct pci_controller *hose, 99ad19e7a5SKumar Gala u64 out_lo, u8 pcie_cap, 100ad19e7a5SKumar Gala volatile pit_t *pi) 101ad19e7a5SKumar Gala { 102ad19e7a5SKumar Gala struct pci_region *r = hose->regions + hose->region_count; 103ad19e7a5SKumar Gala u64 sz = min((u64)gd->ram_size, (1ull << 32)); 104b9a1fa97SKumar Gala 105b9a1fa97SKumar Gala phys_addr_t phys_start = CONFIG_SYS_PCI_MEMORY_PHYS; 106b9a1fa97SKumar Gala pci_addr_t bus_start = CONFIG_SYS_PCI_MEMORY_BUS; 107ad19e7a5SKumar Gala pci_size_t pci_sz; 108b9a1fa97SKumar Gala 109ad19e7a5SKumar Gala /* we have no space available for inbound memory mapping */ 110ad19e7a5SKumar Gala if (bus_start > out_lo) { 111ad19e7a5SKumar Gala printf ("no space for inbound mapping of memory\n"); 112ad19e7a5SKumar Gala return 0; 113ad19e7a5SKumar Gala } 114ad19e7a5SKumar Gala 115ad19e7a5SKumar Gala /* limit size */ 116ad19e7a5SKumar Gala if ((bus_start + sz) > out_lo) { 117ad19e7a5SKumar Gala sz = out_lo - bus_start; 118ad19e7a5SKumar Gala debug ("limiting size to %llx\n", sz); 119ad19e7a5SKumar Gala } 120ad19e7a5SKumar Gala 121ad19e7a5SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 122ad19e7a5SKumar Gala /* 123ad19e7a5SKumar Gala * we can overlap inbound/outbound windows on PCI-E since RX & TX 124ad19e7a5SKumar Gala * links a separate 125ad19e7a5SKumar Gala */ 126ad19e7a5SKumar Gala if ((pcie_cap == PCI_CAP_ID_EXP) && (pci_sz < sz)) { 127b9a1fa97SKumar Gala debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n", 128ad19e7a5SKumar Gala (u64)bus_start, (u64)phys_start, (u64)sz); 129ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, sz, 130ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 131b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 132b9a1fa97SKumar Gala 133ad19e7a5SKumar Gala /* if we aren't an exact power of two match, pci_sz is smaller 134ad19e7a5SKumar Gala * round it up to the next power of two. We report the actual 135ad19e7a5SKumar Gala * size to pci region tracking. 136ad19e7a5SKumar Gala */ 137ad19e7a5SKumar Gala if (pci_sz != sz) 138ad19e7a5SKumar Gala sz = 2ull << __ilog2_u64(sz); 139ad19e7a5SKumar Gala 140ad19e7a5SKumar Gala set_inbound_window(pi--, r++, sz); 141ad19e7a5SKumar Gala sz = 0; /* make sure we dont set the R2 window */ 142ad19e7a5SKumar Gala } else { 143ad19e7a5SKumar Gala debug ("R0 bus_start: %llx phys_start: %llx size: %llx\n", 144ad19e7a5SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 145ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 146ad19e7a5SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 147ad19e7a5SKumar Gala PCI_REGION_PREFETCH); 148ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 149ad19e7a5SKumar Gala 150b9a1fa97SKumar Gala sz -= pci_sz; 151b9a1fa97SKumar Gala bus_start += pci_sz; 152b9a1fa97SKumar Gala phys_start += pci_sz; 153b9a1fa97SKumar Gala 154b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 155b9a1fa97SKumar Gala if (sz) { 156b9a1fa97SKumar Gala debug ("R1 bus_start: %llx phys_start: %llx size: %llx\n", 157b9a1fa97SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 158ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 159ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 160b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 161ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 162b9a1fa97SKumar Gala sz -= pci_sz; 163b9a1fa97SKumar Gala bus_start += pci_sz; 164b9a1fa97SKumar Gala phys_start += pci_sz; 165b9a1fa97SKumar Gala } 166ad19e7a5SKumar Gala } 167b9a1fa97SKumar Gala 168b9a1fa97SKumar Gala #if defined(CONFIG_PHYS_64BIT) && defined(CONFIG_SYS_PCI_64BIT) 169cd425162SBecky Bruce /* 170cd425162SBecky Bruce * On 64-bit capable systems, set up a mapping for all of DRAM 171cd425162SBecky Bruce * in high pci address space. 172cd425162SBecky Bruce */ 173b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(gd->ram_size); 174b9a1fa97SKumar Gala /* round up to the next largest power of two */ 175b9a1fa97SKumar Gala if (gd->ram_size > pci_sz) 176cd425162SBecky Bruce pci_sz = 1ull << (__ilog2_u64(gd->ram_size) + 1); 177b9a1fa97SKumar Gala debug ("R64 bus_start: %llx phys_start: %llx size: %llx\n", 178cd425162SBecky Bruce (u64)CONFIG_SYS_PCI64_MEMORY_BUS, 179b9a1fa97SKumar Gala (u64)CONFIG_SYS_PCI_MEMORY_PHYS, 180b9a1fa97SKumar Gala (u64)pci_sz); 181ad19e7a5SKumar Gala pci_set_region(r, 182cd425162SBecky Bruce CONFIG_SYS_PCI64_MEMORY_BUS, 183b9a1fa97SKumar Gala CONFIG_SYS_PCI_MEMORY_PHYS, 184b9a1fa97SKumar Gala pci_sz, 185ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 186b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 187ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 188b9a1fa97SKumar Gala #else 189b9a1fa97SKumar Gala pci_sz = 1ull << __ilog2_u64(sz); 190b9a1fa97SKumar Gala if (sz) { 191b9a1fa97SKumar Gala debug ("R2 bus_start: %llx phys_start: %llx size: %llx\n", 192b9a1fa97SKumar Gala (u64)bus_start, (u64)phys_start, (u64)pci_sz); 193ad19e7a5SKumar Gala pci_set_region(r, bus_start, phys_start, pci_sz, 194ff4e66e9SKumar Gala PCI_REGION_MEM | PCI_REGION_SYS_MEMORY | 195b9a1fa97SKumar Gala PCI_REGION_PREFETCH); 196b9a1fa97SKumar Gala sz -= pci_sz; 197b9a1fa97SKumar Gala bus_start += pci_sz; 198b9a1fa97SKumar Gala phys_start += pci_sz; 199ad19e7a5SKumar Gala set_inbound_window(pi--, r++, pci_sz); 200b9a1fa97SKumar Gala } 201b9a1fa97SKumar Gala #endif 202b9a1fa97SKumar Gala 2034c253fdbSKumar Gala #ifdef CONFIG_PHYS_64BIT 204b9a1fa97SKumar Gala if (sz && (((u64)gd->ram_size) < (1ull << 32))) 205b9a1fa97SKumar Gala printf("Was not able to map all of memory via " 206b9a1fa97SKumar Gala "inbound windows -- %lld remaining\n", sz); 2074c253fdbSKumar Gala #endif 208b9a1fa97SKumar Gala 209ad19e7a5SKumar Gala hose->region_count = r - hose->regions; 210ad19e7a5SKumar Gala 211ad19e7a5SKumar Gala return 1; 212b9a1fa97SKumar Gala } 213b9a1fa97SKumar Gala 214*19e4a009SLiu Gang #ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER 215b5f7c873SLiu Gang static void fsl_pcie_boot_master(pit_t *pi) 216b5f7c873SLiu Gang { 217b5f7c873SLiu Gang /* configure inbound window for slave's u-boot image */ 218b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's image; " 219b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 220b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 221b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, 222b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 223b5f7c873SLiu Gang struct pci_region r_inbound; 224b5f7c873SLiu Gang u32 sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE) 225b5f7c873SLiu Gang - 1; 226b5f7c873SLiu Gang pci_set_region(&r_inbound, 227b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS1, 228b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 229b5f7c873SLiu Gang sz_inbound, 230b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 231b5f7c873SLiu Gang 232b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 233b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 234b5f7c873SLiu Gang 235b5f7c873SLiu Gang /* configure inbound window for slave's u-boot image */ 236b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's image; " 237b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 238b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 239b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, 240b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 241b5f7c873SLiu Gang pci_set_region(&r_inbound, 242b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_BUS2, 243b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_MEM_PHYS, 244b5f7c873SLiu Gang sz_inbound, 245b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 246b5f7c873SLiu Gang 247b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 248b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_IMAGE_SIZE); 249b5f7c873SLiu Gang 250b5f7c873SLiu Gang /* configure inbound window for slave's ucode and ENV */ 251b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Inbound window for slave's " 252b5f7c873SLiu Gang "ucode and ENV; " 253b5f7c873SLiu Gang "Local = 0x%llx, Bus = 0x%llx, Size = 0x%x\n", 254b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, 255b5f7c873SLiu Gang (u64)CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, 256b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); 257b5f7c873SLiu Gang sz_inbound = __ilog2_u64(CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE) 258b5f7c873SLiu Gang - 1; 259b5f7c873SLiu Gang pci_set_region(&r_inbound, 260b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_BUS, 261b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_MEM_PHYS, 262b5f7c873SLiu Gang sz_inbound, 263b5f7c873SLiu Gang PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); 264b5f7c873SLiu Gang 265b5f7c873SLiu Gang set_inbound_window(pi--, &r_inbound, 266b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_UCODE_ENV_SIZE); 267b5f7c873SLiu Gang } 268b5f7c873SLiu Gang 269b5f7c873SLiu Gang static void fsl_pcie_boot_master_release_slave(int port) 270b5f7c873SLiu Gang { 271b5f7c873SLiu Gang unsigned long release_addr; 272b5f7c873SLiu Gang 273b5f7c873SLiu Gang /* now release slave's core 0 */ 274b5f7c873SLiu Gang switch (port) { 275b5f7c873SLiu Gang case 1: 276b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE1_MEM_VIRT 277b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 278b5f7c873SLiu Gang break; 279a1e4318cSYork Sun #ifdef CONFIG_SYS_PCIE2_MEM_VIRT 280b5f7c873SLiu Gang case 2: 281b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE2_MEM_VIRT 282b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 283b5f7c873SLiu Gang break; 284a1e4318cSYork Sun #endif 285a1e4318cSYork Sun #ifdef CONFIG_SYS_PCIE3_MEM_VIRT 286b5f7c873SLiu Gang case 3: 287b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE3_MEM_VIRT 288b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 289b5f7c873SLiu Gang break; 290a1e4318cSYork Sun #endif 291b5f7c873SLiu Gang default: 292b5f7c873SLiu Gang release_addr = 0; 293b5f7c873SLiu Gang break; 294b5f7c873SLiu Gang } 295b5f7c873SLiu Gang if (release_addr != 0) { 296b5f7c873SLiu Gang out_be32((void *)release_addr, 297b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); 298b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 299b5f7c873SLiu Gang "Release slave successfully! Now the slave should start up!\n"); 300b5f7c873SLiu Gang } else { 301b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 302b5f7c873SLiu Gang "Release slave failed!\n"); 303b5f7c873SLiu Gang } 304b5f7c873SLiu Gang } 305b5f7c873SLiu Gang #endif 306b5f7c873SLiu Gang 307213ac73eSPeter Tyser void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info) 30893a686eeSJean-Christophe PLAGNIOL-VILLARD { 309213ac73eSPeter Tyser u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr; 310213ac73eSPeter Tyser u32 cfg_data = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_data; 31193a686eeSJean-Christophe PLAGNIOL-VILLARD u16 temp16; 31293a686eeSJean-Christophe PLAGNIOL-VILLARD u32 temp32; 313b6ccd2c9SPrabhakar Kushwaha u32 block_rev; 3148295b944SKumar Gala int enabled, r, inbound = 0; 31593a686eeSJean-Christophe PLAGNIOL-VILLARD u16 ltssm; 3168295b944SKumar Gala u8 temp8, pcie_cap; 317fb3143b3SKumar Gala volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr; 318cb151aa2SKumar Gala struct pci_region *reg = hose->regions + hose->region_count; 3198295b944SKumar Gala pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 32093a686eeSJean-Christophe PLAGNIOL-VILLARD 32193a686eeSJean-Christophe PLAGNIOL-VILLARD /* Initialize ATMU registers based on hose regions and flags */ 32293a686eeSJean-Christophe PLAGNIOL-VILLARD volatile pot_t *po = &pci->pot[1]; /* skip 0 */ 323b6ccd2c9SPrabhakar Kushwaha volatile pit_t *pi; 324ad19e7a5SKumar Gala 325ad19e7a5SKumar Gala u64 out_hi = 0, out_lo = -1ULL; 326ad19e7a5SKumar Gala u32 pcicsrbar, pcicsrbar_sz; 32793a686eeSJean-Christophe PLAGNIOL-VILLARD 328fb3143b3SKumar Gala pci_setup_indirect(hose, cfg_addr, cfg_data); 329fb3143b3SKumar Gala 330b6ccd2c9SPrabhakar Kushwaha block_rev = in_be32(&pci->block_rev1); 331b6ccd2c9SPrabhakar Kushwaha if (PEX_IP_BLK_REV_2_2 <= block_rev) { 332b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[2]; /* 0xDC0 */ 333b6ccd2c9SPrabhakar Kushwaha } else { 334b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[3]; /* 0xDE0 */ 335b6ccd2c9SPrabhakar Kushwaha } 336b6ccd2c9SPrabhakar Kushwaha 337ad19e7a5SKumar Gala /* Handle setup of outbound windows first */ 33893a686eeSJean-Christophe PLAGNIOL-VILLARD for (r = 0; r < hose->region_count; r++) { 339ad19e7a5SKumar Gala unsigned long flags = hose->regions[r].flags; 340612ea010SKumar Gala u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1); 341ad19e7a5SKumar Gala 342ad19e7a5SKumar Gala flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE; 343ad19e7a5SKumar Gala if (flags != PCI_REGION_SYS_MEMORY) { 344ad19e7a5SKumar Gala u64 start = hose->regions[r].bus_start; 345ad19e7a5SKumar Gala u64 end = start + hose->regions[r].size; 346ad19e7a5SKumar Gala 347ad19e7a5SKumar Gala out_be32(&po->powbar, hose->regions[r].phys_start >> 12); 348ad19e7a5SKumar Gala out_be32(&po->potar, start >> 12); 349612ea010SKumar Gala #ifdef CONFIG_SYS_PCI_64BIT 350ad19e7a5SKumar Gala out_be32(&po->potear, start >> 44); 351612ea010SKumar Gala #else 352ad19e7a5SKumar Gala out_be32(&po->potear, 0); 353612ea010SKumar Gala #endif 354ad19e7a5SKumar Gala if (hose->regions[r].flags & PCI_REGION_IO) { 355ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 356ad19e7a5SKumar Gala POWAR_IO_READ | POWAR_IO_WRITE); 357ad19e7a5SKumar Gala } else { 358ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 359ad19e7a5SKumar Gala POWAR_MEM_READ | POWAR_MEM_WRITE); 360ad19e7a5SKumar Gala out_lo = min(start, out_lo); 361ad19e7a5SKumar Gala out_hi = max(end, out_hi); 362ad19e7a5SKumar Gala } 36393a686eeSJean-Christophe PLAGNIOL-VILLARD po++; 36493a686eeSJean-Christophe PLAGNIOL-VILLARD } 36593a686eeSJean-Christophe PLAGNIOL-VILLARD } 366ad19e7a5SKumar Gala debug("Outbound memory range: %llx:%llx\n", out_lo, out_hi); 367ad19e7a5SKumar Gala 368ad19e7a5SKumar Gala /* setup PCSRBAR/PEXCSRBAR */ 369ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff); 370ad19e7a5SKumar Gala pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pcicsrbar_sz); 371ad19e7a5SKumar Gala pcicsrbar_sz = ~pcicsrbar_sz + 1; 372ad19e7a5SKumar Gala 373ad19e7a5SKumar Gala if (out_hi < (0x100000000ull - pcicsrbar_sz) || 374ad19e7a5SKumar Gala (out_lo > 0x100000000ull)) 375ad19e7a5SKumar Gala pcicsrbar = 0x100000000ull - pcicsrbar_sz; 376ad19e7a5SKumar Gala else 377ad19e7a5SKumar Gala pcicsrbar = (out_lo - pcicsrbar_sz) & -pcicsrbar_sz; 378ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, pcicsrbar); 379ad19e7a5SKumar Gala 380ad19e7a5SKumar Gala out_lo = min(out_lo, (u64)pcicsrbar); 381ad19e7a5SKumar Gala 382ad19e7a5SKumar Gala debug("PCICSRBAR @ 0x%x\n", pcicsrbar); 383ad19e7a5SKumar Gala 384ad19e7a5SKumar Gala pci_set_region(reg++, pcicsrbar, CONFIG_SYS_CCSRBAR_PHYS, 385ad19e7a5SKumar Gala pcicsrbar_sz, PCI_REGION_SYS_MEMORY); 386ad19e7a5SKumar Gala hose->region_count++; 38793a686eeSJean-Christophe PLAGNIOL-VILLARD 3888295b944SKumar Gala /* see if we are a PCIe or PCI controller */ 3898295b944SKumar Gala pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 3908295b944SKumar Gala 391*19e4a009SLiu Gang #ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER 392b5f7c873SLiu Gang /* boot from PCIE --master */ 393b5f7c873SLiu Gang char *s = getenv("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 */ 42893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_dword(hose, dev, PCI_DCR, &temp32); 42993a686eeSJean-Christophe PLAGNIOL-VILLARD temp32 |= 0xf000e; /* set URR, FER, NFER (but not CER) */ 43093a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_dword(hose, dev, PCI_DCR, temp32); 43193a686eeSJean-Christophe PLAGNIOL-VILLARD 432b03a466dSPrabhakar Kushwaha #if defined(CONFIG_FSL_PCIE_DISABLE_ASPM) 433b03a466dSPrabhakar Kushwaha temp32 = 0; 434b03a466dSPrabhakar Kushwaha pci_hose_read_config_dword(hose, dev, PCI_LCR, &temp32); 435b03a466dSPrabhakar Kushwaha temp32 &= ~0x03; /* Disable ASPM */ 436b03a466dSPrabhakar Kushwaha pci_hose_write_config_dword(hose, dev, PCI_LCR, temp32); 437b03a466dSPrabhakar Kushwaha udelay(1); 438b03a466dSPrabhakar Kushwaha #endif 4398295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 44093a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); 44193a686eeSJean-Christophe PLAGNIOL-VILLARD enabled = ltssm >= PCI_LTSSM_L0; 44293a686eeSJean-Christophe PLAGNIOL-VILLARD 4438ff3de61SKumar Gala #ifdef CONFIG_FSL_PCIE_RESET 4448ff3de61SKumar Gala if (ltssm == 1) { 4458ff3de61SKumar Gala int i; 446ad19e7a5SKumar Gala debug("....PCIe link error. " "LTSSM=0x%02x.", ltssm); 447ad19e7a5SKumar Gala /* assert PCIe reset */ 448ad19e7a5SKumar Gala setbits_be32(&pci->pdb_stat, 0x08000000); 449ad19e7a5SKumar Gala (void) in_be32(&pci->pdb_stat); 4508ff3de61SKumar Gala udelay(100); 451d015df8fSMarek Vasut debug(" Asserting PCIe reset @%p = %x\n", 452ad19e7a5SKumar Gala &pci->pdb_stat, in_be32(&pci->pdb_stat)); 453ad19e7a5SKumar Gala /* clear PCIe reset */ 454ad19e7a5SKumar Gala clrbits_be32(&pci->pdb_stat, 0x08000000); 4558ff3de61SKumar Gala asm("sync;isync"); 4568ff3de61SKumar Gala for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) { 4578ff3de61SKumar Gala pci_hose_read_config_word(hose, dev, PCI_LTSSM, 4588ff3de61SKumar Gala <ssm); 4598ff3de61SKumar Gala udelay(1000); 4608ff3de61SKumar Gala debug("....PCIe link error. " 4618ff3de61SKumar Gala "LTSSM=0x%02x.\n", ltssm); 4628ff3de61SKumar Gala } 4638ff3de61SKumar Gala enabled = ltssm >= PCI_LTSSM_L0; 464ad19e7a5SKumar Gala 465ad19e7a5SKumar Gala /* we need to re-write the bar0 since a reset will 466ad19e7a5SKumar Gala * clear it 467ad19e7a5SKumar Gala */ 468ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, 469ad19e7a5SKumar Gala PCI_BASE_ADDRESS_0, pcicsrbar); 4708ff3de61SKumar Gala } 4718ff3de61SKumar Gala #endif 4728ff3de61SKumar Gala 47393a686eeSJean-Christophe PLAGNIOL-VILLARD if (!enabled) { 474213ac73eSPeter Tyser /* Let the user know there's no PCIe link */ 475213ac73eSPeter Tyser printf("no link, regs @ 0x%lx\n", pci_info->regs); 47693a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->first_busno; 47793a686eeSJean-Christophe PLAGNIOL-VILLARD return; 47893a686eeSJean-Christophe PLAGNIOL-VILLARD } 47993a686eeSJean-Christophe PLAGNIOL-VILLARD 480ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 481ad19e7a5SKumar Gala out_be32(&pci->pme_msg_int_en, 0xffffffff); 482213ac73eSPeter Tyser 483213ac73eSPeter Tyser /* Print the negotiated PCIe link width */ 48493a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16); 485213ac73eSPeter Tyser printf("x%d, regs @ 0x%lx\n", (temp16 & 0x3f0 ) >> 4, 486213ac73eSPeter Tyser pci_info->regs); 487213ac73eSPeter Tyser 48893a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno++; /* Start scan with secondary */ 48993a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); 49093a686eeSJean-Christophe PLAGNIOL-VILLARD } 49193a686eeSJean-Christophe PLAGNIOL-VILLARD 49293a686eeSJean-Christophe PLAGNIOL-VILLARD /* Use generic setup_device to initialize standard pci regs, 49393a686eeSJean-Christophe PLAGNIOL-VILLARD * but do not allocate any windows since any BAR found (such 49493a686eeSJean-Christophe PLAGNIOL-VILLARD * as PCSRBAR) is not in this cpu's memory space. 49593a686eeSJean-Christophe PLAGNIOL-VILLARD */ 49693a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_setup_device(hose, dev, 0, hose->pci_mem, 49793a686eeSJean-Christophe PLAGNIOL-VILLARD hose->pci_prefetch, hose->pci_io); 49893a686eeSJean-Christophe PLAGNIOL-VILLARD 49993a686eeSJean-Christophe PLAGNIOL-VILLARD if (inbound) { 50093a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_COMMAND, &temp16); 50193a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_COMMAND, 50293a686eeSJean-Christophe PLAGNIOL-VILLARD temp16 | PCI_COMMAND_MEMORY); 50393a686eeSJean-Christophe PLAGNIOL-VILLARD } 50493a686eeSJean-Christophe PLAGNIOL-VILLARD 50593a686eeSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_PCI_NOSCAN 506505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) { 50737d03fceSPeter Tyser debug(" Scanning PCI bus %02x\n", 5086df0efd5SEd Swarthout hose->current_busno); 50993a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = pci_hose_scan_bus(hose, hose->current_busno); 5106df0efd5SEd Swarthout } else { 5116df0efd5SEd Swarthout debug(" Not scanning PCI bus %02x. PI=%x\n", 5126df0efd5SEd Swarthout hose->current_busno, temp8); 5136df0efd5SEd Swarthout hose->last_busno = hose->current_busno; 5146df0efd5SEd Swarthout } 51593a686eeSJean-Christophe PLAGNIOL-VILLARD 5168295b944SKumar Gala /* if we are PCIe - update limit regs and subordinate busno 5178295b944SKumar Gala * for the virtual P2P bridge 5188295b944SKumar Gala */ 5198295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 52093a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_postscan_setup_bridge(hose, dev, hose->last_busno); 52193a686eeSJean-Christophe PLAGNIOL-VILLARD } 52293a686eeSJean-Christophe PLAGNIOL-VILLARD #else 52393a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->current_busno; 52493a686eeSJean-Christophe PLAGNIOL-VILLARD #endif 52593a686eeSJean-Christophe PLAGNIOL-VILLARD 52693a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear all error indications */ 5278295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) 528ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 529ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); 53093a686eeSJean-Christophe PLAGNIOL-VILLARD 53193a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_DSR, &temp16); 53293a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 5338295b944SKumar Gala pci_hose_write_config_word(hose, dev, PCI_DSR, 0xffff); 53493a686eeSJean-Christophe PLAGNIOL-VILLARD } 53593a686eeSJean-Christophe PLAGNIOL-VILLARD 53693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16); 53793a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 53893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff); 53993a686eeSJean-Christophe PLAGNIOL-VILLARD } 54093a686eeSJean-Christophe PLAGNIOL-VILLARD } 541a2aab460SKumar Gala 542715d8f76SEd Swarthout int fsl_is_pci_agent(struct pci_controller *hose) 543715d8f76SEd Swarthout { 544505f3e6fSMinghuan Lian u8 pcie_cap; 545715d8f76SEd Swarthout pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 546715d8f76SEd Swarthout 547505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 548505f3e6fSMinghuan Lian if (pcie_cap == PCI_CAP_ID_EXP) { 549505f3e6fSMinghuan Lian u8 header_type; 550715d8f76SEd Swarthout 551505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, 552505f3e6fSMinghuan Lian &header_type); 553505f3e6fSMinghuan Lian return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; 554505f3e6fSMinghuan Lian } else { 555505f3e6fSMinghuan Lian u8 prog_if; 556505f3e6fSMinghuan Lian 557505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); 558715d8f76SEd Swarthout return (prog_if == FSL_PROG_IF_AGENT); 559715d8f76SEd Swarthout } 560505f3e6fSMinghuan Lian } 561715d8f76SEd Swarthout 5620d3d68b2SPoonam Aggrwal int fsl_pci_init_port(struct fsl_pci_info *pci_info, 56301471d53SKumar Gala struct pci_controller *hose, int busno) 5640d3d68b2SPoonam Aggrwal { 5650d3d68b2SPoonam Aggrwal volatile ccsr_fsl_pci_t *pci; 5660d3d68b2SPoonam Aggrwal struct pci_region *r; 567a72dbae2SPeter Tyser pci_dev_t dev = PCI_BDF(busno,0,0); 568a72dbae2SPeter Tyser u8 pcie_cap; 5690d3d68b2SPoonam Aggrwal 5700d3d68b2SPoonam Aggrwal pci = (ccsr_fsl_pci_t *) pci_info->regs; 5710d3d68b2SPoonam Aggrwal 5720d3d68b2SPoonam Aggrwal /* on non-PCIe controllers we don't have pme_msg_det so this code 5730d3d68b2SPoonam Aggrwal * should do nothing since the read will return 0 5740d3d68b2SPoonam Aggrwal */ 5750d3d68b2SPoonam Aggrwal if (in_be32(&pci->pme_msg_det)) { 5760d3d68b2SPoonam Aggrwal out_be32(&pci->pme_msg_det, 0xffffffff); 5770d3d68b2SPoonam Aggrwal debug (" with errors. Clearing. Now 0x%08x", 5780d3d68b2SPoonam Aggrwal pci->pme_msg_det); 5790d3d68b2SPoonam Aggrwal } 5800d3d68b2SPoonam Aggrwal 5810d3d68b2SPoonam Aggrwal r = hose->regions + hose->region_count; 5820d3d68b2SPoonam Aggrwal 5830d3d68b2SPoonam Aggrwal /* outbound memory */ 5840d3d68b2SPoonam Aggrwal pci_set_region(r++, 5850d3d68b2SPoonam Aggrwal pci_info->mem_bus, 5860d3d68b2SPoonam Aggrwal pci_info->mem_phys, 5870d3d68b2SPoonam Aggrwal pci_info->mem_size, 5880d3d68b2SPoonam Aggrwal PCI_REGION_MEM); 5890d3d68b2SPoonam Aggrwal 5900d3d68b2SPoonam Aggrwal /* outbound io */ 5910d3d68b2SPoonam Aggrwal pci_set_region(r++, 5920d3d68b2SPoonam Aggrwal pci_info->io_bus, 5930d3d68b2SPoonam Aggrwal pci_info->io_phys, 5940d3d68b2SPoonam Aggrwal pci_info->io_size, 5950d3d68b2SPoonam Aggrwal PCI_REGION_IO); 5960d3d68b2SPoonam Aggrwal 5970d3d68b2SPoonam Aggrwal hose->region_count = r - hose->regions; 5980d3d68b2SPoonam Aggrwal hose->first_busno = busno; 5990d3d68b2SPoonam Aggrwal 600213ac73eSPeter Tyser fsl_pci_init(hose, pci_info); 6010d3d68b2SPoonam Aggrwal 602715d8f76SEd Swarthout if (fsl_is_pci_agent(hose)) { 603715d8f76SEd Swarthout fsl_pci_config_unlock(hose); 604715d8f76SEd Swarthout hose->last_busno = hose->first_busno; 605*19e4a009SLiu Gang #ifdef CONFIG_SYS_FSL_SRIO_PCIE_BOOT_MASTER 606b5f7c873SLiu Gang } else { 607b5f7c873SLiu Gang /* boot from PCIE --master releases slave's core 0 */ 608b5f7c873SLiu Gang char *s = getenv("bootmaster"); 609b5f7c873SLiu Gang char pcie[6]; 610b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 611b5f7c873SLiu Gang 612b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) 613b5f7c873SLiu Gang fsl_pcie_boot_master_release_slave(pci_info->pci_num); 614b5f7c873SLiu Gang #endif 615715d8f76SEd Swarthout } 616715d8f76SEd Swarthout 617a72dbae2SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6188ca78f2cSPeter Tyser printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ? 619213ac73eSPeter Tyser "e" : "", pci_info->pci_num, 6200d3d68b2SPoonam Aggrwal hose->first_busno, hose->last_busno); 6210d3d68b2SPoonam Aggrwal 6220d3d68b2SPoonam Aggrwal return(hose->last_busno + 1); 6230d3d68b2SPoonam Aggrwal } 6240d3d68b2SPoonam Aggrwal 6257a897959SPeter Tyser /* Enable inbound PCI config cycles for agent/endpoint interface */ 6267a897959SPeter Tyser void fsl_pci_config_unlock(struct pci_controller *hose) 6277a897959SPeter Tyser { 6287a897959SPeter Tyser pci_dev_t dev = PCI_BDF(hose->first_busno,0,0); 6297a897959SPeter Tyser u8 pcie_cap; 6307a897959SPeter Tyser u16 pbfr; 6317a897959SPeter Tyser 632505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) 6337a897959SPeter Tyser return; 6347a897959SPeter Tyser 6357a897959SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6367a897959SPeter Tyser if (pcie_cap != 0x0) { 6377a897959SPeter Tyser /* PCIe - set CFG_READY bit of Configuration Ready Register */ 6387a897959SPeter Tyser pci_hose_write_config_byte(hose, dev, FSL_PCIE_CFG_RDY, 0x1); 6397a897959SPeter Tyser } else { 6407a897959SPeter Tyser /* PCI - clear ACL bit of PBFR */ 6417a897959SPeter Tyser pci_hose_read_config_word(hose, dev, FSL_PCI_PBFR, &pbfr); 6427a897959SPeter Tyser pbfr &= ~0x20; 6437a897959SPeter Tyser pci_hose_write_config_word(hose, dev, FSL_PCI_PBFR, pbfr); 6447a897959SPeter Tyser } 6457a897959SPeter Tyser } 6467a897959SPeter Tyser 647a4aafcc9SKumar Gala #if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \ 648a4aafcc9SKumar Gala defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) 649a4aafcc9SKumar Gala int fsl_configure_pcie(struct fsl_pci_info *info, 650a4aafcc9SKumar Gala struct pci_controller *hose, 651a4aafcc9SKumar Gala const char *connected, int busno) 652a4aafcc9SKumar Gala { 653a4aafcc9SKumar Gala int is_endpoint; 654a4aafcc9SKumar Gala 655a4aafcc9SKumar Gala set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); 656a4aafcc9SKumar Gala set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); 657213ac73eSPeter Tyser 658a4aafcc9SKumar Gala is_endpoint = fsl_setup_hose(hose, info->regs); 659213ac73eSPeter Tyser printf("PCIe%u: %s", info->pci_num, 660213ac73eSPeter Tyser is_endpoint ? "Endpoint" : "Root Complex"); 661213ac73eSPeter Tyser if (connected) 662213ac73eSPeter Tyser printf(" of %s", connected); 663213ac73eSPeter Tyser puts(", "); 664213ac73eSPeter Tyser 665a4aafcc9SKumar Gala return fsl_pci_init_port(info, hose, busno); 666a4aafcc9SKumar Gala } 667a4aafcc9SKumar Gala 668a4aafcc9SKumar Gala #if defined(CONFIG_FSL_CORENET) 6699e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 6709e758758SYork Sun #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR3_PCIE1 6719e758758SYork Sun #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR3_PCIE2 6729e758758SYork Sun #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR3_PCIE3 6739e758758SYork Sun #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR3_PCIE4 6749e758758SYork Sun #else 675a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1 676a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2 677a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3 678a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4 6799e758758SYork Sun #endif 680a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 681a4aafcc9SKumar Gala #elif defined(CONFIG_MPC85xx) 682a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE 683a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2 684a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3 685a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 686a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 687a4aafcc9SKumar Gala #elif defined(CONFIG_MPC86xx) 688a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1 689a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2 690a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 0 691a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 692a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ 693a4aafcc9SKumar Gala (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) 694a4aafcc9SKumar Gala #else 695a4aafcc9SKumar Gala #error "No defines for DEVDISR_PCIE" 696a4aafcc9SKumar Gala #endif 697a4aafcc9SKumar Gala 698a4aafcc9SKumar Gala /* Implement a dummy function for those platforms w/o SERDES */ 699a4aafcc9SKumar Gala static const char *__board_serdes_name(enum srds_prtcl device) 700a4aafcc9SKumar Gala { 701a4aafcc9SKumar Gala switch (device) { 702a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE1_NAME 703a4aafcc9SKumar Gala case PCIE1: 704a4aafcc9SKumar Gala return CONFIG_SYS_PCIE1_NAME; 705a4aafcc9SKumar Gala #endif 706a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE2_NAME 707a4aafcc9SKumar Gala case PCIE2: 708a4aafcc9SKumar Gala return CONFIG_SYS_PCIE2_NAME; 709a4aafcc9SKumar Gala #endif 710a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE3_NAME 711a4aafcc9SKumar Gala case PCIE3: 712a4aafcc9SKumar Gala return CONFIG_SYS_PCIE3_NAME; 713a4aafcc9SKumar Gala #endif 714a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE4_NAME 715a4aafcc9SKumar Gala case PCIE4: 716a4aafcc9SKumar Gala return CONFIG_SYS_PCIE4_NAME; 717a4aafcc9SKumar Gala #endif 718a4aafcc9SKumar Gala default: 719a4aafcc9SKumar Gala return NULL; 720a4aafcc9SKumar Gala } 721a4aafcc9SKumar Gala 722a4aafcc9SKumar Gala return NULL; 723a4aafcc9SKumar Gala } 724a4aafcc9SKumar Gala 725a4aafcc9SKumar Gala __attribute__((weak, alias("__board_serdes_name"))) const char * 726a4aafcc9SKumar Gala board_serdes_name(enum srds_prtcl device); 727a4aafcc9SKumar Gala 728a4aafcc9SKumar Gala static u32 devdisr_mask[] = { 729a4aafcc9SKumar Gala _DEVDISR_PCIE1, 730a4aafcc9SKumar Gala _DEVDISR_PCIE2, 731a4aafcc9SKumar Gala _DEVDISR_PCIE3, 732a4aafcc9SKumar Gala _DEVDISR_PCIE4, 733a4aafcc9SKumar Gala }; 734a4aafcc9SKumar Gala 735a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 736a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 737a4aafcc9SKumar Gala { 738a4aafcc9SKumar Gala struct pci_controller *hose; 739a4aafcc9SKumar Gala int num = dev - PCIE1; 740a4aafcc9SKumar Gala 741a4aafcc9SKumar Gala hose = calloc(1, sizeof(struct pci_controller)); 742a4aafcc9SKumar Gala if (!hose) 743a4aafcc9SKumar Gala return busno; 744a4aafcc9SKumar Gala 745a4aafcc9SKumar Gala if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) { 746a4aafcc9SKumar Gala busno = fsl_configure_pcie(pci_info, hose, 747a4aafcc9SKumar Gala board_serdes_name(dev), busno); 748a4aafcc9SKumar Gala } else { 749213ac73eSPeter Tyser printf("PCIe%d: disabled\n", num + 1); 750a4aafcc9SKumar Gala } 751a4aafcc9SKumar Gala 752a4aafcc9SKumar Gala return busno; 753a4aafcc9SKumar Gala } 754a4aafcc9SKumar Gala 755a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 756a4aafcc9SKumar Gala { 757a4aafcc9SKumar Gala struct fsl_pci_info pci_info; 758a4aafcc9SKumar Gala ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; 7599e758758SYork Sun u32 devdisr; 7609e758758SYork Sun u32 *addr; 7619e758758SYork Sun 7629e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 7639e758758SYork Sun addr = &gur->devdisr3; 7649e758758SYork Sun #else 7659e758758SYork Sun addr = &gur->devdisr; 7669e758758SYork Sun #endif 7679e758758SYork Sun devdisr = in_be32(addr); 768a4aafcc9SKumar Gala 769a4aafcc9SKumar Gala #ifdef CONFIG_PCIE1 770a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 1); 771a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info); 772a4aafcc9SKumar Gala #else 7739e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE1); /* disable */ 774a4aafcc9SKumar Gala #endif 775a4aafcc9SKumar Gala 776a4aafcc9SKumar Gala #ifdef CONFIG_PCIE2 777a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 2); 778a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info); 779a4aafcc9SKumar Gala #else 7809e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE2); /* disable */ 781a4aafcc9SKumar Gala #endif 782a4aafcc9SKumar Gala 783a4aafcc9SKumar Gala #ifdef CONFIG_PCIE3 784a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 3); 785a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info); 786a4aafcc9SKumar Gala #else 7879e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE3); /* disable */ 788a4aafcc9SKumar Gala #endif 789a4aafcc9SKumar Gala 790a4aafcc9SKumar Gala #ifdef CONFIG_PCIE4 791a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 4); 792a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info); 793a4aafcc9SKumar Gala #else 7949e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE4); /* disable */ 795a4aafcc9SKumar Gala #endif 796a4aafcc9SKumar Gala 797a4aafcc9SKumar Gala return busno; 798a4aafcc9SKumar Gala } 799a4aafcc9SKumar Gala #else 800a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 801a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 802a4aafcc9SKumar Gala { 803a4aafcc9SKumar Gala return busno; 804a4aafcc9SKumar Gala } 805a4aafcc9SKumar Gala 806a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 807a4aafcc9SKumar Gala { 808a4aafcc9SKumar Gala return busno; 809a4aafcc9SKumar Gala } 810a4aafcc9SKumar Gala #endif 811a4aafcc9SKumar Gala 812a2aab460SKumar Gala #ifdef CONFIG_OF_BOARD_SETUP 813a2aab460SKumar Gala #include <libfdt.h> 814a2aab460SKumar Gala #include <fdt_support.h> 815a2aab460SKumar Gala 8166525d51fSKumar Gala void ft_fsl_pci_setup(void *blob, const char *pci_compat, 8173a0e3c27SKumar Gala unsigned long ctrl_addr) 818a2aab460SKumar Gala { 8196525d51fSKumar Gala int off; 820a2aab460SKumar Gala u32 bus_range[2]; 8216525d51fSKumar Gala phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr; 8223a0e3c27SKumar Gala struct pci_controller *hose; 8233a0e3c27SKumar Gala 8243a0e3c27SKumar Gala hose = find_hose_by_cfg_addr((void *)(ctrl_addr)); 8256525d51fSKumar Gala 8266525d51fSKumar Gala /* convert ctrl_addr to true physical address */ 8276525d51fSKumar Gala p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR; 8286525d51fSKumar Gala p_ctrl_addr += CONFIG_SYS_CCSRBAR_PHYS; 8296525d51fSKumar Gala 8306525d51fSKumar Gala off = fdt_node_offset_by_compat_reg(blob, pci_compat, p_ctrl_addr); 831a2aab460SKumar Gala 8325a85a309SKumar Gala if (off < 0) 8335a85a309SKumar Gala return; 8345a85a309SKumar Gala 8355a85a309SKumar Gala /* We assume a cfg_addr not being set means we didn't setup the controller */ 8365a85a309SKumar Gala if ((hose == NULL) || (hose->cfg_addr == NULL)) { 8376525d51fSKumar Gala fdt_del_node(blob, off); 8385a85a309SKumar Gala } else { 839a2aab460SKumar Gala bus_range[0] = 0; 840a2aab460SKumar Gala bus_range[1] = hose->last_busno - hose->first_busno; 841a2aab460SKumar Gala fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4); 842a2aab460SKumar Gala fdt_pci_dma_ranges(blob, off, hose); 843a2aab460SKumar Gala } 844a2aab460SKumar Gala } 845a2aab460SKumar Gala #endif 846