193a686eeSJean-Christophe PLAGNIOL-VILLARD /* 2*505f3e6fSMinghuan 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 214b5f7c873SLiu Gang #ifdef CONFIG_FSL_CORENET 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; 279b5f7c873SLiu Gang case 2: 280b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE2_MEM_VIRT 281b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 282b5f7c873SLiu Gang break; 283b5f7c873SLiu Gang case 3: 284b5f7c873SLiu Gang release_addr = CONFIG_SYS_PCIE3_MEM_VIRT 285b5f7c873SLiu Gang + CONFIG_SRIO_PCIE_BOOT_BRR_OFFSET; 286b5f7c873SLiu Gang break; 287b5f7c873SLiu Gang default: 288b5f7c873SLiu Gang release_addr = 0; 289b5f7c873SLiu Gang break; 290b5f7c873SLiu Gang } 291b5f7c873SLiu Gang if (release_addr != 0) { 292b5f7c873SLiu Gang out_be32((void *)release_addr, 293b5f7c873SLiu Gang CONFIG_SRIO_PCIE_BOOT_RELEASE_MASK); 294b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 295b5f7c873SLiu Gang "Release slave successfully! Now the slave should start up!\n"); 296b5f7c873SLiu Gang } else { 297b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: " 298b5f7c873SLiu Gang "Release slave failed!\n"); 299b5f7c873SLiu Gang } 300b5f7c873SLiu Gang } 301b5f7c873SLiu Gang #endif 302b5f7c873SLiu Gang 303213ac73eSPeter Tyser void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info) 30493a686eeSJean-Christophe PLAGNIOL-VILLARD { 305213ac73eSPeter Tyser u32 cfg_addr = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_addr; 306213ac73eSPeter Tyser u32 cfg_data = (u32)&((ccsr_fsl_pci_t *)pci_info->regs)->cfg_data; 30793a686eeSJean-Christophe PLAGNIOL-VILLARD u16 temp16; 30893a686eeSJean-Christophe PLAGNIOL-VILLARD u32 temp32; 309b6ccd2c9SPrabhakar Kushwaha u32 block_rev; 3108295b944SKumar Gala int enabled, r, inbound = 0; 31193a686eeSJean-Christophe PLAGNIOL-VILLARD u16 ltssm; 3128295b944SKumar Gala u8 temp8, pcie_cap; 313fb3143b3SKumar Gala volatile ccsr_fsl_pci_t *pci = (ccsr_fsl_pci_t *)cfg_addr; 314cb151aa2SKumar Gala struct pci_region *reg = hose->regions + hose->region_count; 3158295b944SKumar Gala pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 31693a686eeSJean-Christophe PLAGNIOL-VILLARD 31793a686eeSJean-Christophe PLAGNIOL-VILLARD /* Initialize ATMU registers based on hose regions and flags */ 31893a686eeSJean-Christophe PLAGNIOL-VILLARD volatile pot_t *po = &pci->pot[1]; /* skip 0 */ 319b6ccd2c9SPrabhakar Kushwaha volatile pit_t *pi; 320ad19e7a5SKumar Gala 321ad19e7a5SKumar Gala u64 out_hi = 0, out_lo = -1ULL; 322ad19e7a5SKumar Gala u32 pcicsrbar, pcicsrbar_sz; 32393a686eeSJean-Christophe PLAGNIOL-VILLARD 324fb3143b3SKumar Gala pci_setup_indirect(hose, cfg_addr, cfg_data); 325fb3143b3SKumar Gala 326b6ccd2c9SPrabhakar Kushwaha block_rev = in_be32(&pci->block_rev1); 327b6ccd2c9SPrabhakar Kushwaha if (PEX_IP_BLK_REV_2_2 <= block_rev) { 328b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[2]; /* 0xDC0 */ 329b6ccd2c9SPrabhakar Kushwaha } else { 330b6ccd2c9SPrabhakar Kushwaha pi = &pci->pit[3]; /* 0xDE0 */ 331b6ccd2c9SPrabhakar Kushwaha } 332b6ccd2c9SPrabhakar Kushwaha 333ad19e7a5SKumar Gala /* Handle setup of outbound windows first */ 33493a686eeSJean-Christophe PLAGNIOL-VILLARD for (r = 0; r < hose->region_count; r++) { 335ad19e7a5SKumar Gala unsigned long flags = hose->regions[r].flags; 336612ea010SKumar Gala u32 sz = (__ilog2_u64((u64)hose->regions[r].size) - 1); 337ad19e7a5SKumar Gala 338ad19e7a5SKumar Gala flags &= PCI_REGION_SYS_MEMORY|PCI_REGION_TYPE; 339ad19e7a5SKumar Gala if (flags != PCI_REGION_SYS_MEMORY) { 340ad19e7a5SKumar Gala u64 start = hose->regions[r].bus_start; 341ad19e7a5SKumar Gala u64 end = start + hose->regions[r].size; 342ad19e7a5SKumar Gala 343ad19e7a5SKumar Gala out_be32(&po->powbar, hose->regions[r].phys_start >> 12); 344ad19e7a5SKumar Gala out_be32(&po->potar, start >> 12); 345612ea010SKumar Gala #ifdef CONFIG_SYS_PCI_64BIT 346ad19e7a5SKumar Gala out_be32(&po->potear, start >> 44); 347612ea010SKumar Gala #else 348ad19e7a5SKumar Gala out_be32(&po->potear, 0); 349612ea010SKumar Gala #endif 350ad19e7a5SKumar Gala if (hose->regions[r].flags & PCI_REGION_IO) { 351ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 352ad19e7a5SKumar Gala POWAR_IO_READ | POWAR_IO_WRITE); 353ad19e7a5SKumar Gala } else { 354ad19e7a5SKumar Gala out_be32(&po->powar, POWAR_EN | sz | 355ad19e7a5SKumar Gala POWAR_MEM_READ | POWAR_MEM_WRITE); 356ad19e7a5SKumar Gala out_lo = min(start, out_lo); 357ad19e7a5SKumar Gala out_hi = max(end, out_hi); 358ad19e7a5SKumar Gala } 35993a686eeSJean-Christophe PLAGNIOL-VILLARD po++; 36093a686eeSJean-Christophe PLAGNIOL-VILLARD } 36193a686eeSJean-Christophe PLAGNIOL-VILLARD } 362ad19e7a5SKumar Gala debug("Outbound memory range: %llx:%llx\n", out_lo, out_hi); 363ad19e7a5SKumar Gala 364ad19e7a5SKumar Gala /* setup PCSRBAR/PEXCSRBAR */ 365ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0xffffffff); 366ad19e7a5SKumar Gala pci_hose_read_config_dword (hose, dev, PCI_BASE_ADDRESS_0, &pcicsrbar_sz); 367ad19e7a5SKumar Gala pcicsrbar_sz = ~pcicsrbar_sz + 1; 368ad19e7a5SKumar Gala 369ad19e7a5SKumar Gala if (out_hi < (0x100000000ull - pcicsrbar_sz) || 370ad19e7a5SKumar Gala (out_lo > 0x100000000ull)) 371ad19e7a5SKumar Gala pcicsrbar = 0x100000000ull - pcicsrbar_sz; 372ad19e7a5SKumar Gala else 373ad19e7a5SKumar Gala pcicsrbar = (out_lo - pcicsrbar_sz) & -pcicsrbar_sz; 374ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, pcicsrbar); 375ad19e7a5SKumar Gala 376ad19e7a5SKumar Gala out_lo = min(out_lo, (u64)pcicsrbar); 377ad19e7a5SKumar Gala 378ad19e7a5SKumar Gala debug("PCICSRBAR @ 0x%x\n", pcicsrbar); 379ad19e7a5SKumar Gala 380ad19e7a5SKumar Gala pci_set_region(reg++, pcicsrbar, CONFIG_SYS_CCSRBAR_PHYS, 381ad19e7a5SKumar Gala pcicsrbar_sz, PCI_REGION_SYS_MEMORY); 382ad19e7a5SKumar Gala hose->region_count++; 38393a686eeSJean-Christophe PLAGNIOL-VILLARD 3848295b944SKumar Gala /* see if we are a PCIe or PCI controller */ 3858295b944SKumar Gala pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 3868295b944SKumar Gala 387b5f7c873SLiu Gang #ifdef CONFIG_FSL_CORENET 388b5f7c873SLiu Gang /* boot from PCIE --master */ 389b5f7c873SLiu Gang char *s = getenv("bootmaster"); 390b5f7c873SLiu Gang char pcie[6]; 391b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 392b5f7c873SLiu Gang 393b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) { 394b5f7c873SLiu Gang debug("PCIEBOOT - MASTER: Master port [ %d ] for pcie boot.\n", 395b5f7c873SLiu Gang pci_info->pci_num); 396b5f7c873SLiu Gang fsl_pcie_boot_master((pit_t *)pi); 397b5f7c873SLiu Gang } else { 398b5f7c873SLiu Gang /* inbound */ 399b5f7c873SLiu Gang inbound = fsl_pci_setup_inbound_windows(hose, 400b5f7c873SLiu Gang out_lo, pcie_cap, pi); 401b5f7c873SLiu Gang } 402b5f7c873SLiu Gang #else 403ad19e7a5SKumar Gala /* inbound */ 404ad19e7a5SKumar Gala inbound = fsl_pci_setup_inbound_windows(hose, out_lo, pcie_cap, pi); 405b5f7c873SLiu Gang #endif 406ad19e7a5SKumar Gala 407ad19e7a5SKumar Gala for (r = 0; r < hose->region_count; r++) 408d015df8fSMarek Vasut debug("PCI reg:%d %016llx:%016llx %016llx %08lx\n", r, 409ad19e7a5SKumar Gala (u64)hose->regions[r].phys_start, 410d015df8fSMarek Vasut (u64)hose->regions[r].bus_start, 411d015df8fSMarek Vasut (u64)hose->regions[r].size, 412ad19e7a5SKumar Gala hose->regions[r].flags); 413ad19e7a5SKumar Gala 41493a686eeSJean-Christophe PLAGNIOL-VILLARD pci_register_hose(hose); 41593a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_config_init(hose); /* grab pci_{mem,prefetch,io} */ 41693a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno = hose->first_busno; 41793a686eeSJean-Christophe PLAGNIOL-VILLARD 418ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); /* Clear any errors */ 41916263087SMike Williams out_be32(&pci->peer, ~0x20140); /* Enable All Error Interrupts except 42093a686eeSJean-Christophe PLAGNIOL-VILLARD * - Master abort (pci) 42193a686eeSJean-Christophe PLAGNIOL-VILLARD * - Master PERR (pci) 42293a686eeSJean-Christophe PLAGNIOL-VILLARD * - ICCA (PCIe) 42393a686eeSJean-Christophe PLAGNIOL-VILLARD */ 42493a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_dword(hose, dev, PCI_DCR, &temp32); 42593a686eeSJean-Christophe PLAGNIOL-VILLARD temp32 |= 0xf000e; /* set URR, FER, NFER (but not CER) */ 42693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_dword(hose, dev, PCI_DCR, temp32); 42793a686eeSJean-Christophe PLAGNIOL-VILLARD 428b03a466dSPrabhakar Kushwaha #if defined(CONFIG_FSL_PCIE_DISABLE_ASPM) 429b03a466dSPrabhakar Kushwaha temp32 = 0; 430b03a466dSPrabhakar Kushwaha pci_hose_read_config_dword(hose, dev, PCI_LCR, &temp32); 431b03a466dSPrabhakar Kushwaha temp32 &= ~0x03; /* Disable ASPM */ 432b03a466dSPrabhakar Kushwaha pci_hose_write_config_dword(hose, dev, PCI_LCR, temp32); 433b03a466dSPrabhakar Kushwaha udelay(1); 434b03a466dSPrabhakar Kushwaha #endif 4358295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 43693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LTSSM, <ssm); 43793a686eeSJean-Christophe PLAGNIOL-VILLARD enabled = ltssm >= PCI_LTSSM_L0; 43893a686eeSJean-Christophe PLAGNIOL-VILLARD 4398ff3de61SKumar Gala #ifdef CONFIG_FSL_PCIE_RESET 4408ff3de61SKumar Gala if (ltssm == 1) { 4418ff3de61SKumar Gala int i; 442ad19e7a5SKumar Gala debug("....PCIe link error. " "LTSSM=0x%02x.", ltssm); 443ad19e7a5SKumar Gala /* assert PCIe reset */ 444ad19e7a5SKumar Gala setbits_be32(&pci->pdb_stat, 0x08000000); 445ad19e7a5SKumar Gala (void) in_be32(&pci->pdb_stat); 4468ff3de61SKumar Gala udelay(100); 447d015df8fSMarek Vasut debug(" Asserting PCIe reset @%p = %x\n", 448ad19e7a5SKumar Gala &pci->pdb_stat, in_be32(&pci->pdb_stat)); 449ad19e7a5SKumar Gala /* clear PCIe reset */ 450ad19e7a5SKumar Gala clrbits_be32(&pci->pdb_stat, 0x08000000); 4518ff3de61SKumar Gala asm("sync;isync"); 4528ff3de61SKumar Gala for (i=0; i<100 && ltssm < PCI_LTSSM_L0; i++) { 4538ff3de61SKumar Gala pci_hose_read_config_word(hose, dev, PCI_LTSSM, 4548ff3de61SKumar Gala <ssm); 4558ff3de61SKumar Gala udelay(1000); 4568ff3de61SKumar Gala debug("....PCIe link error. " 4578ff3de61SKumar Gala "LTSSM=0x%02x.\n", ltssm); 4588ff3de61SKumar Gala } 4598ff3de61SKumar Gala enabled = ltssm >= PCI_LTSSM_L0; 460ad19e7a5SKumar Gala 461ad19e7a5SKumar Gala /* we need to re-write the bar0 since a reset will 462ad19e7a5SKumar Gala * clear it 463ad19e7a5SKumar Gala */ 464ad19e7a5SKumar Gala pci_hose_write_config_dword(hose, dev, 465ad19e7a5SKumar Gala PCI_BASE_ADDRESS_0, pcicsrbar); 4668ff3de61SKumar Gala } 4678ff3de61SKumar Gala #endif 4688ff3de61SKumar Gala 46993a686eeSJean-Christophe PLAGNIOL-VILLARD if (!enabled) { 470213ac73eSPeter Tyser /* Let the user know there's no PCIe link */ 471213ac73eSPeter Tyser printf("no link, regs @ 0x%lx\n", pci_info->regs); 47293a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->first_busno; 47393a686eeSJean-Christophe PLAGNIOL-VILLARD return; 47493a686eeSJean-Christophe PLAGNIOL-VILLARD } 47593a686eeSJean-Christophe PLAGNIOL-VILLARD 476ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 477ad19e7a5SKumar Gala out_be32(&pci->pme_msg_int_en, 0xffffffff); 478213ac73eSPeter Tyser 479213ac73eSPeter Tyser /* Print the negotiated PCIe link width */ 48093a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_LSR, &temp16); 481213ac73eSPeter Tyser printf("x%d, regs @ 0x%lx\n", (temp16 & 0x3f0 ) >> 4, 482213ac73eSPeter Tyser pci_info->regs); 483213ac73eSPeter Tyser 48493a686eeSJean-Christophe PLAGNIOL-VILLARD hose->current_busno++; /* Start scan with secondary */ 48593a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); 48693a686eeSJean-Christophe PLAGNIOL-VILLARD } 48793a686eeSJean-Christophe PLAGNIOL-VILLARD 48893a686eeSJean-Christophe PLAGNIOL-VILLARD /* Use generic setup_device to initialize standard pci regs, 48993a686eeSJean-Christophe PLAGNIOL-VILLARD * but do not allocate any windows since any BAR found (such 49093a686eeSJean-Christophe PLAGNIOL-VILLARD * as PCSRBAR) is not in this cpu's memory space. 49193a686eeSJean-Christophe PLAGNIOL-VILLARD */ 49293a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_setup_device(hose, dev, 0, hose->pci_mem, 49393a686eeSJean-Christophe PLAGNIOL-VILLARD hose->pci_prefetch, hose->pci_io); 49493a686eeSJean-Christophe PLAGNIOL-VILLARD 49593a686eeSJean-Christophe PLAGNIOL-VILLARD if (inbound) { 49693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word(hose, dev, PCI_COMMAND, &temp16); 49793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_COMMAND, 49893a686eeSJean-Christophe PLAGNIOL-VILLARD temp16 | PCI_COMMAND_MEMORY); 49993a686eeSJean-Christophe PLAGNIOL-VILLARD } 50093a686eeSJean-Christophe PLAGNIOL-VILLARD 50193a686eeSJean-Christophe PLAGNIOL-VILLARD #ifndef CONFIG_PCI_NOSCAN 502*505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) { 50337d03fceSPeter Tyser debug(" Scanning PCI bus %02x\n", 5046df0efd5SEd Swarthout hose->current_busno); 50593a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = pci_hose_scan_bus(hose, hose->current_busno); 5066df0efd5SEd Swarthout } else { 5076df0efd5SEd Swarthout debug(" Not scanning PCI bus %02x. PI=%x\n", 5086df0efd5SEd Swarthout hose->current_busno, temp8); 5096df0efd5SEd Swarthout hose->last_busno = hose->current_busno; 5106df0efd5SEd Swarthout } 51193a686eeSJean-Christophe PLAGNIOL-VILLARD 5128295b944SKumar Gala /* if we are PCIe - update limit regs and subordinate busno 5138295b944SKumar Gala * for the virtual P2P bridge 5148295b944SKumar Gala */ 5158295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) { 51693a686eeSJean-Christophe PLAGNIOL-VILLARD pciauto_postscan_setup_bridge(hose, dev, hose->last_busno); 51793a686eeSJean-Christophe PLAGNIOL-VILLARD } 51893a686eeSJean-Christophe PLAGNIOL-VILLARD #else 51993a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = hose->current_busno; 52093a686eeSJean-Christophe PLAGNIOL-VILLARD #endif 52193a686eeSJean-Christophe PLAGNIOL-VILLARD 52293a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear all error indications */ 5238295b944SKumar Gala if (pcie_cap == PCI_CAP_ID_EXP) 524ad19e7a5SKumar Gala out_be32(&pci->pme_msg_det, 0xffffffff); 525ad19e7a5SKumar Gala out_be32(&pci->pedr, 0xffffffff); 52693a686eeSJean-Christophe PLAGNIOL-VILLARD 52793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_DSR, &temp16); 52893a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 5298295b944SKumar Gala pci_hose_write_config_word(hose, dev, PCI_DSR, 0xffff); 53093a686eeSJean-Christophe PLAGNIOL-VILLARD } 53193a686eeSJean-Christophe PLAGNIOL-VILLARD 53293a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word (hose, dev, PCI_SEC_STATUS, &temp16); 53393a686eeSJean-Christophe PLAGNIOL-VILLARD if (temp16) { 53493a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word(hose, dev, PCI_SEC_STATUS, 0xffff); 53593a686eeSJean-Christophe PLAGNIOL-VILLARD } 53693a686eeSJean-Christophe PLAGNIOL-VILLARD } 537a2aab460SKumar Gala 538715d8f76SEd Swarthout int fsl_is_pci_agent(struct pci_controller *hose) 539715d8f76SEd Swarthout { 540*505f3e6fSMinghuan Lian u8 pcie_cap; 541715d8f76SEd Swarthout pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 542715d8f76SEd Swarthout 543*505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 544*505f3e6fSMinghuan Lian if (pcie_cap == PCI_CAP_ID_EXP) { 545*505f3e6fSMinghuan Lian u8 header_type; 546715d8f76SEd Swarthout 547*505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, 548*505f3e6fSMinghuan Lian &header_type); 549*505f3e6fSMinghuan Lian return (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; 550*505f3e6fSMinghuan Lian } else { 551*505f3e6fSMinghuan Lian u8 prog_if; 552*505f3e6fSMinghuan Lian 553*505f3e6fSMinghuan Lian pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prog_if); 554715d8f76SEd Swarthout return (prog_if == FSL_PROG_IF_AGENT); 555715d8f76SEd Swarthout } 556*505f3e6fSMinghuan Lian } 557715d8f76SEd Swarthout 5580d3d68b2SPoonam Aggrwal int fsl_pci_init_port(struct fsl_pci_info *pci_info, 55901471d53SKumar Gala struct pci_controller *hose, int busno) 5600d3d68b2SPoonam Aggrwal { 5610d3d68b2SPoonam Aggrwal volatile ccsr_fsl_pci_t *pci; 5620d3d68b2SPoonam Aggrwal struct pci_region *r; 563a72dbae2SPeter Tyser pci_dev_t dev = PCI_BDF(busno,0,0); 564a72dbae2SPeter Tyser u8 pcie_cap; 5650d3d68b2SPoonam Aggrwal 5660d3d68b2SPoonam Aggrwal pci = (ccsr_fsl_pci_t *) pci_info->regs; 5670d3d68b2SPoonam Aggrwal 5680d3d68b2SPoonam Aggrwal /* on non-PCIe controllers we don't have pme_msg_det so this code 5690d3d68b2SPoonam Aggrwal * should do nothing since the read will return 0 5700d3d68b2SPoonam Aggrwal */ 5710d3d68b2SPoonam Aggrwal if (in_be32(&pci->pme_msg_det)) { 5720d3d68b2SPoonam Aggrwal out_be32(&pci->pme_msg_det, 0xffffffff); 5730d3d68b2SPoonam Aggrwal debug (" with errors. Clearing. Now 0x%08x", 5740d3d68b2SPoonam Aggrwal pci->pme_msg_det); 5750d3d68b2SPoonam Aggrwal } 5760d3d68b2SPoonam Aggrwal 5770d3d68b2SPoonam Aggrwal r = hose->regions + hose->region_count; 5780d3d68b2SPoonam Aggrwal 5790d3d68b2SPoonam Aggrwal /* outbound memory */ 5800d3d68b2SPoonam Aggrwal pci_set_region(r++, 5810d3d68b2SPoonam Aggrwal pci_info->mem_bus, 5820d3d68b2SPoonam Aggrwal pci_info->mem_phys, 5830d3d68b2SPoonam Aggrwal pci_info->mem_size, 5840d3d68b2SPoonam Aggrwal PCI_REGION_MEM); 5850d3d68b2SPoonam Aggrwal 5860d3d68b2SPoonam Aggrwal /* outbound io */ 5870d3d68b2SPoonam Aggrwal pci_set_region(r++, 5880d3d68b2SPoonam Aggrwal pci_info->io_bus, 5890d3d68b2SPoonam Aggrwal pci_info->io_phys, 5900d3d68b2SPoonam Aggrwal pci_info->io_size, 5910d3d68b2SPoonam Aggrwal PCI_REGION_IO); 5920d3d68b2SPoonam Aggrwal 5930d3d68b2SPoonam Aggrwal hose->region_count = r - hose->regions; 5940d3d68b2SPoonam Aggrwal hose->first_busno = busno; 5950d3d68b2SPoonam Aggrwal 596213ac73eSPeter Tyser fsl_pci_init(hose, pci_info); 5970d3d68b2SPoonam Aggrwal 598715d8f76SEd Swarthout if (fsl_is_pci_agent(hose)) { 599715d8f76SEd Swarthout fsl_pci_config_unlock(hose); 600715d8f76SEd Swarthout hose->last_busno = hose->first_busno; 601b5f7c873SLiu Gang #ifdef CONFIG_FSL_CORENET 602b5f7c873SLiu Gang } else { 603b5f7c873SLiu Gang /* boot from PCIE --master releases slave's core 0 */ 604b5f7c873SLiu Gang char *s = getenv("bootmaster"); 605b5f7c873SLiu Gang char pcie[6]; 606b5f7c873SLiu Gang sprintf(pcie, "PCIE%d", pci_info->pci_num); 607b5f7c873SLiu Gang 608b5f7c873SLiu Gang if (s && (strcmp(s, pcie) == 0)) 609b5f7c873SLiu Gang fsl_pcie_boot_master_release_slave(pci_info->pci_num); 610b5f7c873SLiu Gang #endif 611715d8f76SEd Swarthout } 612715d8f76SEd Swarthout 613a72dbae2SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6148ca78f2cSPeter Tyser printf("PCI%s%x: Bus %02x - %02x\n", pcie_cap == PCI_CAP_ID_EXP ? 615213ac73eSPeter Tyser "e" : "", pci_info->pci_num, 6160d3d68b2SPoonam Aggrwal hose->first_busno, hose->last_busno); 6170d3d68b2SPoonam Aggrwal 6180d3d68b2SPoonam Aggrwal return(hose->last_busno + 1); 6190d3d68b2SPoonam Aggrwal } 6200d3d68b2SPoonam Aggrwal 6217a897959SPeter Tyser /* Enable inbound PCI config cycles for agent/endpoint interface */ 6227a897959SPeter Tyser void fsl_pci_config_unlock(struct pci_controller *hose) 6237a897959SPeter Tyser { 6247a897959SPeter Tyser pci_dev_t dev = PCI_BDF(hose->first_busno,0,0); 6257a897959SPeter Tyser u8 pcie_cap; 6267a897959SPeter Tyser u16 pbfr; 6277a897959SPeter Tyser 628*505f3e6fSMinghuan Lian if (!fsl_is_pci_agent(hose)) 6297a897959SPeter Tyser return; 6307a897959SPeter Tyser 6317a897959SPeter Tyser pci_hose_read_config_byte(hose, dev, FSL_PCIE_CAP_ID, &pcie_cap); 6327a897959SPeter Tyser if (pcie_cap != 0x0) { 6337a897959SPeter Tyser /* PCIe - set CFG_READY bit of Configuration Ready Register */ 6347a897959SPeter Tyser pci_hose_write_config_byte(hose, dev, FSL_PCIE_CFG_RDY, 0x1); 6357a897959SPeter Tyser } else { 6367a897959SPeter Tyser /* PCI - clear ACL bit of PBFR */ 6377a897959SPeter Tyser pci_hose_read_config_word(hose, dev, FSL_PCI_PBFR, &pbfr); 6387a897959SPeter Tyser pbfr &= ~0x20; 6397a897959SPeter Tyser pci_hose_write_config_word(hose, dev, FSL_PCI_PBFR, pbfr); 6407a897959SPeter Tyser } 6417a897959SPeter Tyser } 6427a897959SPeter Tyser 643a4aafcc9SKumar Gala #if defined(CONFIG_PCIE1) || defined(CONFIG_PCIE2) || \ 644a4aafcc9SKumar Gala defined(CONFIG_PCIE3) || defined(CONFIG_PCIE4) 645a4aafcc9SKumar Gala int fsl_configure_pcie(struct fsl_pci_info *info, 646a4aafcc9SKumar Gala struct pci_controller *hose, 647a4aafcc9SKumar Gala const char *connected, int busno) 648a4aafcc9SKumar Gala { 649a4aafcc9SKumar Gala int is_endpoint; 650a4aafcc9SKumar Gala 651a4aafcc9SKumar Gala set_next_law(info->mem_phys, law_size_bits(info->mem_size), info->law); 652a4aafcc9SKumar Gala set_next_law(info->io_phys, law_size_bits(info->io_size), info->law); 653213ac73eSPeter Tyser 654a4aafcc9SKumar Gala is_endpoint = fsl_setup_hose(hose, info->regs); 655213ac73eSPeter Tyser printf("PCIe%u: %s", info->pci_num, 656213ac73eSPeter Tyser is_endpoint ? "Endpoint" : "Root Complex"); 657213ac73eSPeter Tyser if (connected) 658213ac73eSPeter Tyser printf(" of %s", connected); 659213ac73eSPeter Tyser puts(", "); 660213ac73eSPeter Tyser 661a4aafcc9SKumar Gala return fsl_pci_init_port(info, hose, busno); 662a4aafcc9SKumar Gala } 663a4aafcc9SKumar Gala 664a4aafcc9SKumar Gala #if defined(CONFIG_FSL_CORENET) 665a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 FSL_CORENET_DEVDISR_PCIE1 666a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 FSL_CORENET_DEVDISR_PCIE2 667a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 FSL_CORENET_DEVDISR_PCIE3 668a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 FSL_CORENET_DEVDISR_PCIE4 669a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 670a4aafcc9SKumar Gala #elif defined(CONFIG_MPC85xx) 671a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE 672a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2 673a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3 674a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 675a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR CONFIG_SYS_MPC85xx_GUTS_ADDR 676a4aafcc9SKumar Gala #elif defined(CONFIG_MPC86xx) 677a4aafcc9SKumar Gala #define _DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIE1 678a4aafcc9SKumar Gala #define _DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIE2 679a4aafcc9SKumar Gala #define _DEVDISR_PCIE3 0 680a4aafcc9SKumar Gala #define _DEVDISR_PCIE4 0 681a4aafcc9SKumar Gala #define CONFIG_SYS_MPC8xxx_GUTS_ADDR \ 682a4aafcc9SKumar Gala (&((immap_t *)CONFIG_SYS_IMMR)->im_gur) 683a4aafcc9SKumar Gala #else 684a4aafcc9SKumar Gala #error "No defines for DEVDISR_PCIE" 685a4aafcc9SKumar Gala #endif 686a4aafcc9SKumar Gala 687a4aafcc9SKumar Gala /* Implement a dummy function for those platforms w/o SERDES */ 688a4aafcc9SKumar Gala static const char *__board_serdes_name(enum srds_prtcl device) 689a4aafcc9SKumar Gala { 690a4aafcc9SKumar Gala switch (device) { 691a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE1_NAME 692a4aafcc9SKumar Gala case PCIE1: 693a4aafcc9SKumar Gala return CONFIG_SYS_PCIE1_NAME; 694a4aafcc9SKumar Gala #endif 695a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE2_NAME 696a4aafcc9SKumar Gala case PCIE2: 697a4aafcc9SKumar Gala return CONFIG_SYS_PCIE2_NAME; 698a4aafcc9SKumar Gala #endif 699a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE3_NAME 700a4aafcc9SKumar Gala case PCIE3: 701a4aafcc9SKumar Gala return CONFIG_SYS_PCIE3_NAME; 702a4aafcc9SKumar Gala #endif 703a4aafcc9SKumar Gala #ifdef CONFIG_SYS_PCIE4_NAME 704a4aafcc9SKumar Gala case PCIE4: 705a4aafcc9SKumar Gala return CONFIG_SYS_PCIE4_NAME; 706a4aafcc9SKumar Gala #endif 707a4aafcc9SKumar Gala default: 708a4aafcc9SKumar Gala return NULL; 709a4aafcc9SKumar Gala } 710a4aafcc9SKumar Gala 711a4aafcc9SKumar Gala return NULL; 712a4aafcc9SKumar Gala } 713a4aafcc9SKumar Gala 714a4aafcc9SKumar Gala __attribute__((weak, alias("__board_serdes_name"))) const char * 715a4aafcc9SKumar Gala board_serdes_name(enum srds_prtcl device); 716a4aafcc9SKumar Gala 717a4aafcc9SKumar Gala static u32 devdisr_mask[] = { 718a4aafcc9SKumar Gala _DEVDISR_PCIE1, 719a4aafcc9SKumar Gala _DEVDISR_PCIE2, 720a4aafcc9SKumar Gala _DEVDISR_PCIE3, 721a4aafcc9SKumar Gala _DEVDISR_PCIE4, 722a4aafcc9SKumar Gala }; 723a4aafcc9SKumar Gala 724a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 725a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 726a4aafcc9SKumar Gala { 727a4aafcc9SKumar Gala struct pci_controller *hose; 728a4aafcc9SKumar Gala int num = dev - PCIE1; 729a4aafcc9SKumar Gala 730a4aafcc9SKumar Gala hose = calloc(1, sizeof(struct pci_controller)); 731a4aafcc9SKumar Gala if (!hose) 732a4aafcc9SKumar Gala return busno; 733a4aafcc9SKumar Gala 734a4aafcc9SKumar Gala if (is_serdes_configured(dev) && !(devdisr & devdisr_mask[num])) { 735a4aafcc9SKumar Gala busno = fsl_configure_pcie(pci_info, hose, 736a4aafcc9SKumar Gala board_serdes_name(dev), busno); 737a4aafcc9SKumar Gala } else { 738213ac73eSPeter Tyser printf("PCIe%d: disabled\n", num + 1); 739a4aafcc9SKumar Gala } 740a4aafcc9SKumar Gala 741a4aafcc9SKumar Gala return busno; 742a4aafcc9SKumar Gala } 743a4aafcc9SKumar Gala 744a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 745a4aafcc9SKumar Gala { 746a4aafcc9SKumar Gala struct fsl_pci_info pci_info; 747a4aafcc9SKumar Gala ccsr_gur_t *gur = (void *)CONFIG_SYS_MPC8xxx_GUTS_ADDR; 748a4aafcc9SKumar Gala u32 devdisr = in_be32(&gur->devdisr); 749a4aafcc9SKumar Gala 750a4aafcc9SKumar Gala #ifdef CONFIG_PCIE1 751a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 1); 752a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE1, &pci_info); 753a4aafcc9SKumar Gala #else 754a4aafcc9SKumar Gala setbits_be32(&gur->devdisr, _DEVDISR_PCIE1); /* disable */ 755a4aafcc9SKumar Gala #endif 756a4aafcc9SKumar Gala 757a4aafcc9SKumar Gala #ifdef CONFIG_PCIE2 758a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 2); 759a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE2, &pci_info); 760a4aafcc9SKumar Gala #else 761a4aafcc9SKumar Gala setbits_be32(&gur->devdisr, _DEVDISR_PCIE2); /* disable */ 762a4aafcc9SKumar Gala #endif 763a4aafcc9SKumar Gala 764a4aafcc9SKumar Gala #ifdef CONFIG_PCIE3 765a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 3); 766a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE3, &pci_info); 767a4aafcc9SKumar Gala #else 768a4aafcc9SKumar Gala setbits_be32(&gur->devdisr, _DEVDISR_PCIE3); /* disable */ 769a4aafcc9SKumar Gala #endif 770a4aafcc9SKumar Gala 771a4aafcc9SKumar Gala #ifdef CONFIG_PCIE4 772a4aafcc9SKumar Gala SET_STD_PCIE_INFO(pci_info, 4); 773a4aafcc9SKumar Gala busno = fsl_pcie_init_ctrl(busno, devdisr, PCIE4, &pci_info); 774a4aafcc9SKumar Gala #else 775a4aafcc9SKumar Gala setbits_be32(&gur->devdisr, _DEVDISR_PCIE4); /* disable */ 776a4aafcc9SKumar Gala #endif 777a4aafcc9SKumar Gala 778a4aafcc9SKumar Gala return busno; 779a4aafcc9SKumar Gala } 780a4aafcc9SKumar Gala #else 781a4aafcc9SKumar Gala int fsl_pcie_init_ctrl(int busno, u32 devdisr, enum srds_prtcl dev, 782a4aafcc9SKumar Gala struct fsl_pci_info *pci_info) 783a4aafcc9SKumar Gala { 784a4aafcc9SKumar Gala return busno; 785a4aafcc9SKumar Gala } 786a4aafcc9SKumar Gala 787a4aafcc9SKumar Gala int fsl_pcie_init_board(int busno) 788a4aafcc9SKumar Gala { 789a4aafcc9SKumar Gala return busno; 790a4aafcc9SKumar Gala } 791a4aafcc9SKumar Gala #endif 792a4aafcc9SKumar Gala 793a2aab460SKumar Gala #ifdef CONFIG_OF_BOARD_SETUP 794a2aab460SKumar Gala #include <libfdt.h> 795a2aab460SKumar Gala #include <fdt_support.h> 796a2aab460SKumar Gala 7976525d51fSKumar Gala void ft_fsl_pci_setup(void *blob, const char *pci_compat, 7983a0e3c27SKumar Gala unsigned long ctrl_addr) 799a2aab460SKumar Gala { 8006525d51fSKumar Gala int off; 801a2aab460SKumar Gala u32 bus_range[2]; 8026525d51fSKumar Gala phys_addr_t p_ctrl_addr = (phys_addr_t)ctrl_addr; 8033a0e3c27SKumar Gala struct pci_controller *hose; 8043a0e3c27SKumar Gala 8053a0e3c27SKumar Gala hose = find_hose_by_cfg_addr((void *)(ctrl_addr)); 8066525d51fSKumar Gala 8076525d51fSKumar Gala /* convert ctrl_addr to true physical address */ 8086525d51fSKumar Gala p_ctrl_addr = (phys_addr_t)ctrl_addr - CONFIG_SYS_CCSRBAR; 8096525d51fSKumar Gala p_ctrl_addr += CONFIG_SYS_CCSRBAR_PHYS; 8106525d51fSKumar Gala 8116525d51fSKumar Gala off = fdt_node_offset_by_compat_reg(blob, pci_compat, p_ctrl_addr); 812a2aab460SKumar Gala 8135a85a309SKumar Gala if (off < 0) 8145a85a309SKumar Gala return; 8155a85a309SKumar Gala 8165a85a309SKumar Gala /* We assume a cfg_addr not being set means we didn't setup the controller */ 8175a85a309SKumar Gala if ((hose == NULL) || (hose->cfg_addr == NULL)) { 8186525d51fSKumar Gala fdt_del_node(blob, off); 8195a85a309SKumar Gala } else { 820a2aab460SKumar Gala bus_range[0] = 0; 821a2aab460SKumar Gala bus_range[1] = hose->last_busno - hose->first_busno; 822a2aab460SKumar Gala fdt_setprop(blob, off, "bus-range", &bus_range[0], 2*4); 823a2aab460SKumar Gala fdt_pci_dma_ranges(blob, off, hose); 824a2aab460SKumar Gala } 825a2aab460SKumar Gala } 826a2aab460SKumar Gala #endif 827