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*c8b28152SLiu Gang #ifdef CONFIG_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*c8b28152SLiu Gang #ifdef CONFIG_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 473c0a4e6b8SYuanquan Chen #ifdef CONFIG_SYS_P4080_ERRATUM_PCIE_A003 474c0a4e6b8SYuanquan Chen if (enabled == 0) { 475c0a4e6b8SYuanquan Chen serdes_corenet_t *srds_regs = (void *)CONFIG_SYS_FSL_CORENET_SERDES_ADDR; 476c0a4e6b8SYuanquan Chen temp32 = in_be32(&srds_regs->srdspccr0); 477c0a4e6b8SYuanquan Chen 478c0a4e6b8SYuanquan Chen if ((temp32 >> 28) == 3) { 479c0a4e6b8SYuanquan Chen int i; 480c0a4e6b8SYuanquan Chen 481c0a4e6b8SYuanquan Chen out_be32(&srds_regs->srdspccr0, 2 << 28); 482c0a4e6b8SYuanquan Chen setbits_be32(&pci->pdb_stat, 0x08000000); 483c0a4e6b8SYuanquan Chen in_be32(&pci->pdb_stat); 484c0a4e6b8SYuanquan Chen udelay(100); 485c0a4e6b8SYuanquan Chen clrbits_be32(&pci->pdb_stat, 0x08000000); 486c0a4e6b8SYuanquan Chen asm("sync;isync"); 487c0a4e6b8SYuanquan Chen for (i=0; i < 100 && ltssm < PCI_LTSSM_L0; i++) { 488c0a4e6b8SYuanquan Chen pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); 489c0a4e6b8SYuanquan Chen udelay(1000); 490c0a4e6b8SYuanquan Chen } 491c0a4e6b8SYuanquan Chen enabled = ltssm >= PCI_LTSSM_L0; 492c0a4e6b8SYuanquan Chen } 493c0a4e6b8SYuanquan Chen } 494c0a4e6b8SYuanquan Chen #endif 49593a686eeSJean-Christophe PLAGNIOL-VILLARD if (!enabled) { 496213ac73eSPeter Tyser /* Let the user know there's no PCIe link */ 497213ac73eSPeter Tyser printf("no link, regs @ 0x%lx\n", pci_info->regs); 49893a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->first_busno; 49993a686eeSJean-Christophe PLAGNIOL-VILLARD return; 50093a686eeSJean-Christophe PLAGNIOL-VILLARD } 50193a686eeSJean-Christophe PLAGNIOL-VILLARD 502ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 503ad19e7a5SKumar Gala out_be32(&pci->pme_msg_int_en, 0xffffffff); 504213ac73eSPeter Tyser 505213ac73eSPeter Tyser /* Print the negotiated PCIe link width */ 50693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16); 507213ac73eSPeter Tyser printf("x%d, regs @ 0x%lx\n", (temp16 & 0x3f0 ) >> 4, 508213ac73eSPeter Tyser pci_info->regs); 509213ac73eSPeter Tyser 51093a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno++; /* Start scan with secondary */ 51193a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); 51293a686eeSJean-Christophe PLAGNIOL-VILLARD } 51393a686eeSJean-Christophe PLAGNIOL-VILLARD 51493a686eeSJean-Christophe PLAGNIOL-VILLARD /* Use generic setup_device to initialize standard pci regs, 51593a686eeSJean-Christophe PLAGNIOL-VILLARD * but do not allocate any windows since any BAR found (such 51693a686eeSJean-Christophe PLAGNIOL-VILLARD * as PCSRBAR) is not in this cpu's memory space. 51793a686eeSJean-Christophe PLAGNIOL-VILLARD */ 51893a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_setup_device(hose, dev, 0, hose->pci_mem, 51993a686eeSJean-Christophe PLAGNIOL-VILLARD hose->pci_prefetch, hose->pci_io); 52093a686eeSJean-Christophe PLAGNIOL-VILLARD 52193a686eeSJean-Christophe PLAGNIOL-VILLARD if (inbound) { 52293a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_COMMAND, &temp16); 52393a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_COMMAND, 52493a686eeSJean-Christophe PLAGNIOL-VILLARD temp16 | PCI_COMMAND_MEMORY); 52593a686eeSJean-Christophe PLAGNIOL-VILLARD } 52693a686eeSJean-Christophe PLAGNIOL-VILLARD 52793a686eeSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_PCI_NOSCAN 528505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) { 52937d03fceSPeter Tyser debug(" Scanning PCI bus %02x\n", 5306df0efd5SEd Swarthout hose->current_busno); 53193a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = pci_hose_scan_bus(hose, hose->current_busno); 5326df0efd5SEd Swarthout } else { 5336df0efd5SEd Swarthout debug(" Not scanning PCI bus %02x. PI=%x\n", 5346df0efd5SEd Swarthout hose->current_busno, temp8); 5356df0efd5SEd Swarthout hose->last_busno = hose->current_busno; 5366df0efd5SEd Swarthout } 53793a686eeSJean-Christophe PLAGNIOL-VILLARD 5388295b944SKumar Gala /* if we are PCIe - update limit regs and subordinate busno 5398295b944SKumar Gala * for the virtual P2P bridge 5408295b944SKumar Gala */ 5418295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 54293a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_postscan_setup_bridge(hose, dev, hose->last_busno); 54393a686eeSJean-Christophe PLAGNIOL-VILLARD } 54493a686eeSJean-Christophe PLAGNIOL-VILLARD #else 54593a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->current_busno; 54693a686eeSJean-Christophe PLAGNIOL-VILLARD #endif 54793a686eeSJean-Christophe PLAGNIOL-VILLARD 54893a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear all error indications */ 5498295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) 550ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 551ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); 55293a686eeSJean-Christophe PLAGNIOL-VILLARD 55393a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_DSR, &temp16); 55493a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 5558295b944SKumar Gala pci_hose_write_config_word(hose, dev, PCI_DSR, 0xffff); 55693a686eeSJean-Christophe PLAGNIOL-VILLARD } 55793a686eeSJean-Christophe PLAGNIOL-VILLARD 55893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16); 55993a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 56093a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff); 56193a686eeSJean-Christophe PLAGNIOL-VILLARD } 56293a686eeSJean-Christophe PLAGNIOL-VILLARD } 563a2aab460SKumar Gala 564715d8f76SEd Swarthout int fsl_is_pci_agent(struct pci_controller *hose) 565715d8f76SEd Swarthout { 566505f3e6fSMinghuan Lian u8 pcie_cap; 567715d8f76SEd Swarthout pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 568715d8f76SEd Swarthout 569505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 570505f3e6fSMinghuan Lian if (pcie_cap == PCI_CAP_ID_EXP) { 571505f3e6fSMinghuan Lian u8 header_type; 572715d8f76SEd Swarthout 573505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, 574505f3e6fSMinghuan Lian &header_type); 575505f3e6fSMinghuan Lian return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; 576505f3e6fSMinghuan Lian } else { 577505f3e6fSMinghuan Lian u8 prog_if; 578505f3e6fSMinghuan Lian 579505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); 580715d8f76SEd Swarthout return (prog_if == FSL_PROG_IF_AGENT); 581715d8f76SEd Swarthout } 582505f3e6fSMinghuan Lian } 583715d8f76SEd Swarthout 5840d3d68b2SPoonam Aggrwal int fsl_pci_init_port(struct fsl_pci_info *pci_info, 58501471d53SKumar Gala struct pci_controller *hose, int busno) 5860d3d68b2SPoonam Aggrwal { 5870d3d68b2SPoonam Aggrwal volatile ccsr_fsl_pci_t *pci; 5880d3d68b2SPoonam Aggrwal struct pci_region *r; 589a72dbae2SPeter Tyser pci_dev_t dev = PCI_BDF(busno,0,0); 590a72dbae2SPeter Tyser u8 pcie_cap; 5910d3d68b2SPoonam Aggrwal 5920d3d68b2SPoonam Aggrwal pci = (ccsr_fsl_pci_t *) pci_info->regs; 5930d3d68b2SPoonam Aggrwal 5940d3d68b2SPoonam Aggrwal /* on non-PCIe controllers we don't have pme_msg_det so this code 5950d3d68b2SPoonam Aggrwal * should do nothing since the read will return 0 5960d3d68b2SPoonam Aggrwal */ 5970d3d68b2SPoonam Aggrwal if (in_be32(&pci->pme_msg_det)) { 5980d3d68b2SPoonam Aggrwal out_be32(&pci->pme_msg_det, 0xffffffff); 5990d3d68b2SPoonam Aggrwal debug (" with errors. Clearing. Now 0x%08x", 6000d3d68b2SPoonam Aggrwal pci->pme_msg_det); 6010d3d68b2SPoonam Aggrwal } 6020d3d68b2SPoonam Aggrwal 6030d3d68b2SPoonam Aggrwal r = hose->regions + hose->region_count; 6040d3d68b2SPoonam Aggrwal 6050d3d68b2SPoonam Aggrwal /* outbound memory */ 6060d3d68b2SPoonam Aggrwal pci_set_region(r++, 6070d3d68b2SPoonam Aggrwal pci_info->mem_bus, 6080d3d68b2SPoonam Aggrwal pci_info->mem_phys, 6090d3d68b2SPoonam Aggrwal pci_info->mem_size, 6100d3d68b2SPoonam Aggrwal PCI_REGION_MEM); 6110d3d68b2SPoonam Aggrwal 6120d3d68b2SPoonam Aggrwal /* outbound io */ 6130d3d68b2SPoonam Aggrwal pci_set_region(r++, 6140d3d68b2SPoonam Aggrwal pci_info->io_bus, 6150d3d68b2SPoonam Aggrwal pci_info->io_phys, 6160d3d68b2SPoonam Aggrwal pci_info->io_size, 6170d3d68b2SPoonam Aggrwal PCI_REGION_IO); 6180d3d68b2SPoonam Aggrwal 6190d3d68b2SPoonam Aggrwal hose->region_count = r - hose->regions; 6200d3d68b2SPoonam Aggrwal hose->first_busno = busno; 6210d3d68b2SPoonam Aggrwal 622213ac73eSPeter Tyser fsl_pci_init(hose, pci_info); 6230d3d68b2SPoonam Aggrwal 624715d8f76SEd Swarthout if (fsl_is_pci_agent(hose)) { 625715d8f76SEd Swarthout fsl_pci_config_unlock(hose); 626715d8f76SEd Swarthout hose->last_busno = hose->first_busno; 627*c8b28152SLiu Gang #ifdef CONFIG_SRIO_PCIE_BOOT_MASTER 628b5f7c873SLiu Gang } else { 629b5f7c873SLiu Gang /* boot from PCIE --master releases slave's core 0 */ 630b5f7c873SLiu Gang char *s = getenv("bootmaster"); 631b5f7c873SLiu Gang char pcie[6]; 632b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 633b5f7c873SLiu Gang 634b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) 635b5f7c873SLiu Gang fsl_pcie_boot_master_release_slave(pci_info->pci_num); 636b5f7c873SLiu Gang #endif 637715d8f76SEd Swarthout } 638715d8f76SEd Swarthout 639a72dbae2SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6408ca78f2cSPeter Tyser printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ? 641213ac73eSPeter Tyser "e" : "", pci_info->pci_num, 6420d3d68b2SPoonam Aggrwal hose->first_busno, hose->last_busno); 6430d3d68b2SPoonam Aggrwal 6440d3d68b2SPoonam Aggrwal return(hose->last_busno + 1); 6450d3d68b2SPoonam Aggrwal } 6460d3d68b2SPoonam Aggrwal 6477a897959SPeter Tyser /* Enable inbound PCI config cycles for agent/endpoint interface */ 6487a897959SPeter Tyser void fsl_pci_config_unlock(struct pci_controller *hose) 6497a897959SPeter Tyser { 6507a897959SPeter Tyser pci_dev_t dev = PCI_BDF(hose->first_busno,0,0); 6517a897959SPeter Tyser u8 pcie_cap; 6527a897959SPeter Tyser u16 pbfr; 6537a897959SPeter Tyser 654505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) 6557a897959SPeter Tyser return; 6567a897959SPeter Tyser 6577a897959SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6587a897959SPeter Tyser if (pcie_cap != 0x0) { 6597a897959SPeter Tyser /* PCIe - set CFG_READY bit of Configuration Ready Register */ 6607a897959SPeter Tyser pci_hose_write_config_byte(hose, dev, FSL_PCIE_CFG_RDY, 0x1); 6617a897959SPeter Tyser } else { 6627a897959SPeter Tyser /* PCI - clear ACL bit of PBFR */ 6637a897959SPeter Tyser pci_hose_read_config_word(hose, dev, FSL_PCI_PBFR, &pbfr); 6647a897959SPeter Tyser pbfr &= ~0x20; 6657a897959SPeter Tyser pci_hose_write_config_word(hose, dev, FSL_PCI_PBFR, pbfr); 6667a897959SPeter Tyser } 6677a897959SPeter Tyser } 6687a897959SPeter Tyser 669a4aafcc9SKumar Gala #if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \ 670a4aafcc9SKumar Gala defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) 671a4aafcc9SKumar Gala int fsl_configure_pcie(struct fsl_pci_info *info, 672a4aafcc9SKumar Gala struct pci_controller *hose, 673a4aafcc9SKumar Gala const char *connected, int busno) 674a4aafcc9SKumar Gala { 675a4aafcc9SKumar Gala int is_endpoint; 676a4aafcc9SKumar Gala 677a4aafcc9SKumar Gala set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); 678a4aafcc9SKumar Gala set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); 679213ac73eSPeter Tyser 680a4aafcc9SKumar Gala is_endpoint = fsl_setup_hose(hose, info->regs); 681213ac73eSPeter Tyser printf("PCIe%u: %s", info->pci_num, 682213ac73eSPeter Tyser is_endpoint ? "Endpoint" : "Root Complex"); 683213ac73eSPeter Tyser if (connected) 684213ac73eSPeter Tyser printf(" of %s", connected); 685213ac73eSPeter Tyser puts(", "); 686213ac73eSPeter Tyser 687a4aafcc9SKumar Gala return fsl_pci_init_port(info, hose, busno); 688a4aafcc9SKumar Gala } 689a4aafcc9SKumar Gala 690a4aafcc9SKumar Gala #if defined(CONFIG_FSL_CORENET) 6919e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 6929e758758SYork Sun #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR3_PCIE1 6939e758758SYork Sun #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR3_PCIE2 6949e758758SYork Sun #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR3_PCIE3 6959e758758SYork Sun #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR3_PCIE4 6969e758758SYork Sun #else 697a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1 698a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2 699a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3 700a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4 7019e758758SYork Sun #endif 702a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 703a4aafcc9SKumar Gala #elif defined(CONFIG_MPC85xx) 704a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE 705a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2 706a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3 707a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 708a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 709a4aafcc9SKumar Gala #elif defined(CONFIG_MPC86xx) 710a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1 711a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2 712a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 0 713a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 714a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ 715a4aafcc9SKumar Gala (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) 716a4aafcc9SKumar Gala #else 717a4aafcc9SKumar Gala #error "No defines for DEVDISR_PCIE" 718a4aafcc9SKumar Gala #endif 719a4aafcc9SKumar Gala 720a4aafcc9SKumar Gala /* Implement a dummy function for those platforms w/o SERDES */ 721a4aafcc9SKumar Gala static const char *__board_serdes_name(enum srds_prtcl device) 722a4aafcc9SKumar Gala { 723a4aafcc9SKumar Gala switch (device) { 724a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE1_NAME 725a4aafcc9SKumar Gala case PCIE1: 726a4aafcc9SKumar Gala return CONFIG_SYS_PCIE1_NAME; 727a4aafcc9SKumar Gala #endif 728a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE2_NAME 729a4aafcc9SKumar Gala case PCIE2: 730a4aafcc9SKumar Gala return CONFIG_SYS_PCIE2_NAME; 731a4aafcc9SKumar Gala #endif 732a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE3_NAME 733a4aafcc9SKumar Gala case PCIE3: 734a4aafcc9SKumar Gala return CONFIG_SYS_PCIE3_NAME; 735a4aafcc9SKumar Gala #endif 736a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE4_NAME 737a4aafcc9SKumar Gala case PCIE4: 738a4aafcc9SKumar Gala return CONFIG_SYS_PCIE4_NAME; 739a4aafcc9SKumar Gala #endif 740a4aafcc9SKumar Gala default: 741a4aafcc9SKumar Gala return NULL; 742a4aafcc9SKumar Gala } 743a4aafcc9SKumar Gala 744a4aafcc9SKumar Gala return NULL; 745a4aafcc9SKumar Gala } 746a4aafcc9SKumar Gala 747a4aafcc9SKumar Gala __attribute__((weak, alias("__board_serdes_name"))) const char * 748a4aafcc9SKumar Gala board_serdes_name(enum srds_prtcl device); 749a4aafcc9SKumar Gala 750a4aafcc9SKumar Gala static u32 devdisr_mask[] = { 751a4aafcc9SKumar Gala _DEVDISR_PCIE1, 752a4aafcc9SKumar Gala _DEVDISR_PCIE2, 753a4aafcc9SKumar Gala _DEVDISR_PCIE3, 754a4aafcc9SKumar Gala _DEVDISR_PCIE4, 755a4aafcc9SKumar Gala }; 756a4aafcc9SKumar Gala 757a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 758a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 759a4aafcc9SKumar Gala { 760a4aafcc9SKumar Gala struct pci_controller *hose; 761a4aafcc9SKumar Gala int num = dev - PCIE1; 762a4aafcc9SKumar Gala 763a4aafcc9SKumar Gala hose = calloc(1, sizeof(struct pci_controller)); 764a4aafcc9SKumar Gala if (!hose) 765a4aafcc9SKumar Gala return busno; 766a4aafcc9SKumar Gala 767a4aafcc9SKumar Gala if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) { 768a4aafcc9SKumar Gala busno = fsl_configure_pcie(pci_info, hose, 769a4aafcc9SKumar Gala board_serdes_name(dev), busno); 770a4aafcc9SKumar Gala } else { 771213ac73eSPeter Tyser printf("PCIe%d: disabled\n", num + 1); 772a4aafcc9SKumar Gala } 773a4aafcc9SKumar Gala 774a4aafcc9SKumar Gala return busno; 775a4aafcc9SKumar Gala } 776a4aafcc9SKumar Gala 777a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 778a4aafcc9SKumar Gala { 779a4aafcc9SKumar Gala struct fsl_pci_info pci_info; 780a4aafcc9SKumar Gala ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; 7819e758758SYork Sun u32 devdisr; 7829e758758SYork Sun u32 *addr; 7839e758758SYork Sun 7849e758758SYork Sun #ifdef CONFIG_SYS_FSL_QORIQ_CHASSIS2 7859e758758SYork Sun addr = &gur->devdisr3; 7869e758758SYork Sun #else 7879e758758SYork Sun addr = &gur->devdisr; 7889e758758SYork Sun #endif 7899e758758SYork Sun devdisr = in_be32(addr); 790a4aafcc9SKumar Gala 791a4aafcc9SKumar Gala #ifdef CONFIG_PCIE1 792a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 1); 793a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info); 794a4aafcc9SKumar Gala #else 7959e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE1); /* disable */ 796a4aafcc9SKumar Gala #endif 797a4aafcc9SKumar Gala 798a4aafcc9SKumar Gala #ifdef CONFIG_PCIE2 799a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 2); 800a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info); 801a4aafcc9SKumar Gala #else 8029e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE2); /* disable */ 803a4aafcc9SKumar Gala #endif 804a4aafcc9SKumar Gala 805a4aafcc9SKumar Gala #ifdef CONFIG_PCIE3 806a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 3); 807a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info); 808a4aafcc9SKumar Gala #else 8099e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE3); /* disable */ 810a4aafcc9SKumar Gala #endif 811a4aafcc9SKumar Gala 812a4aafcc9SKumar Gala #ifdef CONFIG_PCIE4 813a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 4); 814a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info); 815a4aafcc9SKumar Gala #else 8169e758758SYork Sun setbits_be32(addr, _DEVDISR_PCIE4); /* disable */ 817a4aafcc9SKumar Gala #endif 818a4aafcc9SKumar Gala 819a4aafcc9SKumar Gala return busno; 820a4aafcc9SKumar Gala } 821a4aafcc9SKumar Gala #else 822a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 823a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 824a4aafcc9SKumar Gala { 825a4aafcc9SKumar Gala return busno; 826a4aafcc9SKumar Gala } 827a4aafcc9SKumar Gala 828a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 829a4aafcc9SKumar Gala { 830a4aafcc9SKumar Gala return busno; 831a4aafcc9SKumar Gala } 832a4aafcc9SKumar Gala #endif 833a4aafcc9SKumar Gala 834a2aab460SKumar Gala #ifdef CONFIG_OF_BOARD_SETUP 835a2aab460SKumar Gala #include <libfdt.h> 836a2aab460SKumar Gala #include <fdt_support.h> 837a2aab460SKumar Gala 8386525d51fSKumar Gala void ft_fsl_pci_setup(void *blob, const char *pci_compat, 8393a0e3c27SKumar Gala unsigned long ctrl_addr) 840a2aab460SKumar Gala { 8416525d51fSKumar Gala int off; 842a2aab460SKumar Gala u32 bus_range[2]; 8436525d51fSKumar Gala phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr; 8443a0e3c27SKumar Gala struct pci_controller *hose; 8453a0e3c27SKumar Gala 8463a0e3c27SKumar Gala hose = find_hose_by_cfg_addr((void *)(ctrl_addr)); 8476525d51fSKumar Gala 8486525d51fSKumar Gala /* convert ctrl_addr to true physical address */ 8496525d51fSKumar Gala p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR; 8506525d51fSKumar Gala p_ctrl_addr += CONFIG_SYS_CCSRBAR_PHYS; 8516525d51fSKumar Gala 8526525d51fSKumar Gala off = fdt_node_offset_by_compat_reg(blob, pci_compat, p_ctrl_addr); 853a2aab460SKumar Gala 8545a85a309SKumar Gala if (off < 0) 8555a85a309SKumar Gala return; 8565a85a309SKumar Gala 8575a85a309SKumar Gala /* We assume a cfg_addr not being set means we didn't setup the controller */ 8585a85a309SKumar Gala if ((hose == NULL) || (hose->cfg_addr == NULL)) { 8596525d51fSKumar Gala fdt_del_node(blob, off); 8605a85a309SKumar Gala } else { 861a2aab460SKumar Gala bus_range[0] = 0; 862a2aab460SKumar Gala bus_range[1] = hose->last_busno - hose->first_busno; 863a2aab460SKumar Gala fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4); 864a2aab460SKumar Gala fdt_pci_dma_ranges(blob, off, hose); 865a2aab460SKumar Gala } 866a2aab460SKumar Gala } 867a2aab460SKumar Gala #endif 868