1da419027SMinghuan Lian /* 2*e4e8cb71SMinghuan Lian * Copyright 2014-2015 Freescale Semiconductor, Inc. 3da419027SMinghuan Lian * Layerscape PCIe driver 4da419027SMinghuan Lian * 5da419027SMinghuan Lian * SPDX-License-Identifier: GPL-2.0+ 6da419027SMinghuan Lian */ 7da419027SMinghuan Lian 8da419027SMinghuan Lian #include <common.h> 9da419027SMinghuan Lian #include <asm/arch/fsl_serdes.h> 10da419027SMinghuan Lian #include <pci.h> 11da419027SMinghuan Lian #include <asm/io.h> 12*e4e8cb71SMinghuan Lian #include <errno.h> 13*e4e8cb71SMinghuan Lian #include <malloc.h> 14da419027SMinghuan Lian #include <asm/pcie_layerscape.h> 15da419027SMinghuan Lian 16*e4e8cb71SMinghuan Lian #ifndef CONFIG_SYS_PCI_MEMORY_BUS 17*e4e8cb71SMinghuan Lian #define CONFIG_SYS_PCI_MEMORY_BUS CONFIG_SYS_SDRAM_BASE 18*e4e8cb71SMinghuan Lian #endif 19*e4e8cb71SMinghuan Lian 20*e4e8cb71SMinghuan Lian #ifndef CONFIG_SYS_PCI_MEMORY_PHYS 21*e4e8cb71SMinghuan Lian #define CONFIG_SYS_PCI_MEMORY_PHYS CONFIG_SYS_SDRAM_BASE 22*e4e8cb71SMinghuan Lian #endif 23*e4e8cb71SMinghuan Lian 24*e4e8cb71SMinghuan Lian #ifndef CONFIG_SYS_PCI_MEMORY_SIZE 25*e4e8cb71SMinghuan Lian #define CONFIG_SYS_PCI_MEMORY_SIZE (2 * 1024 * 1024 * 1024UL) /* 2G */ 26*e4e8cb71SMinghuan Lian #endif 27*e4e8cb71SMinghuan Lian 28*e4e8cb71SMinghuan Lian /* iATU registers */ 29*e4e8cb71SMinghuan Lian #define PCIE_ATU_VIEWPORT 0x900 30*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_INBOUND (0x1 << 31) 31*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) 32*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_INDEX0 (0x0 << 0) 33*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_INDEX1 (0x1 << 0) 34*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_INDEX2 (0x2 << 0) 35*e4e8cb71SMinghuan Lian #define PCIE_ATU_REGION_INDEX3 (0x3 << 0) 36*e4e8cb71SMinghuan Lian #define PCIE_ATU_CR1 0x904 37*e4e8cb71SMinghuan Lian #define PCIE_ATU_TYPE_MEM (0x0 << 0) 38*e4e8cb71SMinghuan Lian #define PCIE_ATU_TYPE_IO (0x2 << 0) 39*e4e8cb71SMinghuan Lian #define PCIE_ATU_TYPE_CFG0 (0x4 << 0) 40*e4e8cb71SMinghuan Lian #define PCIE_ATU_TYPE_CFG1 (0x5 << 0) 41*e4e8cb71SMinghuan Lian #define PCIE_ATU_CR2 0x908 42*e4e8cb71SMinghuan Lian #define PCIE_ATU_ENABLE (0x1 << 31) 43*e4e8cb71SMinghuan Lian #define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) 44*e4e8cb71SMinghuan Lian #define PCIE_ATU_LOWER_BASE 0x90C 45*e4e8cb71SMinghuan Lian #define PCIE_ATU_UPPER_BASE 0x910 46*e4e8cb71SMinghuan Lian #define PCIE_ATU_LIMIT 0x914 47*e4e8cb71SMinghuan Lian #define PCIE_ATU_LOWER_TARGET 0x918 48*e4e8cb71SMinghuan Lian #define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) 49*e4e8cb71SMinghuan Lian #define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) 50*e4e8cb71SMinghuan Lian #define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) 51*e4e8cb71SMinghuan Lian #define PCIE_ATU_UPPER_TARGET 0x91C 52*e4e8cb71SMinghuan Lian 53*e4e8cb71SMinghuan Lian #define PCIE_LINK_CAP 0x7c 54*e4e8cb71SMinghuan Lian #define PCIE_LINK_SPEED_MASK 0xf 55*e4e8cb71SMinghuan Lian #define PCIE_LINK_STA 0x82 56*e4e8cb71SMinghuan Lian 57*e4e8cb71SMinghuan Lian #define PCIE_DBI_SIZE (4 * 1024) /* 4K */ 58*e4e8cb71SMinghuan Lian 59*e4e8cb71SMinghuan Lian struct ls_pcie { 60*e4e8cb71SMinghuan Lian int idx; 61*e4e8cb71SMinghuan Lian void __iomem *dbi; 62*e4e8cb71SMinghuan Lian void __iomem *va_cfg0; 63*e4e8cb71SMinghuan Lian void __iomem *va_cfg1; 64*e4e8cb71SMinghuan Lian struct pci_controller hose; 65*e4e8cb71SMinghuan Lian }; 66*e4e8cb71SMinghuan Lian 67*e4e8cb71SMinghuan Lian struct ls_pcie_info { 68*e4e8cb71SMinghuan Lian unsigned long regs; 69*e4e8cb71SMinghuan Lian int pci_num; 70*e4e8cb71SMinghuan Lian u64 cfg0_phys; 71*e4e8cb71SMinghuan Lian u64 cfg0_size; 72*e4e8cb71SMinghuan Lian u64 cfg1_phys; 73*e4e8cb71SMinghuan Lian u64 cfg1_size; 74*e4e8cb71SMinghuan Lian u64 mem_bus; 75*e4e8cb71SMinghuan Lian u64 mem_phys; 76*e4e8cb71SMinghuan Lian u64 mem_size; 77*e4e8cb71SMinghuan Lian u64 io_bus; 78*e4e8cb71SMinghuan Lian u64 io_phys; 79*e4e8cb71SMinghuan Lian u64 io_size; 80*e4e8cb71SMinghuan Lian }; 81*e4e8cb71SMinghuan Lian 82*e4e8cb71SMinghuan Lian #define SET_LS_PCIE_INFO(x, num) \ 83*e4e8cb71SMinghuan Lian { \ 84*e4e8cb71SMinghuan Lian x.regs = CONFIG_SYS_PCIE##num##_ADDR; \ 85*e4e8cb71SMinghuan Lian x.cfg0_phys = CONFIG_SYS_PCIE_CFG0_PHYS_OFF + \ 86*e4e8cb71SMinghuan Lian CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ 87*e4e8cb71SMinghuan Lian x.cfg0_size = CONFIG_SYS_PCIE_CFG0_SIZE; \ 88*e4e8cb71SMinghuan Lian x.cfg1_phys = CONFIG_SYS_PCIE_CFG1_PHYS_OFF + \ 89*e4e8cb71SMinghuan Lian CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ 90*e4e8cb71SMinghuan Lian x.cfg1_size = CONFIG_SYS_PCIE_CFG1_SIZE; \ 91*e4e8cb71SMinghuan Lian x.mem_bus = CONFIG_SYS_PCIE_MEM_BUS; \ 92*e4e8cb71SMinghuan Lian x.mem_phys = CONFIG_SYS_PCIE_MEM_PHYS_OFF + \ 93*e4e8cb71SMinghuan Lian CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ 94*e4e8cb71SMinghuan Lian x.mem_size = CONFIG_SYS_PCIE_MEM_SIZE; \ 95*e4e8cb71SMinghuan Lian x.io_bus = CONFIG_SYS_PCIE_IO_BUS; \ 96*e4e8cb71SMinghuan Lian x.io_phys = CONFIG_SYS_PCIE_IO_PHYS_OFF + \ 97*e4e8cb71SMinghuan Lian CONFIG_SYS_PCIE##num##_PHYS_ADDR; \ 98*e4e8cb71SMinghuan Lian x.io_size = CONFIG_SYS_PCIE_IO_SIZE; \ 99*e4e8cb71SMinghuan Lian x.pci_num = num; \ 100*e4e8cb71SMinghuan Lian } 101*e4e8cb71SMinghuan Lian 102*e4e8cb71SMinghuan Lian #ifdef CONFIG_LS102XA 103*e4e8cb71SMinghuan Lian #include <asm/arch/immap_ls102xa.h> 104*e4e8cb71SMinghuan Lian 105*e4e8cb71SMinghuan Lian /* PEX1/2 Misc Ports Status Register */ 106*e4e8cb71SMinghuan Lian #define LTSSM_STATE_SHIFT 20 107*e4e8cb71SMinghuan Lian #define LTSSM_STATE_MASK 0x3f 108*e4e8cb71SMinghuan Lian #define LTSSM_PCIE_L0 0x11 /* L0 state */ 109*e4e8cb71SMinghuan Lian 110*e4e8cb71SMinghuan Lian static int ls_pcie_link_state(struct ls_pcie *pcie) 111*e4e8cb71SMinghuan Lian { 112*e4e8cb71SMinghuan Lian u32 state; 113*e4e8cb71SMinghuan Lian struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR; 114*e4e8cb71SMinghuan Lian 115*e4e8cb71SMinghuan Lian state = in_be32(&scfg->pexmscportsr[pcie->idx]); 116*e4e8cb71SMinghuan Lian state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; 117*e4e8cb71SMinghuan Lian if (state < LTSSM_PCIE_L0) { 118*e4e8cb71SMinghuan Lian debug("....PCIe link error. LTSSM=0x%02x.\n", state); 119*e4e8cb71SMinghuan Lian return 0; 120*e4e8cb71SMinghuan Lian } 121*e4e8cb71SMinghuan Lian 122*e4e8cb71SMinghuan Lian return 1; 123*e4e8cb71SMinghuan Lian } 124*e4e8cb71SMinghuan Lian #else 125*e4e8cb71SMinghuan Lian #define PCIE_LDBG 0x7FC 126*e4e8cb71SMinghuan Lian 127*e4e8cb71SMinghuan Lian static int ls_pcie_link_state(struct ls_pcie *pcie) 128*e4e8cb71SMinghuan Lian { 129*e4e8cb71SMinghuan Lian u32 state; 130*e4e8cb71SMinghuan Lian 131*e4e8cb71SMinghuan Lian state = readl(pcie->dbi + PCIE_LDBG); 132*e4e8cb71SMinghuan Lian if (state) 133*e4e8cb71SMinghuan Lian return 1; 134*e4e8cb71SMinghuan Lian 135*e4e8cb71SMinghuan Lian debug("....PCIe link error.\n"); 136*e4e8cb71SMinghuan Lian return 0; 137*e4e8cb71SMinghuan Lian } 138*e4e8cb71SMinghuan Lian #endif 139*e4e8cb71SMinghuan Lian 140*e4e8cb71SMinghuan Lian static int ls_pcie_link_up(struct ls_pcie *pcie) 141*e4e8cb71SMinghuan Lian { 142*e4e8cb71SMinghuan Lian int state; 143*e4e8cb71SMinghuan Lian u32 cap; 144*e4e8cb71SMinghuan Lian 145*e4e8cb71SMinghuan Lian state = ls_pcie_link_state(pcie); 146*e4e8cb71SMinghuan Lian if (state) 147*e4e8cb71SMinghuan Lian return state; 148*e4e8cb71SMinghuan Lian 149*e4e8cb71SMinghuan Lian /* Try to download speed to gen1 */ 150*e4e8cb71SMinghuan Lian cap = readl(pcie->dbi + PCIE_LINK_CAP); 151*e4e8cb71SMinghuan Lian writel((cap & (~PCIE_LINK_SPEED_MASK)) | 1, pcie->dbi + PCIE_LINK_CAP); 152*e4e8cb71SMinghuan Lian udelay(2000); 153*e4e8cb71SMinghuan Lian state = ls_pcie_link_state(pcie); 154*e4e8cb71SMinghuan Lian if (state) 155*e4e8cb71SMinghuan Lian return state; 156*e4e8cb71SMinghuan Lian 157*e4e8cb71SMinghuan Lian writel(cap, pcie->dbi + PCIE_LINK_CAP); 158*e4e8cb71SMinghuan Lian 159*e4e8cb71SMinghuan Lian return 0; 160*e4e8cb71SMinghuan Lian } 161*e4e8cb71SMinghuan Lian 162*e4e8cb71SMinghuan Lian static void ls_pcie_cfg0_set_busdev(struct ls_pcie *pcie, u32 busdev) 163*e4e8cb71SMinghuan Lian { 164*e4e8cb71SMinghuan Lian writel(PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, 165*e4e8cb71SMinghuan Lian pcie->dbi + PCIE_ATU_VIEWPORT); 166*e4e8cb71SMinghuan Lian writel(busdev, pcie->dbi + PCIE_ATU_LOWER_TARGET); 167*e4e8cb71SMinghuan Lian } 168*e4e8cb71SMinghuan Lian 169*e4e8cb71SMinghuan Lian static void ls_pcie_cfg1_set_busdev(struct ls_pcie *pcie, u32 busdev) 170*e4e8cb71SMinghuan Lian { 171*e4e8cb71SMinghuan Lian writel(PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, 172*e4e8cb71SMinghuan Lian pcie->dbi + PCIE_ATU_VIEWPORT); 173*e4e8cb71SMinghuan Lian writel(busdev, pcie->dbi + PCIE_ATU_LOWER_TARGET); 174*e4e8cb71SMinghuan Lian } 175*e4e8cb71SMinghuan Lian 176*e4e8cb71SMinghuan Lian static void ls_pcie_iatu_outbound_set(struct ls_pcie *pcie, int idx, int type, 177*e4e8cb71SMinghuan Lian u64 phys, u64 bus_addr, pci_size_t size) 178*e4e8cb71SMinghuan Lian { 179*e4e8cb71SMinghuan Lian writel(PCIE_ATU_REGION_OUTBOUND | idx, pcie->dbi + PCIE_ATU_VIEWPORT); 180*e4e8cb71SMinghuan Lian writel((u32)phys, pcie->dbi + PCIE_ATU_LOWER_BASE); 181*e4e8cb71SMinghuan Lian writel(phys >> 32, pcie->dbi + PCIE_ATU_UPPER_BASE); 182*e4e8cb71SMinghuan Lian writel(phys + size - 1, pcie->dbi + PCIE_ATU_LIMIT); 183*e4e8cb71SMinghuan Lian writel((u32)bus_addr, pcie->dbi + PCIE_ATU_LOWER_TARGET); 184*e4e8cb71SMinghuan Lian writel(bus_addr >> 32, pcie->dbi + PCIE_ATU_UPPER_TARGET); 185*e4e8cb71SMinghuan Lian writel(type, pcie->dbi + PCIE_ATU_CR1); 186*e4e8cb71SMinghuan Lian writel(PCIE_ATU_ENABLE, pcie->dbi + PCIE_ATU_CR2); 187*e4e8cb71SMinghuan Lian } 188*e4e8cb71SMinghuan Lian 189*e4e8cb71SMinghuan Lian static void ls_pcie_setup_atu(struct ls_pcie *pcie, struct ls_pcie_info *info) 190*e4e8cb71SMinghuan Lian { 191*e4e8cb71SMinghuan Lian #ifdef DEBUG 192*e4e8cb71SMinghuan Lian int i; 193*e4e8cb71SMinghuan Lian #endif 194*e4e8cb71SMinghuan Lian 195*e4e8cb71SMinghuan Lian /* ATU 0 : OUTBOUND : CFG0 */ 196*e4e8cb71SMinghuan Lian ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX0, 197*e4e8cb71SMinghuan Lian PCIE_ATU_TYPE_CFG0, 198*e4e8cb71SMinghuan Lian info->cfg0_phys, 199*e4e8cb71SMinghuan Lian 0, 200*e4e8cb71SMinghuan Lian info->cfg0_size); 201*e4e8cb71SMinghuan Lian /* ATU 1 : OUTBOUND : CFG1 */ 202*e4e8cb71SMinghuan Lian ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX1, 203*e4e8cb71SMinghuan Lian PCIE_ATU_TYPE_CFG1, 204*e4e8cb71SMinghuan Lian info->cfg1_phys, 205*e4e8cb71SMinghuan Lian 0, 206*e4e8cb71SMinghuan Lian info->cfg1_size); 207*e4e8cb71SMinghuan Lian /* ATU 2 : OUTBOUND : MEM */ 208*e4e8cb71SMinghuan Lian ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX2, 209*e4e8cb71SMinghuan Lian PCIE_ATU_TYPE_MEM, 210*e4e8cb71SMinghuan Lian info->mem_phys, 211*e4e8cb71SMinghuan Lian info->mem_bus, 212*e4e8cb71SMinghuan Lian info->mem_size); 213*e4e8cb71SMinghuan Lian /* ATU 3 : OUTBOUND : IO */ 214*e4e8cb71SMinghuan Lian ls_pcie_iatu_outbound_set(pcie, PCIE_ATU_REGION_INDEX3, 215*e4e8cb71SMinghuan Lian PCIE_ATU_TYPE_IO, 216*e4e8cb71SMinghuan Lian info->io_phys, 217*e4e8cb71SMinghuan Lian info->io_bus, 218*e4e8cb71SMinghuan Lian info->io_size); 219*e4e8cb71SMinghuan Lian 220*e4e8cb71SMinghuan Lian #ifdef DEBUG 221*e4e8cb71SMinghuan Lian for (i = 0; i <= PCIE_ATU_REGION_INDEX3; i++) { 222*e4e8cb71SMinghuan Lian writel(PCIE_ATU_REGION_OUTBOUND | i, 223*e4e8cb71SMinghuan Lian pcie->dbi + PCIE_ATU_VIEWPORT); 224*e4e8cb71SMinghuan Lian debug("iATU%d:\n", i); 225*e4e8cb71SMinghuan Lian debug("\tLOWER PHYS 0x%08x\n", 226*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_LOWER_BASE)); 227*e4e8cb71SMinghuan Lian debug("\tUPPER PHYS 0x%08x\n", 228*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_UPPER_BASE)); 229*e4e8cb71SMinghuan Lian debug("\tLOWER BUS 0x%08x\n", 230*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_LOWER_TARGET)); 231*e4e8cb71SMinghuan Lian debug("\tUPPER BUS 0x%08x\n", 232*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_UPPER_TARGET)); 233*e4e8cb71SMinghuan Lian debug("\tLIMIT 0x%08x\n", 234*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_LIMIT)); 235*e4e8cb71SMinghuan Lian debug("\tCR1 0x%08x\n", 236*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_CR1)); 237*e4e8cb71SMinghuan Lian debug("\tCR2 0x%08x\n", 238*e4e8cb71SMinghuan Lian readl(pcie->dbi + PCIE_ATU_CR2)); 239*e4e8cb71SMinghuan Lian } 240*e4e8cb71SMinghuan Lian #endif 241*e4e8cb71SMinghuan Lian } 242*e4e8cb71SMinghuan Lian 243*e4e8cb71SMinghuan Lian int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev) 244*e4e8cb71SMinghuan Lian { 245*e4e8cb71SMinghuan Lian /* Do not skip controller */ 246*e4e8cb71SMinghuan Lian return 0; 247*e4e8cb71SMinghuan Lian } 248*e4e8cb71SMinghuan Lian 249*e4e8cb71SMinghuan Lian static int ls_pcie_addr_valid(struct pci_controller *hose, pci_dev_t d) 250*e4e8cb71SMinghuan Lian { 251*e4e8cb71SMinghuan Lian if (PCI_DEV(d) > 0) 252*e4e8cb71SMinghuan Lian return -EINVAL; 253*e4e8cb71SMinghuan Lian 254*e4e8cb71SMinghuan Lian return 0; 255*e4e8cb71SMinghuan Lian } 256*e4e8cb71SMinghuan Lian 257*e4e8cb71SMinghuan Lian static int ls_pcie_read_config(struct pci_controller *hose, pci_dev_t d, 258*e4e8cb71SMinghuan Lian int where, u32 *val) 259*e4e8cb71SMinghuan Lian { 260*e4e8cb71SMinghuan Lian struct ls_pcie *pcie = hose->priv_data; 261*e4e8cb71SMinghuan Lian u32 busdev, *addr; 262*e4e8cb71SMinghuan Lian 263*e4e8cb71SMinghuan Lian if (ls_pcie_addr_valid(hose, d)) { 264*e4e8cb71SMinghuan Lian *val = 0xffffffff; 265*e4e8cb71SMinghuan Lian return -EINVAL; 266*e4e8cb71SMinghuan Lian } 267*e4e8cb71SMinghuan Lian 268*e4e8cb71SMinghuan Lian if (PCI_BUS(d) == hose->first_busno) { 269*e4e8cb71SMinghuan Lian addr = pcie->dbi + (where & ~0x3); 270*e4e8cb71SMinghuan Lian } else { 271*e4e8cb71SMinghuan Lian busdev = PCIE_ATU_BUS(PCI_BUS(d)) | 272*e4e8cb71SMinghuan Lian PCIE_ATU_DEV(PCI_DEV(d)) | 273*e4e8cb71SMinghuan Lian PCIE_ATU_FUNC(PCI_FUNC(d)); 274*e4e8cb71SMinghuan Lian 275*e4e8cb71SMinghuan Lian if (PCI_BUS(d) == hose->first_busno + 1) { 276*e4e8cb71SMinghuan Lian ls_pcie_cfg0_set_busdev(pcie, busdev); 277*e4e8cb71SMinghuan Lian addr = pcie->va_cfg0 + (where & ~0x3); 278*e4e8cb71SMinghuan Lian } else { 279*e4e8cb71SMinghuan Lian ls_pcie_cfg1_set_busdev(pcie, busdev); 280*e4e8cb71SMinghuan Lian addr = pcie->va_cfg1 + (where & ~0x3); 281*e4e8cb71SMinghuan Lian } 282*e4e8cb71SMinghuan Lian } 283*e4e8cb71SMinghuan Lian 284*e4e8cb71SMinghuan Lian *val = readl(addr); 285*e4e8cb71SMinghuan Lian 286*e4e8cb71SMinghuan Lian return 0; 287*e4e8cb71SMinghuan Lian } 288*e4e8cb71SMinghuan Lian 289*e4e8cb71SMinghuan Lian static int ls_pcie_write_config(struct pci_controller *hose, pci_dev_t d, 290*e4e8cb71SMinghuan Lian int where, u32 val) 291*e4e8cb71SMinghuan Lian { 292*e4e8cb71SMinghuan Lian struct ls_pcie *pcie = hose->priv_data; 293*e4e8cb71SMinghuan Lian u32 busdev, *addr; 294*e4e8cb71SMinghuan Lian 295*e4e8cb71SMinghuan Lian if (ls_pcie_addr_valid(hose, d)) 296*e4e8cb71SMinghuan Lian return -EINVAL; 297*e4e8cb71SMinghuan Lian 298*e4e8cb71SMinghuan Lian if (PCI_BUS(d) == hose->first_busno) { 299*e4e8cb71SMinghuan Lian addr = pcie->dbi + (where & ~0x3); 300*e4e8cb71SMinghuan Lian } else { 301*e4e8cb71SMinghuan Lian busdev = PCIE_ATU_BUS(PCI_BUS(d)) | 302*e4e8cb71SMinghuan Lian PCIE_ATU_DEV(PCI_DEV(d)) | 303*e4e8cb71SMinghuan Lian PCIE_ATU_FUNC(PCI_FUNC(d)); 304*e4e8cb71SMinghuan Lian 305*e4e8cb71SMinghuan Lian if (PCI_BUS(d) == hose->first_busno + 1) { 306*e4e8cb71SMinghuan Lian ls_pcie_cfg0_set_busdev(pcie, busdev); 307*e4e8cb71SMinghuan Lian addr = pcie->va_cfg0 + (where & ~0x3); 308*e4e8cb71SMinghuan Lian } else { 309*e4e8cb71SMinghuan Lian ls_pcie_cfg1_set_busdev(pcie, busdev); 310*e4e8cb71SMinghuan Lian addr = pcie->va_cfg1 + (where & ~0x3); 311*e4e8cb71SMinghuan Lian } 312*e4e8cb71SMinghuan Lian } 313*e4e8cb71SMinghuan Lian 314*e4e8cb71SMinghuan Lian writel(val, addr); 315*e4e8cb71SMinghuan Lian 316*e4e8cb71SMinghuan Lian return 0; 317*e4e8cb71SMinghuan Lian } 318*e4e8cb71SMinghuan Lian 319*e4e8cb71SMinghuan Lian static void ls_pcie_setup_ctrl(struct ls_pcie *pcie, 320*e4e8cb71SMinghuan Lian struct ls_pcie_info *info) 321*e4e8cb71SMinghuan Lian { 322*e4e8cb71SMinghuan Lian struct pci_controller *hose = &pcie->hose; 323*e4e8cb71SMinghuan Lian pci_dev_t dev = PCI_BDF(hose->first_busno, 0, 0); 324*e4e8cb71SMinghuan Lian 325*e4e8cb71SMinghuan Lian ls_pcie_setup_atu(pcie, info); 326*e4e8cb71SMinghuan Lian 327*e4e8cb71SMinghuan Lian pci_hose_write_config_dword(hose, dev, PCI_BASE_ADDRESS_0, 0); 328*e4e8cb71SMinghuan Lian 329*e4e8cb71SMinghuan Lian /* program correct class for RC */ 330*e4e8cb71SMinghuan Lian pci_hose_write_config_word(hose, dev, PCI_CLASS_DEVICE, 331*e4e8cb71SMinghuan Lian PCI_CLASS_BRIDGE_PCI); 332*e4e8cb71SMinghuan Lian } 333*e4e8cb71SMinghuan Lian 334*e4e8cb71SMinghuan Lian int ls_pcie_init_ctrl(int busno, enum srds_prtcl dev, struct ls_pcie_info *info) 335*e4e8cb71SMinghuan Lian { 336*e4e8cb71SMinghuan Lian struct ls_pcie *pcie; 337*e4e8cb71SMinghuan Lian struct pci_controller *hose; 338*e4e8cb71SMinghuan Lian int num = dev - PCIE1; 339*e4e8cb71SMinghuan Lian pci_dev_t pdev = PCI_BDF(busno, 0, 0); 340*e4e8cb71SMinghuan Lian int i, linkup, ep_mode; 341*e4e8cb71SMinghuan Lian u8 header_type; 342*e4e8cb71SMinghuan Lian u16 temp16; 343*e4e8cb71SMinghuan Lian 344*e4e8cb71SMinghuan Lian if (!is_serdes_configured(dev)) { 345*e4e8cb71SMinghuan Lian printf("PCIe%d: disabled\n", num + 1); 346*e4e8cb71SMinghuan Lian return busno; 347*e4e8cb71SMinghuan Lian } 348*e4e8cb71SMinghuan Lian 349*e4e8cb71SMinghuan Lian pcie = malloc(sizeof(*pcie)); 350*e4e8cb71SMinghuan Lian if (!pcie) 351*e4e8cb71SMinghuan Lian return busno; 352*e4e8cb71SMinghuan Lian memset(pcie, 0, sizeof(*pcie)); 353*e4e8cb71SMinghuan Lian 354*e4e8cb71SMinghuan Lian hose = &pcie->hose; 355*e4e8cb71SMinghuan Lian hose->priv_data = pcie; 356*e4e8cb71SMinghuan Lian hose->first_busno = busno; 357*e4e8cb71SMinghuan Lian pcie->idx = num; 358*e4e8cb71SMinghuan Lian pcie->dbi = map_physmem(info->regs, PCIE_DBI_SIZE, MAP_NOCACHE); 359*e4e8cb71SMinghuan Lian pcie->va_cfg0 = map_physmem(info->cfg0_phys, 360*e4e8cb71SMinghuan Lian info->cfg0_size, 361*e4e8cb71SMinghuan Lian MAP_NOCACHE); 362*e4e8cb71SMinghuan Lian pcie->va_cfg1 = map_physmem(info->cfg1_phys, 363*e4e8cb71SMinghuan Lian info->cfg1_size, 364*e4e8cb71SMinghuan Lian MAP_NOCACHE); 365*e4e8cb71SMinghuan Lian 366*e4e8cb71SMinghuan Lian /* outbound memory */ 367*e4e8cb71SMinghuan Lian pci_set_region(&hose->regions[0], 368*e4e8cb71SMinghuan Lian (pci_size_t)info->mem_bus, 369*e4e8cb71SMinghuan Lian (phys_size_t)info->mem_phys, 370*e4e8cb71SMinghuan Lian (pci_size_t)info->mem_size, 371*e4e8cb71SMinghuan Lian PCI_REGION_MEM); 372*e4e8cb71SMinghuan Lian 373*e4e8cb71SMinghuan Lian /* outbound io */ 374*e4e8cb71SMinghuan Lian pci_set_region(&hose->regions[1], 375*e4e8cb71SMinghuan Lian (pci_size_t)info->io_bus, 376*e4e8cb71SMinghuan Lian (phys_size_t)info->io_phys, 377*e4e8cb71SMinghuan Lian (pci_size_t)info->io_size, 378*e4e8cb71SMinghuan Lian PCI_REGION_IO); 379*e4e8cb71SMinghuan Lian 380*e4e8cb71SMinghuan Lian /* System memory space */ 381*e4e8cb71SMinghuan Lian pci_set_region(&hose->regions[2], 382*e4e8cb71SMinghuan Lian CONFIG_SYS_PCI_MEMORY_BUS, 383*e4e8cb71SMinghuan Lian CONFIG_SYS_PCI_MEMORY_PHYS, 384*e4e8cb71SMinghuan Lian CONFIG_SYS_PCI_MEMORY_SIZE, 385*e4e8cb71SMinghuan Lian PCI_REGION_SYS_MEMORY); 386*e4e8cb71SMinghuan Lian 387*e4e8cb71SMinghuan Lian hose->region_count = 3; 388*e4e8cb71SMinghuan Lian 389*e4e8cb71SMinghuan Lian for (i = 0; i < hose->region_count; i++) 390*e4e8cb71SMinghuan Lian debug("PCI reg:%d %016llx:%016llx %016llx %08lx\n", 391*e4e8cb71SMinghuan Lian i, 392*e4e8cb71SMinghuan Lian (u64)hose->regions[i].phys_start, 393*e4e8cb71SMinghuan Lian (u64)hose->regions[i].bus_start, 394*e4e8cb71SMinghuan Lian (u64)hose->regions[i].size, 395*e4e8cb71SMinghuan Lian hose->regions[i].flags); 396*e4e8cb71SMinghuan Lian 397*e4e8cb71SMinghuan Lian pci_set_ops(hose, 398*e4e8cb71SMinghuan Lian pci_hose_read_config_byte_via_dword, 399*e4e8cb71SMinghuan Lian pci_hose_read_config_word_via_dword, 400*e4e8cb71SMinghuan Lian ls_pcie_read_config, 401*e4e8cb71SMinghuan Lian pci_hose_write_config_byte_via_dword, 402*e4e8cb71SMinghuan Lian pci_hose_write_config_word_via_dword, 403*e4e8cb71SMinghuan Lian ls_pcie_write_config); 404*e4e8cb71SMinghuan Lian 405*e4e8cb71SMinghuan Lian pci_hose_read_config_byte(hose, pdev, PCI_HEADER_TYPE, &header_type); 406*e4e8cb71SMinghuan Lian ep_mode = (header_type & 0x7f) == PCI_HEADER_TYPE_NORMAL; 407*e4e8cb71SMinghuan Lian printf("PCIe%u: %s ", info->pci_num, 408*e4e8cb71SMinghuan Lian ep_mode ? "Endpoint" : "Root Complex"); 409*e4e8cb71SMinghuan Lian 410*e4e8cb71SMinghuan Lian linkup = ls_pcie_link_up(pcie); 411*e4e8cb71SMinghuan Lian 412*e4e8cb71SMinghuan Lian if (!linkup) { 413*e4e8cb71SMinghuan Lian /* Let the user know there's no PCIe link */ 414*e4e8cb71SMinghuan Lian printf("no link, regs @ 0x%lx\n", info->regs); 415*e4e8cb71SMinghuan Lian hose->last_busno = hose->first_busno; 416*e4e8cb71SMinghuan Lian return busno; 417*e4e8cb71SMinghuan Lian } 418*e4e8cb71SMinghuan Lian 419*e4e8cb71SMinghuan Lian /* Print the negotiated PCIe link width */ 420*e4e8cb71SMinghuan Lian pci_hose_read_config_word(hose, dev, PCIE_LINK_STA, &temp16); 421*e4e8cb71SMinghuan Lian printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, 422*e4e8cb71SMinghuan Lian (temp16 & 0xf), info->regs); 423*e4e8cb71SMinghuan Lian 424*e4e8cb71SMinghuan Lian if (ep_mode) 425*e4e8cb71SMinghuan Lian return busno; 426*e4e8cb71SMinghuan Lian 427*e4e8cb71SMinghuan Lian ls_pcie_setup_ctrl(pcie, info); 428*e4e8cb71SMinghuan Lian 429*e4e8cb71SMinghuan Lian pci_register_hose(hose); 430*e4e8cb71SMinghuan Lian 431*e4e8cb71SMinghuan Lian hose->last_busno = pci_hose_scan(hose); 432*e4e8cb71SMinghuan Lian 433*e4e8cb71SMinghuan Lian printf("PCIe%x: Bus %02x - %02x\n", 434*e4e8cb71SMinghuan Lian info->pci_num, hose->first_busno, hose->last_busno); 435*e4e8cb71SMinghuan Lian 436*e4e8cb71SMinghuan Lian return hose->last_busno + 1; 437*e4e8cb71SMinghuan Lian } 438*e4e8cb71SMinghuan Lian 439*e4e8cb71SMinghuan Lian int ls_pcie_init_board(int busno) 440*e4e8cb71SMinghuan Lian { 441*e4e8cb71SMinghuan Lian struct ls_pcie_info info; 442*e4e8cb71SMinghuan Lian 443*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE1 444*e4e8cb71SMinghuan Lian SET_LS_PCIE_INFO(info, 1); 445*e4e8cb71SMinghuan Lian busno = ls_pcie_init_ctrl(busno, PCIE1, &info); 446*e4e8cb71SMinghuan Lian #endif 447*e4e8cb71SMinghuan Lian 448*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE2 449*e4e8cb71SMinghuan Lian SET_LS_PCIE_INFO(info, 2); 450*e4e8cb71SMinghuan Lian busno = ls_pcie_init_ctrl(busno, PCIE2, &info); 451*e4e8cb71SMinghuan Lian #endif 452*e4e8cb71SMinghuan Lian 453*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE3 454*e4e8cb71SMinghuan Lian SET_LS_PCIE_INFO(info, 3); 455*e4e8cb71SMinghuan Lian busno = ls_pcie_init_ctrl(busno, PCIE3, &info); 456*e4e8cb71SMinghuan Lian #endif 457*e4e8cb71SMinghuan Lian 458*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE4 459*e4e8cb71SMinghuan Lian SET_LS_PCIE_INFO(info, 4); 460*e4e8cb71SMinghuan Lian busno = ls_pcie_init_ctrl(busno, PCIE4, &info); 461*e4e8cb71SMinghuan Lian #endif 462*e4e8cb71SMinghuan Lian 463*e4e8cb71SMinghuan Lian return busno; 464*e4e8cb71SMinghuan Lian } 465*e4e8cb71SMinghuan Lian 466*e4e8cb71SMinghuan Lian void pci_init_board(void) 467*e4e8cb71SMinghuan Lian { 468*e4e8cb71SMinghuan Lian ls_pcie_init_board(0); 469*e4e8cb71SMinghuan Lian } 470*e4e8cb71SMinghuan Lian 471da419027SMinghuan Lian #ifdef CONFIG_OF_BOARD_SETUP 472da419027SMinghuan Lian #include <libfdt.h> 473da419027SMinghuan Lian #include <fdt_support.h> 474da419027SMinghuan Lian 475da419027SMinghuan Lian static void ft_pcie_ls_setup(void *blob, const char *pci_compat, 476da419027SMinghuan Lian unsigned long ctrl_addr, enum srds_prtcl dev) 477da419027SMinghuan Lian { 478da419027SMinghuan Lian int off; 479da419027SMinghuan Lian 480da419027SMinghuan Lian off = fdt_node_offset_by_compat_reg(blob, pci_compat, 481da419027SMinghuan Lian (phys_addr_t)ctrl_addr); 482da419027SMinghuan Lian if (off < 0) 483da419027SMinghuan Lian return; 484da419027SMinghuan Lian 485da419027SMinghuan Lian if (!is_serdes_configured(dev)) 486da419027SMinghuan Lian fdt_set_node_status(blob, off, FDT_STATUS_DISABLED, 0); 487da419027SMinghuan Lian } 488da419027SMinghuan Lian 489da419027SMinghuan Lian void ft_pcie_setup(void *blob, bd_t *bd) 490da419027SMinghuan Lian { 491da419027SMinghuan Lian #ifdef CONFIG_PCIE1 492da419027SMinghuan Lian ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE1_ADDR, PCIE1); 493da419027SMinghuan Lian #endif 494da419027SMinghuan Lian 495da419027SMinghuan Lian #ifdef CONFIG_PCIE2 496da419027SMinghuan Lian ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE2_ADDR, PCIE2); 497da419027SMinghuan Lian #endif 498*e4e8cb71SMinghuan Lian 499*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE3 500*e4e8cb71SMinghuan Lian ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE3_ADDR, PCIE3); 501*e4e8cb71SMinghuan Lian #endif 502*e4e8cb71SMinghuan Lian 503*e4e8cb71SMinghuan Lian #ifdef CONFIG_PCIE4 504*e4e8cb71SMinghuan Lian ft_pcie_ls_setup(blob, FSL_PCIE_COMPAT, CONFIG_SYS_PCIE4_ADDR, PCIE4); 505*e4e8cb71SMinghuan Lian #endif 506da419027SMinghuan Lian } 507da419027SMinghuan Lian 508da419027SMinghuan Lian #else 509da419027SMinghuan Lian void ft_pcie_setup(void *blob, bd_t *bd) 510da419027SMinghuan Lian { 511da419027SMinghuan Lian } 512da419027SMinghuan Lian #endif 513