18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 38c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 48c2ecf20Sopenharmony_ci * for more details. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/types.h> 108c2ecf20Sopenharmony_ci#include <linux/pci.h> 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/clk.h> 158c2ecf20Sopenharmony_ci#include <asm/bootinfo.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <bcm63xx_reset.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "pci-bcm63xx.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * Allow PCI to be disabled at runtime depending on board nvram 238c2ecf20Sopenharmony_ci * configuration 248c2ecf20Sopenharmony_ci */ 258c2ecf20Sopenharmony_ciint bcm63xx_pci_enabled; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic struct resource bcm_pci_mem_resource = { 288c2ecf20Sopenharmony_ci .name = "bcm63xx PCI memory space", 298c2ecf20Sopenharmony_ci .start = BCM_PCI_MEM_BASE_PA, 308c2ecf20Sopenharmony_ci .end = BCM_PCI_MEM_END_PA, 318c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic struct resource bcm_pci_io_resource = { 358c2ecf20Sopenharmony_ci .name = "bcm63xx PCI IO space", 368c2ecf20Sopenharmony_ci .start = BCM_PCI_IO_BASE_PA, 378c2ecf20Sopenharmony_ci#ifdef CONFIG_CARDBUS 388c2ecf20Sopenharmony_ci .end = BCM_PCI_IO_HALF_PA, 398c2ecf20Sopenharmony_ci#else 408c2ecf20Sopenharmony_ci .end = BCM_PCI_IO_END_PA, 418c2ecf20Sopenharmony_ci#endif 428c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct pci_controller bcm63xx_controller = { 468c2ecf20Sopenharmony_ci .pci_ops = &bcm63xx_pci_ops, 478c2ecf20Sopenharmony_ci .io_resource = &bcm_pci_io_resource, 488c2ecf20Sopenharmony_ci .mem_resource = &bcm_pci_mem_resource, 498c2ecf20Sopenharmony_ci}; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* 528c2ecf20Sopenharmony_ci * We handle cardbus via a fake Cardbus bridge, memory and io spaces 538c2ecf20Sopenharmony_ci * have to be clearly separated from PCI one since we have different 548c2ecf20Sopenharmony_ci * memory decoder. 558c2ecf20Sopenharmony_ci */ 568c2ecf20Sopenharmony_ci#ifdef CONFIG_CARDBUS 578c2ecf20Sopenharmony_cistatic struct resource bcm_cb_mem_resource = { 588c2ecf20Sopenharmony_ci .name = "bcm63xx Cardbus memory space", 598c2ecf20Sopenharmony_ci .start = BCM_CB_MEM_BASE_PA, 608c2ecf20Sopenharmony_ci .end = BCM_CB_MEM_END_PA, 618c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistatic struct resource bcm_cb_io_resource = { 658c2ecf20Sopenharmony_ci .name = "bcm63xx Cardbus IO space", 668c2ecf20Sopenharmony_ci .start = BCM_PCI_IO_HALF_PA + 1, 678c2ecf20Sopenharmony_ci .end = BCM_PCI_IO_END_PA, 688c2ecf20Sopenharmony_ci .flags = IORESOURCE_IO 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistruct pci_controller bcm63xx_cb_controller = { 728c2ecf20Sopenharmony_ci .pci_ops = &bcm63xx_cb_ops, 738c2ecf20Sopenharmony_ci .io_resource = &bcm_cb_io_resource, 748c2ecf20Sopenharmony_ci .mem_resource = &bcm_cb_mem_resource, 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci#endif 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic struct resource bcm_pcie_mem_resource = { 798c2ecf20Sopenharmony_ci .name = "bcm63xx PCIe memory space", 808c2ecf20Sopenharmony_ci .start = BCM_PCIE_MEM_BASE_PA, 818c2ecf20Sopenharmony_ci .end = BCM_PCIE_MEM_END_PA, 828c2ecf20Sopenharmony_ci .flags = IORESOURCE_MEM, 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic struct resource bcm_pcie_io_resource = { 868c2ecf20Sopenharmony_ci .name = "bcm63xx PCIe IO space", 878c2ecf20Sopenharmony_ci .start = 0, 888c2ecf20Sopenharmony_ci .end = 0, 898c2ecf20Sopenharmony_ci .flags = 0, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistruct pci_controller bcm63xx_pcie_controller = { 938c2ecf20Sopenharmony_ci .pci_ops = &bcm63xx_pcie_ops, 948c2ecf20Sopenharmony_ci .io_resource = &bcm_pcie_io_resource, 958c2ecf20Sopenharmony_ci .mem_resource = &bcm_pcie_mem_resource, 968c2ecf20Sopenharmony_ci}; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic u32 bcm63xx_int_cfg_readl(u32 reg) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci u32 tmp; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; 1038c2ecf20Sopenharmony_ci tmp |= MPI_PCICFGCTL_WRITEEN_MASK; 1048c2ecf20Sopenharmony_ci bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG); 1058c2ecf20Sopenharmony_ci iob(); 1068c2ecf20Sopenharmony_ci return bcm_mpi_readl(MPI_PCICFGDATA_REG); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic void bcm63xx_int_cfg_writel(u32 val, u32 reg) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci u32 tmp; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; 1148c2ecf20Sopenharmony_ci tmp |= MPI_PCICFGCTL_WRITEEN_MASK; 1158c2ecf20Sopenharmony_ci bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG); 1168c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_PCICFGDATA_REG); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_civoid __iomem *pci_iospace_start; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void __init bcm63xx_reset_pcie(void) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci u32 val; 1248c2ecf20Sopenharmony_ci u32 reg; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* enable SERDES */ 1278c2ecf20Sopenharmony_ci if (BCMCPU_IS_6328()) 1288c2ecf20Sopenharmony_ci reg = MISC_SERDES_CTRL_6328_REG; 1298c2ecf20Sopenharmony_ci else 1308c2ecf20Sopenharmony_ci reg = MISC_SERDES_CTRL_6362_REG; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci val = bcm_misc_readl(reg); 1338c2ecf20Sopenharmony_ci val |= SERDES_PCIE_EN | SERDES_PCIE_EXD_EN; 1348c2ecf20Sopenharmony_ci bcm_misc_writel(val, reg); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* reset the PCIe core */ 1378c2ecf20Sopenharmony_ci bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 1); 1388c2ecf20Sopenharmony_ci bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 1); 1398c2ecf20Sopenharmony_ci mdelay(10); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci bcm63xx_core_set_reset(BCM63XX_RESET_PCIE, 0); 1428c2ecf20Sopenharmony_ci mdelay(10); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci bcm63xx_core_set_reset(BCM63XX_RESET_PCIE_EXT, 0); 1458c2ecf20Sopenharmony_ci mdelay(200); 1468c2ecf20Sopenharmony_ci} 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_cistatic struct clk *pcie_clk; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cistatic int __init bcm63xx_register_pcie(void) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci u32 val; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* enable clock */ 1558c2ecf20Sopenharmony_ci pcie_clk = clk_get(NULL, "pcie"); 1568c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(pcie_clk)) 1578c2ecf20Sopenharmony_ci return -ENODEV; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci clk_prepare_enable(pcie_clk); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci bcm63xx_reset_pcie(); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci /* configure the PCIe bridge */ 1648c2ecf20Sopenharmony_ci val = bcm_pcie_readl(PCIE_BRIDGE_OPT1_REG); 1658c2ecf20Sopenharmony_ci val |= OPT1_RD_BE_OPT_EN; 1668c2ecf20Sopenharmony_ci val |= OPT1_RD_REPLY_BE_FIX_EN; 1678c2ecf20Sopenharmony_ci val |= OPT1_PCIE_BRIDGE_HOLE_DET_EN; 1688c2ecf20Sopenharmony_ci val |= OPT1_L1_INT_STATUS_MASK_POL; 1698c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_BRIDGE_OPT1_REG); 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci /* setup the interrupts */ 1728c2ecf20Sopenharmony_ci val = bcm_pcie_readl(PCIE_BRIDGE_RC_INT_MASK_REG); 1738c2ecf20Sopenharmony_ci val |= PCIE_RC_INT_A | PCIE_RC_INT_B | PCIE_RC_INT_C | PCIE_RC_INT_D; 1748c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_BRIDGE_RC_INT_MASK_REG); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci val = bcm_pcie_readl(PCIE_BRIDGE_OPT2_REG); 1778c2ecf20Sopenharmony_ci /* enable credit checking and error checking */ 1788c2ecf20Sopenharmony_ci val |= OPT2_TX_CREDIT_CHK_EN; 1798c2ecf20Sopenharmony_ci val |= OPT2_UBUS_UR_DECODE_DIS; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* set device bus/func for the pcie device */ 1828c2ecf20Sopenharmony_ci val |= (PCIE_BUS_DEVICE << OPT2_CFG_TYPE1_BUS_NO_SHIFT); 1838c2ecf20Sopenharmony_ci val |= OPT2_CFG_TYPE1_BD_SEL; 1848c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_BRIDGE_OPT2_REG); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci /* setup class code as bridge */ 1878c2ecf20Sopenharmony_ci val = bcm_pcie_readl(PCIE_IDVAL3_REG); 1888c2ecf20Sopenharmony_ci val &= ~IDVAL3_CLASS_CODE_MASK; 1898c2ecf20Sopenharmony_ci val |= (PCI_CLASS_BRIDGE_PCI << IDVAL3_SUBCLASS_SHIFT); 1908c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_IDVAL3_REG); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* disable bar1 size */ 1938c2ecf20Sopenharmony_ci val = bcm_pcie_readl(PCIE_CONFIG2_REG); 1948c2ecf20Sopenharmony_ci val &= ~CONFIG2_BAR1_SIZE_MASK; 1958c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_CONFIG2_REG); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci /* set bar0 to little endian */ 1988c2ecf20Sopenharmony_ci val = (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_BASE_SHIFT; 1998c2ecf20Sopenharmony_ci val |= (BCM_PCIE_MEM_BASE_PA >> 20) << BASEMASK_MASK_SHIFT; 2008c2ecf20Sopenharmony_ci val |= BASEMASK_REMAP_EN; 2018c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_BASEMASK_REG); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci val = (BCM_PCIE_MEM_BASE_PA >> 20) << REBASE_ADDR_BASE_SHIFT; 2048c2ecf20Sopenharmony_ci bcm_pcie_writel(val, PCIE_BRIDGE_BAR0_REBASE_ADDR_REG); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci register_pci_controller(&bcm63xx_pcie_controller); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci return 0; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_cistatic int __init bcm63xx_register_pci(void) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci unsigned int mem_size; 2148c2ecf20Sopenharmony_ci u32 val; 2158c2ecf20Sopenharmony_ci /* 2168c2ecf20Sopenharmony_ci * configuration access are done through IO space, remap 4 2178c2ecf20Sopenharmony_ci * first bytes to access it from CPU. 2188c2ecf20Sopenharmony_ci * 2198c2ecf20Sopenharmony_ci * this means that no io access from CPU should happen while 2208c2ecf20Sopenharmony_ci * we do a configuration cycle, but there's no way we can add 2218c2ecf20Sopenharmony_ci * a spinlock for each io access, so this is currently kind of 2228c2ecf20Sopenharmony_ci * broken on SMP. 2238c2ecf20Sopenharmony_ci */ 2248c2ecf20Sopenharmony_ci pci_iospace_start = ioremap(BCM_PCI_IO_BASE_PA, 4); 2258c2ecf20Sopenharmony_ci if (!pci_iospace_start) 2268c2ecf20Sopenharmony_ci return -ENOMEM; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci /* setup local bus to PCI access (PCI memory) */ 2298c2ecf20Sopenharmony_ci val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK; 2308c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG); 2318c2ecf20Sopenharmony_ci bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG); 2328c2ecf20Sopenharmony_ci bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci /* set Cardbus IDSEL (type 0 cfg access on primary bus for 2358c2ecf20Sopenharmony_ci * this IDSEL will be done on Cardbus instead) */ 2368c2ecf20Sopenharmony_ci val = bcm_pcmcia_readl(PCMCIA_C1_REG); 2378c2ecf20Sopenharmony_ci val &= ~PCMCIA_C1_CBIDSEL_MASK; 2388c2ecf20Sopenharmony_ci val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT); 2398c2ecf20Sopenharmony_ci bcm_pcmcia_writel(val, PCMCIA_C1_REG); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci#ifdef CONFIG_CARDBUS 2428c2ecf20Sopenharmony_ci /* setup local bus to PCI access (Cardbus memory) */ 2438c2ecf20Sopenharmony_ci val = BCM_CB_MEM_BASE_PA & MPI_L2P_BASE_MASK; 2448c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_L2PMEMBASE2_REG); 2458c2ecf20Sopenharmony_ci bcm_mpi_writel(~(BCM_CB_MEM_SIZE - 1), MPI_L2PMEMRANGE2_REG); 2468c2ecf20Sopenharmony_ci val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK; 2478c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_L2PMEMREMAP2_REG); 2488c2ecf20Sopenharmony_ci#else 2498c2ecf20Sopenharmony_ci /* disable second access windows */ 2508c2ecf20Sopenharmony_ci bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG); 2518c2ecf20Sopenharmony_ci#endif 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci /* setup local bus to PCI access (IO memory), we have only 1 2548c2ecf20Sopenharmony_ci * IO window for both PCI and cardbus, but it cannot handle 2558c2ecf20Sopenharmony_ci * both at the same time, assume standard PCI for now, if 2568c2ecf20Sopenharmony_ci * cardbus card has IO zone, PCI fixup will change window to 2578c2ecf20Sopenharmony_ci * cardbus */ 2588c2ecf20Sopenharmony_ci val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK; 2598c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_L2PIOBASE_REG); 2608c2ecf20Sopenharmony_ci bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG); 2618c2ecf20Sopenharmony_ci bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci /* enable PCI related GPIO pins */ 2648c2ecf20Sopenharmony_ci bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* setup PCI to local bus access, used by PCI device to target 2678c2ecf20Sopenharmony_ci * local RAM while bus mastering */ 2688c2ecf20Sopenharmony_ci bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); 2698c2ecf20Sopenharmony_ci if (BCMCPU_IS_3368() || BCMCPU_IS_6358() || BCMCPU_IS_6368()) 2708c2ecf20Sopenharmony_ci val = MPI_SP0_REMAP_ENABLE_MASK; 2718c2ecf20Sopenharmony_ci else 2728c2ecf20Sopenharmony_ci val = 0; 2738c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_SP0_REMAP_REG); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4); 2768c2ecf20Sopenharmony_ci bcm_mpi_writel(0, MPI_SP1_REMAP_REG); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci mem_size = bcm63xx_get_memory_size(); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci /* 6348 before rev b0 exposes only 16 MB of RAM memory through 2818c2ecf20Sopenharmony_ci * PCI, throw a warning if we have more memory */ 2828c2ecf20Sopenharmony_ci if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) { 2838c2ecf20Sopenharmony_ci if (mem_size > (16 * 1024 * 1024)) 2848c2ecf20Sopenharmony_ci printk(KERN_WARNING "bcm63xx: this CPU " 2858c2ecf20Sopenharmony_ci "revision cannot handle more than 16MB " 2868c2ecf20Sopenharmony_ci "of RAM for PCI bus mastering\n"); 2878c2ecf20Sopenharmony_ci } else { 2888c2ecf20Sopenharmony_ci /* setup sp0 range to local RAM size */ 2898c2ecf20Sopenharmony_ci bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG); 2908c2ecf20Sopenharmony_ci bcm_mpi_writel(0, MPI_SP1_RANGE_REG); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci /* change host bridge retry counter to infinite number of 2948c2ecf20Sopenharmony_ci * retry, needed for some broadcom wifi cards with Silicon 2958c2ecf20Sopenharmony_ci * Backplane bus where access to srom seems very slow */ 2968c2ecf20Sopenharmony_ci val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS); 2978c2ecf20Sopenharmony_ci val &= ~REG_TIMER_RETRY_MASK; 2988c2ecf20Sopenharmony_ci bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci /* enable memory decoder and bus mastering */ 3018c2ecf20Sopenharmony_ci val = bcm63xx_int_cfg_readl(PCI_COMMAND); 3028c2ecf20Sopenharmony_ci val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 3038c2ecf20Sopenharmony_ci bcm63xx_int_cfg_writel(val, PCI_COMMAND); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* enable read prefetching & disable byte swapping for bus 3068c2ecf20Sopenharmony_ci * mastering transfers */ 3078c2ecf20Sopenharmony_ci val = bcm_mpi_readl(MPI_PCIMODESEL_REG); 3088c2ecf20Sopenharmony_ci val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK; 3098c2ecf20Sopenharmony_ci val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK; 3108c2ecf20Sopenharmony_ci val &= ~MPI_PCIMODESEL_PREFETCH_MASK; 3118c2ecf20Sopenharmony_ci val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT); 3128c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_PCIMODESEL_REG); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* enable pci interrupt */ 3158c2ecf20Sopenharmony_ci val = bcm_mpi_readl(MPI_LOCINT_REG); 3168c2ecf20Sopenharmony_ci val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT); 3178c2ecf20Sopenharmony_ci bcm_mpi_writel(val, MPI_LOCINT_REG); 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci register_pci_controller(&bcm63xx_controller); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci#ifdef CONFIG_CARDBUS 3228c2ecf20Sopenharmony_ci register_pci_controller(&bcm63xx_cb_controller); 3238c2ecf20Sopenharmony_ci#endif 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci /* mark memory space used for IO mapping as reserved */ 3268c2ecf20Sopenharmony_ci request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE, 3278c2ecf20Sopenharmony_ci "bcm63xx PCI IO space"); 3288c2ecf20Sopenharmony_ci return 0; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic int __init bcm63xx_pci_init(void) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci if (!bcm63xx_pci_enabled) 3358c2ecf20Sopenharmony_ci return -ENODEV; 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci switch (bcm63xx_get_cpu_id()) { 3388c2ecf20Sopenharmony_ci case BCM6328_CPU_ID: 3398c2ecf20Sopenharmony_ci case BCM6362_CPU_ID: 3408c2ecf20Sopenharmony_ci return bcm63xx_register_pcie(); 3418c2ecf20Sopenharmony_ci case BCM3368_CPU_ID: 3428c2ecf20Sopenharmony_ci case BCM6348_CPU_ID: 3438c2ecf20Sopenharmony_ci case BCM6358_CPU_ID: 3448c2ecf20Sopenharmony_ci case BCM6368_CPU_ID: 3458c2ecf20Sopenharmony_ci return bcm63xx_register_pci(); 3468c2ecf20Sopenharmony_ci default: 3478c2ecf20Sopenharmony_ci return -ENODEV; 3488c2ecf20Sopenharmony_ci } 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ciarch_initcall(bcm63xx_pci_init); 352