146 lines
4.8 KiB
C
146 lines
4.8 KiB
C
/*
|
|
* <:copyright-BRCM:2011:GPL/GPL:standard
|
|
*
|
|
* Copyright (c) 2011 Broadcom Corporation
|
|
* All Rights Reserved
|
|
*
|
|
* Unless you and Broadcom execute a separate written software license
|
|
* agreement governing use of this software, this software is licensed
|
|
* to you under the terms of the GNU General Public License version 2
|
|
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
|
|
* with the following added to such license:
|
|
*
|
|
* As a special exception, the copyright holders of this software give
|
|
* you permission to link this software with independent modules, and
|
|
* to copy and distribute the resulting executable under terms of your
|
|
* choice, provided that you also meet, for each linked independent
|
|
* module, the terms and conditions of the license of that module.
|
|
* An independent module is a module which is not derived from this
|
|
* software. The special exception does not apply to any modifications
|
|
* of the software.
|
|
*
|
|
* Not withstanding the above, under no circumstances may you combine
|
|
* this software in any way with any other Broadcom software provided
|
|
* under a license other than the GPL, without Broadcom's express prior
|
|
* written consent.
|
|
*
|
|
* :>
|
|
*/
|
|
#include <linux/init.h>
|
|
#include <linux/types.h>
|
|
#include <linux/pci.h>
|
|
|
|
#include <bcm_intr.h>
|
|
#include <bcm_map_part.h>
|
|
#include <bcmpci.h>
|
|
|
|
static char irq_tab_bcm63xx[] __initdata = {
|
|
#if (defined(CONFIG_BCM96368) || defined(CONFIG_BCM96816))
|
|
[0] = INTERRUPT_ID_MPI,
|
|
[1] = INTERRUPT_ID_MPI,
|
|
[2] = INTERRUPT_ID_MPI,
|
|
#endif
|
|
#if defined(CONFIG_BCM96362) || defined(CONFIG_BCM963268)
|
|
[WLAN_ONCHIP_DEV_SLOT] = INTERRUPT_ID_WLAN,
|
|
#endif
|
|
#if defined(CONFIG_USB)
|
|
[USB_HOST_SLOT] = INTERRUPT_ID_USBH,
|
|
[USB20_HOST_SLOT] = INTERRUPT_ID_USBH20
|
|
#endif
|
|
};
|
|
|
|
|
|
static void bcm63xx_fixup_header(struct pci_dev *dev)
|
|
{
|
|
uint32 memaddr;
|
|
uint32 size;
|
|
|
|
memaddr = pci_resource_start(dev, 0);
|
|
size = pci_resource_len(dev, 0);
|
|
|
|
if (dev->bus->number == BCM_BUS_PCI) {
|
|
switch (PCI_SLOT(dev->devfn)) {
|
|
#if defined(CONFIG_USB)
|
|
case USB_HOST_SLOT:
|
|
dev->resource[0].flags |= IORESOURCE_PCI_FIXED; // prevent linux from reallocating resources
|
|
break;
|
|
|
|
case USB20_HOST_SLOT:
|
|
dev->resource[0].flags |= IORESOURCE_PCI_FIXED; // prevent linux from reallocating resources
|
|
break;
|
|
#endif
|
|
#if defined(WLAN_CHIPC_BASE)
|
|
case WLAN_ONCHIP_DEV_SLOT:
|
|
dev->resource[0].flags |= IORESOURCE_PCI_FIXED; // prevent linux from reallocating resources
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup_header);
|
|
|
|
|
|
static void bcm63xx_fixup_final(struct pci_dev *dev)
|
|
{
|
|
uint32 memaddr;
|
|
uint32 size;
|
|
#if defined(CONFIG_BCM96368)
|
|
uint32 resno;
|
|
#endif
|
|
|
|
memaddr = pci_resource_start(dev, 0);
|
|
size = pci_resource_len(dev, 0);
|
|
|
|
if (dev->bus->number == BCM_BUS_PCI) {
|
|
switch (PCI_SLOT(dev->devfn)) {
|
|
#if defined(CONFIG_BCM96368)
|
|
case 0:
|
|
// Move device in slot 0 to a different memory range
|
|
// In case this is a CB device, it will be accessed via l2pmremap1
|
|
// which will have CARDBUS_MEM bit set
|
|
for (resno = 0; resno < 6; resno++) {
|
|
if (dev->resource[resno].end && (dev->resource[resno].start < BCM_CB_MEM_BASE)) {
|
|
dev->resource[resno].start += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE);
|
|
dev->resource[resno].end += (BCM_CB_MEM_BASE - BCM_PCI_MEM_BASE);
|
|
dev->resource[resno].flags |= IORESOURCE_PCI_FIXED; // prevent linux from reallocating resources
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, bcm63xx_fixup_final);
|
|
|
|
|
|
#if defined(CONFIG_BCM96816)
|
|
static char irq_tab_pcie_bcm63xx_pcie_bus[] __initdata = {
|
|
/* SWITCH_8232104c DS Ports */
|
|
[BCM_BUS_PCIE_DEVICE+2] = 0, /*INTA*/
|
|
[BCM_BUS_PCIE_DEVICE+3] = 1, /*INTB*/
|
|
[BCM_BUS_PCIE_DEVICE+4] = 2 /*INTC*/
|
|
};
|
|
#endif /* defined(CONFIG_BCM96816) || defined(CONFIG_BCM96818) */
|
|
|
|
int pcibios_plat_dev_init(struct pci_dev *dev)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int __init pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
|
{
|
|
#if defined(CONFIG_BCM96816)
|
|
if (dev->bus->number >= BCM_BUS_PCIE_DEVICE) {
|
|
return INTERRUPT_ID_PCIE_A+(irq_tab_pcie_bcm63xx_pcie_bus[dev->bus->number]+slot)%4;
|
|
}
|
|
#endif
|
|
#if defined(CONFIG_BCM96362) || defined(CONFIG_BCM96328) || defined(CONFIG_BCM963268) || defined(CONFIG_BCM96828) || defined(CONFIG_BCM96818) || defined(UBUS2_PCIE)
|
|
if ((dev->bus->number >= BCM_BUS_PCIE_DEVICE) &&
|
|
((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)) {
|
|
return INTERRUPT_ID_PCIE_RC;
|
|
}
|
|
#endif
|
|
return irq_tab_bcm63xx[slot];
|
|
}
|
|
|