Skip to content

Commit

Permalink
bcma: add PCIe host controller
Browse files Browse the repository at this point in the history
Some SoCs have a PCIe host controller to make it possible to attach
some other devices to it, like an other Wifi card.
This code was tested with an Netgear WNDR3400 (bcm4716 based), but
should work with all bcma based SoCs.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
hauke authored and linvjw committed Feb 6, 2012
1 parent d1a7a8e commit 49dc957
Show file tree
Hide file tree
Showing 6 changed files with 690 additions and 39 deletions.
49 changes: 44 additions & 5 deletions arch/mips/pci/pci-bcm47xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,20 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/ssb/ssb.h>
#include <linux/bcma/bcma.h>
#include <bcm47xx.h>

int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
return 0;
}

int pcibios_plat_dev_init(struct pci_dev *dev)
{
#ifdef CONFIG_BCM47XX_SSB
static int bcm47xx_pcibios_plat_dev_init_ssb(struct pci_dev *dev)
{
int res;
u8 slot, pin;

if (bcm47xx_bus_type != BCM47XX_BUS_TYPE_SSB)
return 0;

res = ssb_pcibios_plat_dev_init(dev);
if (res < 0) {
printk(KERN_ALERT "PCI: Failed to init device %s\n",
Expand All @@ -60,6 +58,47 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
}

dev->irq = res;
return 0;
}
#endif

#ifdef CONFIG_BCM47XX_BCMA
static int bcm47xx_pcibios_plat_dev_init_bcma(struct pci_dev *dev)
{
int res;

res = bcma_core_pci_plat_dev_init(dev);
if (res < 0) {
printk(KERN_ALERT "PCI: Failed to init device %s\n",
pci_name(dev));
return res;
}

res = bcma_core_pci_pcibios_map_irq(dev);

/* IRQ-0 and IRQ-1 are software interrupts. */
if (res < 2) {
printk(KERN_ALERT "PCI: Failed to map IRQ of device %s\n",
pci_name(dev));
return res;
}

dev->irq = res;
return 0;
}
#endif

int pcibios_plat_dev_init(struct pci_dev *dev)
{
#ifdef CONFIG_BCM47XX_SSB
if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_SSB)
return bcm47xx_pcibios_plat_dev_init_ssb(dev);
else
#endif
#ifdef CONFIG_BCM47XX_BCMA
if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA)
return bcm47xx_pcibios_plat_dev_init_bcma(dev);
else
#endif
return 0;
}
1 change: 1 addition & 0 deletions drivers/bcma/bcma_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ extern void __exit bcma_host_pci_exit(void);
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);

#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc);
void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc);
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */

Expand Down
38 changes: 5 additions & 33 deletions drivers/bcma/driver_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Broadcom specific AMBA
* PCI Core
*
* Copyright 2005, Broadcom Corporation
* Copyright 2005, 2011, Broadcom Corporation
* Copyright 2006, 2007, Michael Buesch <m@bues.ch>
* Copyright 2011, 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
Expand Down Expand Up @@ -179,47 +179,19 @@ static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc)
bcma_pcicore_serdes_workaround(pc);
}

static bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
{
struct bcma_bus *bus = pc->core->bus;
u16 chipid_top;

chipid_top = (bus->chipinfo.id & 0xFF00);
if (chipid_top != 0x4700 &&
chipid_top != 0x5300)
return false;

#ifdef CONFIG_SSB_DRIVER_PCICORE
if (bus->sprom.boardflags_lo & SSB_BFL_NOPCI)
return false;
#endif /* CONFIG_SSB_DRIVER_PCICORE */

#if 0
/* TODO: on BCMA we use address from EROM instead of magic formula */
u32 tmp;
return !mips_busprobe32(tmp, (bus->mmio +
(pc->core->core_index * BCMA_CORE_SIZE)));
#endif

return true;
}

void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc)
{
if (pc->setup_done)
return;

if (bcma_core_pci_is_in_hostmode(pc)) {
#ifdef CONFIG_BCMA_DRIVER_PCI_HOSTMODE
pc->hostmode = bcma_core_pci_is_in_hostmode(pc);
if (pc->hostmode)
bcma_core_pci_hostmode_init(pc);
#else
pr_err("Driver compiled without support for hostmode PCI\n");
#endif /* CONFIG_BCMA_DRIVER_PCI_HOSTMODE */
} else {
bcma_core_pci_clientmode_init(pc);
}

pc->setup_done = true;
if (!pc->hostmode)
bcma_core_pci_clientmode_init(pc);
}

int bcma_core_pci_irq_ctl(struct bcma_drv_pci *pc, struct bcma_device *core,
Expand Down
Loading

0 comments on commit 49dc957

Please sign in to comment.