linux/arch/mips/pci/pci-bcm63xx.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 */
   8
   9#include <linux/types.h>
  10#include <linux/pci.h>
  11#include <linux/kernel.h>
  12#include <linux/init.h>
  13#include <asm/bootinfo.h>
  14
  15#include "pci-bcm63xx.h"
  16
  17/*
  18 * Allow PCI to be disabled at runtime depending on board nvram
  19 * configuration
  20 */
  21int bcm63xx_pci_enabled;
  22
  23static struct resource bcm_pci_mem_resource = {
  24        .name   = "bcm63xx PCI memory space",
  25        .start  = BCM_PCI_MEM_BASE_PA,
  26        .end    = BCM_PCI_MEM_END_PA,
  27        .flags  = IORESOURCE_MEM
  28};
  29
  30static struct resource bcm_pci_io_resource = {
  31        .name   = "bcm63xx PCI IO space",
  32        .start  = BCM_PCI_IO_BASE_PA,
  33#ifdef CONFIG_CARDBUS
  34        .end    = BCM_PCI_IO_HALF_PA,
  35#else
  36        .end    = BCM_PCI_IO_END_PA,
  37#endif
  38        .flags  = IORESOURCE_IO
  39};
  40
  41struct pci_controller bcm63xx_controller = {
  42        .pci_ops        = &bcm63xx_pci_ops,
  43        .io_resource    = &bcm_pci_io_resource,
  44        .mem_resource   = &bcm_pci_mem_resource,
  45};
  46
  47/*
  48 * We handle cardbus  via a fake Cardbus bridge,  memory and io spaces
  49 * have to be  clearly separated from PCI one  since we have different
  50 * memory decoder.
  51 */
  52#ifdef CONFIG_CARDBUS
  53static struct resource bcm_cb_mem_resource = {
  54        .name   = "bcm63xx Cardbus memory space",
  55        .start  = BCM_CB_MEM_BASE_PA,
  56        .end    = BCM_CB_MEM_END_PA,
  57        .flags  = IORESOURCE_MEM
  58};
  59
  60static struct resource bcm_cb_io_resource = {
  61        .name   = "bcm63xx Cardbus IO space",
  62        .start  = BCM_PCI_IO_HALF_PA + 1,
  63        .end    = BCM_PCI_IO_END_PA,
  64        .flags  = IORESOURCE_IO
  65};
  66
  67struct pci_controller bcm63xx_cb_controller = {
  68        .pci_ops        = &bcm63xx_cb_ops,
  69        .io_resource    = &bcm_cb_io_resource,
  70        .mem_resource   = &bcm_cb_mem_resource,
  71};
  72#endif
  73
  74static u32 bcm63xx_int_cfg_readl(u32 reg)
  75{
  76        u32 tmp;
  77
  78        tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
  79        tmp |= MPI_PCICFGCTL_WRITEEN_MASK;
  80        bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG);
  81        iob();
  82        return bcm_mpi_readl(MPI_PCICFGDATA_REG);
  83}
  84
  85static void bcm63xx_int_cfg_writel(u32 val, u32 reg)
  86{
  87        u32 tmp;
  88
  89        tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK;
  90        tmp |=  MPI_PCICFGCTL_WRITEEN_MASK;
  91        bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG);
  92        bcm_mpi_writel(val, MPI_PCICFGDATA_REG);
  93}
  94
  95void __iomem *pci_iospace_start;
  96
  97static int __init bcm63xx_pci_init(void)
  98{
  99        unsigned int mem_size;
 100        u32 val;
 101
 102        if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358())
 103                return -ENODEV;
 104
 105        if (!bcm63xx_pci_enabled)
 106                return -ENODEV;
 107
 108        /*
 109         * configuration  access are  done through  IO space,  remap 4
 110         * first bytes to access it from CPU.
 111         *
 112         * this means that  no io access from CPU  should happen while
 113         * we do a configuration cycle,  but there's no way we can add
 114         * a spinlock for each io access, so this is currently kind of
 115         * broken on SMP.
 116         */
 117        pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4);
 118        if (!pci_iospace_start)
 119                return -ENOMEM;
 120
 121        /* setup local bus to PCI access (PCI memory) */
 122        val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK;
 123        bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG);
 124        bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG);
 125        bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG);
 126
 127        /* set Cardbus IDSEL (type 0 cfg access on primary bus for
 128         * this IDSEL will be done on Cardbus instead) */
 129        val = bcm_pcmcia_readl(PCMCIA_C1_REG);
 130        val &= ~PCMCIA_C1_CBIDSEL_MASK;
 131        val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT);
 132        bcm_pcmcia_writel(val, PCMCIA_C1_REG);
 133
 134#ifdef CONFIG_CARDBUS
 135        /* setup local bus to PCI access (Cardbus memory) */
 136        val = BCM_CB_MEM_BASE_PA & MPI_L2P_BASE_MASK;
 137        bcm_mpi_writel(val, MPI_L2PMEMBASE2_REG);
 138        bcm_mpi_writel(~(BCM_CB_MEM_SIZE - 1), MPI_L2PMEMRANGE2_REG);
 139        val |= MPI_L2PREMAP_ENABLED_MASK | MPI_L2PREMAP_IS_CARDBUS_MASK;
 140        bcm_mpi_writel(val, MPI_L2PMEMREMAP2_REG);
 141#else
 142        /* disable second access windows */
 143        bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG);
 144#endif
 145
 146        /* setup local bus  to PCI access (IO memory),  we have only 1
 147         * IO window  for both PCI  and cardbus, but it  cannot handle
 148         * both  at the  same time,  assume standard  PCI for  now, if
 149         * cardbus card has  IO zone, PCI fixup will  change window to
 150         * cardbus */
 151        val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK;
 152        bcm_mpi_writel(val, MPI_L2PIOBASE_REG);
 153        bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG);
 154        bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG);
 155
 156        /* enable PCI related GPIO pins */
 157        bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG);
 158
 159        /* setup PCI to local bus access, used by PCI device to target
 160         * local RAM while bus mastering */
 161        bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3);
 162        if (BCMCPU_IS_6358())
 163                val = MPI_SP0_REMAP_ENABLE_MASK;
 164        else
 165                val = 0;
 166        bcm_mpi_writel(val, MPI_SP0_REMAP_REG);
 167
 168        bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4);
 169        bcm_mpi_writel(0, MPI_SP1_REMAP_REG);
 170
 171        mem_size = bcm63xx_get_memory_size();
 172
 173        /* 6348 before rev b0 exposes only 16 MB of RAM memory through
 174         * PCI, throw a warning if we have more memory */
 175        if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) {
 176                if (mem_size > (16 * 1024 * 1024))
 177                        printk(KERN_WARNING "bcm63xx: this CPU "
 178                               "revision cannot handle more than 16MB "
 179                               "of RAM for PCI bus mastering\n");
 180        } else {
 181                /* setup sp0 range to local RAM size */
 182                bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG);
 183                bcm_mpi_writel(0, MPI_SP1_RANGE_REG);
 184        }
 185
 186        /* change  host bridge  retry  counter to  infinite number  of
 187         * retry,  needed for  some broadcom  wifi cards  with Silicon
 188         * Backplane bus where access to srom seems very slow  */
 189        val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS);
 190        val &= ~REG_TIMER_RETRY_MASK;
 191        bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS);
 192
 193        /* enable memory decoder and bus mastering */
 194        val = bcm63xx_int_cfg_readl(PCI_COMMAND);
 195        val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
 196        bcm63xx_int_cfg_writel(val, PCI_COMMAND);
 197
 198        /* enable read prefetching & disable byte swapping for bus
 199         * mastering transfers */
 200        val = bcm_mpi_readl(MPI_PCIMODESEL_REG);
 201        val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK;
 202        val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK;
 203        val &= ~MPI_PCIMODESEL_PREFETCH_MASK;
 204        val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT);
 205        bcm_mpi_writel(val, MPI_PCIMODESEL_REG);
 206
 207        /* enable pci interrupt */
 208        val = bcm_mpi_readl(MPI_LOCINT_REG);
 209        val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT);
 210        bcm_mpi_writel(val, MPI_LOCINT_REG);
 211
 212        register_pci_controller(&bcm63xx_controller);
 213
 214#ifdef CONFIG_CARDBUS
 215        register_pci_controller(&bcm63xx_cb_controller);
 216#endif
 217
 218        /* mark memory space used for IO mapping as reserved */
 219        request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE,
 220                           "bcm63xx PCI IO space");
 221        return 0;
 222}
 223
 224arch_initcall(bcm63xx_pci_init);
 225