source: trunk/target/linux/brcm63xx/patches-2.6.27/004_add_pci_support.patch @ 13001

Last change on this file since 13001 was 13001, checked in by florian, 8 years ago

New Broadcom BCM63xx codebase, huge thanks to Maxime ;)

File size: 14.2 KB
  • arch/mips/bcm63xx/Kconfig

    From 2a7fa2dbbf68650644f807a50cc2d84ca30835c1 Mon Sep 17 00:00:00 2001
    From: Maxime Bizon <mbizon@freebox.fr>
    Date: Sun, 21 Sep 2008 04:47:13 +0200
    Subject: [PATCH] [MIPS] BCM63XX: Add PCI support.
    
    Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
    ---
     arch/mips/bcm63xx/Kconfig                       |    2 +
     arch/mips/bcm63xx/setup.c                       |    2 +
     arch/mips/pci/Makefile                          |    2 +
     arch/mips/pci/fixup-bcm63xx.c                   |   21 +++
     arch/mips/pci/ops-bcm63xx.c                     |  179 +++++++++++++++++++++++
     arch/mips/pci/pci-bcm63xx.c                     |  178 ++++++++++++++++++++++
     arch/mips/pci/pci-bcm63xx.h                     |   27 ++++
     include/asm-mips/mach-bcm63xx/bcm63xx_dev_pci.h |    6 +
     8 files changed, 417 insertions(+), 0 deletions(-)
     create mode 100644 arch/mips/pci/fixup-bcm63xx.c
     create mode 100644 arch/mips/pci/ops-bcm63xx.c
     create mode 100644 arch/mips/pci/pci-bcm63xx.c
     create mode 100644 arch/mips/pci/pci-bcm63xx.h
     create mode 100644 include/asm-mips/mach-bcm63xx/bcm63xx_dev_pci.h
    
    diff --git a/arch/mips/bcm63xx/Kconfig b/arch/mips/bcm63xx/Kconfig
    index e6d2699..7ca370a 100644
    a b menu "CPU support" 
    33 
    44config BCM63XX_CPU_6348 
    55        bool "support 6348 CPU" 
     6        select HW_HAS_PCI 
    67 
    78config BCM63XX_CPU_6358 
    89        bool "support 6358 CPU" 
     10        select HW_HAS_PCI 
    911endmenu 
  • arch/mips/bcm63xx/setup.c

    diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
    index 55c51a9..4d8b127 100644
    a b void __init plat_mem_setup(void) 
    105105        pm_power_off = bcm63xx_machine_halt; 
    106106 
    107107        set_io_port_base(0); 
     108        ioport_resource.start = 0; 
     109        ioport_resource.end = ~0; 
    108110} 
  • arch/mips/pci/Makefile

    diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
    index c8c32f4..0b688a8 100644
    a b obj-$(CONFIG_PCI_VR41XX) += ops-vr41xx.o pci-vr41xx.o 
    1616obj-$(CONFIG_MARKEINS)          += ops-emma2rh.o pci-emma2rh.o fixup-emma2rh.o 
    1717obj-$(CONFIG_PCI_TX4927)        += ops-tx4927.o 
    1818obj-$(CONFIG_BCM47XX)           += pci-bcm47xx.o 
     19obj-$(CONFIG_BCM63XX)           += pci-bcm63xx.o fixup-bcm63xx.o \ 
     20                                        ops-bcm63xx.o 
    1921 
    2022# 
    2123# These are still pretty much in the old state, watch, go blind. 
  • new file arch/mips/pci/fixup-bcm63xx.c

    diff --git a/arch/mips/pci/fixup-bcm63xx.c b/arch/mips/pci/fixup-bcm63xx.c
    new file mode 100644
    index 0000000..3408630
    - +  
     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 <bcm63xx_cpu.h> 
     12 
     13int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 
     14{ 
     15        return bcm63xx_get_irq_number(IRQ_PCI); 
     16} 
     17 
     18int pcibios_plat_dev_init(struct pci_dev *dev) 
     19{ 
     20        return 0; 
     21} 
  • new file arch/mips/pci/ops-bcm63xx.c

    diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c
    new file mode 100644
    index 0000000..f8dce9d
    - +  
     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 <linux/delay.h> 
     14#include <linux/io.h> 
     15 
     16#include "pci-bcm63xx.h" 
     17 
     18/* 
     19 * swizzle 32bits data to return only the needed part 
     20 */ 
     21static int postprocess_read(u32 data, int where, unsigned int size) 
     22{ 
     23        u32 ret; 
     24 
     25        ret = 0; 
     26        switch (size) { 
     27        case 1: 
     28                ret = (data >> ((where & 3) << 3)) & 0xff; 
     29                break; 
     30        case 2: 
     31                ret = (data >> ((where & 3) << 3)) & 0xffff; 
     32                break; 
     33        case 4: 
     34                ret = data; 
     35                break; 
     36        } 
     37        return ret; 
     38} 
     39 
     40static int preprocess_write(u32 orig_data, u32 val, int where, 
     41                            unsigned int size) 
     42{ 
     43        u32 ret; 
     44 
     45        ret = 0; 
     46        switch (size) { 
     47        case 1: 
     48                ret = (orig_data & ~(0xff << ((where & 3) << 3))) | 
     49                        (val << ((where & 3) << 3)); 
     50                break; 
     51        case 2: 
     52                ret = (orig_data & ~(0xffff << ((where & 3) << 3))) | 
     53                        (val << ((where & 3) << 3)); 
     54                break; 
     55        case 4: 
     56                ret = val; 
     57                break; 
     58        } 
     59        return ret; 
     60} 
     61 
     62/* 
     63 * setup hardware for a configuration cycle with given parameters 
     64 */ 
     65static int bcm63xx_setup_cfg_access(int type, unsigned int busn, 
     66                                    unsigned int devfn, int where) 
     67{ 
     68        unsigned int slot, func, reg; 
     69        u32 val; 
     70 
     71        slot = PCI_SLOT(devfn); 
     72        func = PCI_FUNC(devfn); 
     73        reg = where >> 2; 
     74 
     75        /* sanity check */ 
     76        if (slot > (MPI_L2PCFG_DEVNUM_MASK >> MPI_L2PCFG_DEVNUM_SHIFT)) 
     77                return 1; 
     78 
     79        if (func > (MPI_L2PCFG_FUNC_MASK >> MPI_L2PCFG_FUNC_SHIFT)) 
     80                return 1; 
     81 
     82        if (reg > (MPI_L2PCFG_REG_MASK >> MPI_L2PCFG_REG_SHIFT)) 
     83                return 1; 
     84 
     85        /* ok, setup config access */ 
     86        val = (reg << MPI_L2PCFG_REG_SHIFT); 
     87        val |= (func << MPI_L2PCFG_FUNC_SHIFT); 
     88        val |= (slot << MPI_L2PCFG_DEVNUM_SHIFT); 
     89        val |= MPI_L2PCFG_CFG_USEREG_MASK; 
     90        val |= MPI_L2PCFG_CFG_SEL_MASK; 
     91        /* type 0 cycle for local bus, type 1 cycle for anything else */ 
     92        if (type != 0) { 
     93                /* FIXME: how to specify bus ??? */ 
     94                val |= (1 << MPI_L2PCFG_CFG_TYPE_SHIFT); 
     95        } 
     96        bcm_mpi_writel(val, MPI_L2PCFG_REG); 
     97 
     98        return 0; 
     99} 
     100 
     101static int bcm63xx_do_cfg_read(int type, unsigned int busn, 
     102                                unsigned int devfn, int where, int size, 
     103                                u32 *val) 
     104{ 
     105        u32 data; 
     106 
     107        /* two phase cycle, first we write address, then read data at 
     108         * another location, caller already has a spinlock so no need 
     109         * to add one here  */ 
     110        if (bcm63xx_setup_cfg_access(type, busn, devfn, where)) 
     111                return PCIBIOS_DEVICE_NOT_FOUND; 
     112        iob(); 
     113        data = le32_to_cpu(__raw_readl(pci_iospace_start)); 
     114        /* restore IO space normal behaviour */ 
     115        bcm_mpi_writel(0, MPI_L2PCFG_REG); 
     116 
     117        *val = postprocess_read(data, where, size); 
     118 
     119        return PCIBIOS_SUCCESSFUL; 
     120} 
     121 
     122static int bcm63xx_do_cfg_write(int type, unsigned int busn, 
     123                                 unsigned int devfn, int where, int size, 
     124                                 u32 val) 
     125{ 
     126        u32 data; 
     127 
     128        /* two phase cycle, first we write address, then write data to 
     129         * another location, caller already has a spinlock so no need 
     130         * to add one here  */ 
     131        if (bcm63xx_setup_cfg_access(type, busn, devfn, where)) 
     132                return PCIBIOS_DEVICE_NOT_FOUND; 
     133        iob(); 
     134 
     135        data = le32_to_cpu(__raw_readl(pci_iospace_start)); 
     136        data = preprocess_write(data, val, where, size); 
     137 
     138        __raw_writel(cpu_to_le32(data), pci_iospace_start); 
     139        wmb(); 
     140        /* no way to know the access is done, we have to wait */ 
     141        udelay(500); 
     142        /* restore IO space normal behaviour */ 
     143        bcm_mpi_writel(0, MPI_L2PCFG_REG); 
     144 
     145        return PCIBIOS_SUCCESSFUL; 
     146} 
     147 
     148static int bcm63xx_pci_read(struct pci_bus *bus, unsigned int devfn, 
     149                             int where, int size, u32 *val) 
     150{ 
     151        int type; 
     152 
     153        type = bus->parent ? 1 : 0; 
     154 
     155        if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) 
     156                return PCIBIOS_DEVICE_NOT_FOUND; 
     157 
     158        return bcm63xx_do_cfg_read(type, bus->number, devfn, 
     159                                    where, size, val); 
     160} 
     161 
     162static int bcm63xx_pci_write(struct pci_bus *bus, unsigned int devfn, 
     163                              int where, int size, u32 val) 
     164{ 
     165        int type; 
     166 
     167        type = bus->parent ? 1 : 0; 
     168 
     169        if (type == 0 && PCI_SLOT(devfn) == CARDBUS_PCI_IDSEL) 
     170                return PCIBIOS_DEVICE_NOT_FOUND; 
     171 
     172        return bcm63xx_do_cfg_write(type, bus->number, devfn, 
     173                                     where, size, val); 
     174} 
     175 
     176struct pci_ops bcm63xx_pci_ops = { 
     177        .read   = bcm63xx_pci_read, 
     178        .write  = bcm63xx_pci_write 
     179}; 
  • new file arch/mips/pci/pci-bcm63xx.c

    diff --git a/arch/mips/pci/pci-bcm63xx.c b/arch/mips/pci/pci-bcm63xx.c
    new file mode 100644
    index 0000000..52bac8e
    - +  
     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/* allow PCI to be disabled at runtime depending on board nvram 
     18 * configuration */ 
     19int bcm63xx_pci_enabled = 0; 
     20 
     21static struct resource bcm_pci_mem_resource = { 
     22        .name   = "bcm63xx PCI memory space", 
     23        .start  = BCM_PCI_MEM_BASE_PA, 
     24        .end    = BCM_PCI_MEM_END_PA, 
     25        .flags  = IORESOURCE_MEM 
     26}; 
     27 
     28static struct resource bcm_pci_io_resource = { 
     29        .name   = "bcm63xx PCI IO space", 
     30        .start  = BCM_PCI_IO_BASE_PA, 
     31        .end    = BCM_PCI_IO_END_PA, 
     32        .flags  = IORESOURCE_IO 
     33}; 
     34 
     35struct pci_controller bcm63xx_controller = { 
     36        .pci_ops        = &bcm63xx_pci_ops, 
     37        .io_resource    = &bcm_pci_io_resource, 
     38        .mem_resource   = &bcm_pci_mem_resource, 
     39}; 
     40 
     41static u32 bcm63xx_int_cfg_readl(u32 reg) 
     42{ 
     43        u32 tmp; 
     44 
     45        tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; 
     46        tmp |= MPI_PCICFGCTL_WRITEEN_MASK; 
     47        bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG); 
     48        iob(); 
     49        return bcm_mpi_readl(MPI_PCICFGDATA_REG); 
     50} 
     51 
     52static void bcm63xx_int_cfg_writel(u32 val, u32 reg) 
     53{ 
     54        u32 tmp; 
     55 
     56        tmp = reg & MPI_PCICFGCTL_CFGADDR_MASK; 
     57        tmp |=  MPI_PCICFGCTL_WRITEEN_MASK; 
     58        bcm_mpi_writel(tmp, MPI_PCICFGCTL_REG); 
     59        bcm_mpi_writel(val, MPI_PCICFGDATA_REG); 
     60} 
     61 
     62void __iomem *pci_iospace_start; 
     63 
     64static int __init bcm63xx_pci_init(void) 
     65{ 
     66        unsigned int mem_size; 
     67        u32 val; 
     68 
     69        if (!BCMCPU_IS_6348() && !BCMCPU_IS_6358()) 
     70                return -ENODEV; 
     71 
     72        if (!bcm63xx_pci_enabled) 
     73                return -ENODEV; 
     74 
     75        /* 
     76         * configuration  access are  done through  IO space,  remap 4 
     77         * first bytes to access it from CPU. 
     78         * 
     79         * this means that  no io access from CPU  should happen while 
     80         * we do a configuration cycle,  but there's no way we can add 
     81         * a spinlock for each io access, so this is currently kind of 
     82         * broken on SMP. 
     83         */ 
     84        pci_iospace_start = ioremap_nocache(BCM_PCI_IO_BASE_PA, 4); 
     85        if (!pci_iospace_start) 
     86                return -ENOMEM; 
     87 
     88        /* setup local bus to PCI access (PCI memory) */ 
     89        val = BCM_PCI_MEM_BASE_PA & MPI_L2P_BASE_MASK; 
     90        bcm_mpi_writel(val, MPI_L2PMEMBASE1_REG); 
     91        bcm_mpi_writel(~(BCM_PCI_MEM_SIZE - 1), MPI_L2PMEMRANGE1_REG); 
     92        bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PMEMREMAP1_REG); 
     93 
     94        /* set Cardbus IDSEL (type 0 cfg access on primary bus for 
     95         * this IDSEL will be done on Cardbus instead) */ 
     96        val = bcm_pcmcia_readl(PCMCIA_C1_REG); 
     97        val &= ~PCMCIA_C1_CBIDSEL_MASK; 
     98        val |= (CARDBUS_PCI_IDSEL << PCMCIA_C1_CBIDSEL_SHIFT); 
     99        bcm_pcmcia_writel(val, PCMCIA_C1_REG); 
     100 
     101        /* disable second access windows */ 
     102        bcm_mpi_writel(0, MPI_L2PMEMREMAP2_REG); 
     103 
     104        /* setup local bus  to PCI access (IO memory),  we have only 1 
     105         * IO window  for both PCI  and cardbus, but it  cannot handle 
     106         * both  at the  same time,  assume standard  PCI for  now, if 
     107         * cardbus card has  IO zone, PCI fixup will  change window to 
     108         * cardbus */ 
     109        val = BCM_PCI_IO_BASE_PA & MPI_L2P_BASE_MASK; 
     110        bcm_mpi_writel(val, MPI_L2PIOBASE_REG); 
     111        bcm_mpi_writel(~(BCM_PCI_IO_SIZE - 1), MPI_L2PIORANGE_REG); 
     112        bcm_mpi_writel(val | MPI_L2PREMAP_ENABLED_MASK, MPI_L2PIOREMAP_REG); 
     113 
     114        /* enable PCI related GPIO pins */ 
     115        bcm_mpi_writel(MPI_LOCBUSCTL_EN_PCI_GPIO_MASK, MPI_LOCBUSCTL_REG); 
     116 
     117        /* setup PCI to local bus access, used by PCI device to target 
     118         * local RAM while bus mastering */ 
     119        bcm63xx_int_cfg_writel(0, PCI_BASE_ADDRESS_3); 
     120        if (BCMCPU_IS_6358()) 
     121                val = MPI_SP0_REMAP_ENABLE_MASK; 
     122        else 
     123                val = 0; 
     124        bcm_mpi_writel(val, MPI_SP0_REMAP_REG); 
     125 
     126        bcm63xx_int_cfg_writel(0x0, PCI_BASE_ADDRESS_4); 
     127        bcm_mpi_writel(0, MPI_SP1_REMAP_REG); 
     128 
     129        mem_size = bcm63xx_get_memory_size(); 
     130 
     131        /* 6348 before rev b0 exposes only 16 MB of RAM memory through 
     132         * PCI, throw a warning if we have more memory */ 
     133        if (BCMCPU_IS_6348() && (bcm63xx_get_cpu_rev() & 0xf0) == 0xa0) { 
     134                if (mem_size > (16 * 1024 * 1024)) 
     135                        printk(KERN_WARNING "bcm63xx: this CPU " 
     136                               "revision cannot handle more than 16MB " 
     137                               "of RAM for PCI bus mastering\n"); 
     138        } else { 
     139                /* setup sp0 range to local RAM size */ 
     140                bcm_mpi_writel(~(mem_size - 1), MPI_SP0_RANGE_REG); 
     141                bcm_mpi_writel(0, MPI_SP1_RANGE_REG); 
     142        } 
     143 
     144        /* change  host bridge  retry  counter to  infinite number  of 
     145         * retry,  needed for  some broadcom  wifi cards  with Silicon 
     146         * Backplane bus where access to srom seems very slow  */ 
     147        val = bcm63xx_int_cfg_readl(BCMPCI_REG_TIMERS); 
     148        val &= ~REG_TIMER_RETRY_MASK; 
     149        bcm63xx_int_cfg_writel(val, BCMPCI_REG_TIMERS); 
     150 
     151        /* enable memory decoder and bus mastering */ 
     152        val = bcm63xx_int_cfg_readl(PCI_COMMAND); 
     153        val |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 
     154        bcm63xx_int_cfg_writel(val, PCI_COMMAND); 
     155 
     156        /* enable read prefetching & disable byte swapping for bus 
     157         * mastering transfers */ 
     158        val = bcm_mpi_readl(MPI_PCIMODESEL_REG); 
     159        val &= ~MPI_PCIMODESEL_BAR1_NOSWAP_MASK; 
     160        val &= ~MPI_PCIMODESEL_BAR2_NOSWAP_MASK; 
     161        val &= ~MPI_PCIMODESEL_PREFETCH_MASK; 
     162        val |= (8 << MPI_PCIMODESEL_PREFETCH_SHIFT); 
     163        bcm_mpi_writel(val, MPI_PCIMODESEL_REG); 
     164 
     165        /* enable pci interrupt */ 
     166        val = bcm_mpi_readl(MPI_LOCINT_REG); 
     167        val |= MPI_LOCINT_MASK(MPI_LOCINT_EXT_PCI_INT); 
     168        bcm_mpi_writel(val, MPI_LOCINT_REG); 
     169 
     170        register_pci_controller(&bcm63xx_controller); 
     171 
     172        /* mark memory space used for IO mapping as reserved */ 
     173        request_mem_region(BCM_PCI_IO_BASE_PA, BCM_PCI_IO_SIZE, 
     174                           "bcm63xx PCI IO space"); 
     175        return 0; 
     176} 
     177 
     178arch_initcall(bcm63xx_pci_init); 
  • new file arch/mips/pci/pci-bcm63xx.h

    diff --git a/arch/mips/pci/pci-bcm63xx.h b/arch/mips/pci/pci-bcm63xx.h
    new file mode 100644
    index 0000000..a6e594e
    - +  
     1#ifndef PCI_BCM63XX_H_ 
     2#define PCI_BCM63XX_H_ 
     3 
     4#include <bcm63xx_cpu.h> 
     5#include <bcm63xx_io.h> 
     6#include <bcm63xx_regs.h> 
     7#include <bcm63xx_dev_pci.h> 
     8 
     9/* 
     10 * Cardbus shares  the PCI bus, but has  no IDSEL, so a  special id is 
     11 * reserved for it.  If you have a standard PCI device at this id, you 
     12 * need to change the following definition. 
     13 */ 
     14#define CARDBUS_PCI_IDSEL       0x8 
     15 
     16/* 
     17 * defined in ops-bcm63xx.c 
     18 */ 
     19extern struct pci_ops bcm63xx_pci_ops; 
     20extern struct pci_ops bcm63xx_cb_ops; 
     21 
     22/* 
     23 * defined in pci-bcm63xx.c 
     24 */ 
     25extern void __iomem *pci_iospace_start; 
     26 
     27#endif /* ! PCI_BCM63XX_H_ */ 
  • new file include/asm-mips/mach-bcm63xx/bcm63xx_dev_pci.h

    diff --git a/include/asm-mips/mach-bcm63xx/bcm63xx_dev_pci.h b/include/asm-mips/mach-bcm63xx/bcm63xx_dev_pci.h
    new file mode 100644
    index 0000000..c549344
    - +  
     1#ifndef BCM63XX_DEV_PCI_H_ 
     2#define BCM63XX_DEV_PCI_H_ 
     3 
     4extern int bcm63xx_pci_enabled; 
     5 
     6#endif /* BCM63XX_DEV_PCI_H_ */ 
Note: See TracBrowser for help on using the repository browser.