summaryrefslogtreecommitdiffstats
path: root/drivers/bcma
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/bcma')
-rw-r--r--drivers/bcma/Makefile1
-rw-r--r--drivers/bcma/bcma_private.h18
-rw-r--r--drivers/bcma/driver_chipcommon_b.c61
-rw-r--r--drivers/bcma/driver_gpio.c11
-rw-r--r--drivers/bcma/driver_mips.c62
-rw-r--r--drivers/bcma/host_pci.c4
-rw-r--r--drivers/bcma/host_soc.c99
-rw-r--r--drivers/bcma/main.c150
-rw-r--r--drivers/bcma/scan.c34
9 files changed, 386 insertions, 54 deletions
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile
index 91290f7f61b8..838b4b9d352f 100644
--- a/drivers/bcma/Makefile
+++ b/drivers/bcma/Makefile
@@ -1,5 +1,6 @@
bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
+bcma-y += driver_chipcommon_b.o
bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
bcma-y += driver_pci.o
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index 09b632ad0fe2..b6412b2d748d 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -50,6 +50,10 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
extern struct platform_device bcma_pflash_dev;
#endif /* CONFIG_BCMA_DRIVER_MIPS */
+/* driver_chipcommon_b.c */
+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb);
+
/* driver_chipcommon_pmu.c */
u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
@@ -84,6 +88,20 @@ extern int __init bcma_host_pci_init(void);
extern void __exit bcma_host_pci_exit(void);
#endif /* CONFIG_BCMA_HOST_PCI */
+/* host_soc.c */
+#if defined(CONFIG_BCMA_HOST_SOC) && defined(CONFIG_OF)
+extern int __init bcma_host_soc_register_driver(void);
+extern void __exit bcma_host_soc_unregister_driver(void);
+#else
+static inline int __init bcma_host_soc_register_driver(void)
+{
+ return 0;
+}
+static inline void __exit bcma_host_soc_unregister_driver(void)
+{
+}
+#endif /* CONFIG_BCMA_HOST_SOC && CONFIG_OF */
+
/* driver_pci.c */
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
diff --git a/drivers/bcma/driver_chipcommon_b.c b/drivers/bcma/driver_chipcommon_b.c
new file mode 100644
index 000000000000..c20b5f4ff290
--- /dev/null
+++ b/drivers/bcma/driver_chipcommon_b.c
@@ -0,0 +1,61 @@
+/*
+ * Broadcom specific AMBA
+ * ChipCommon B Unit driver
+ *
+ * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ */
+
+#include "bcma_private.h"
+#include <linux/export.h>
+#include <linux/bcma/bcma.h>
+
+static bool bcma_wait_reg(struct bcma_bus *bus, void __iomem *addr, u32 mask,
+ u32 value, int timeout)
+{
+ unsigned long deadline = jiffies + timeout;
+ u32 val;
+
+ do {
+ val = readl(addr);
+ if ((val & mask) == value)
+ return true;
+ cpu_relax();
+ udelay(10);
+ } while (!time_after_eq(jiffies, deadline));
+
+ bcma_err(bus, "Timeout waiting for register %p\n", addr);
+
+ return false;
+}
+
+void bcma_chipco_b_mii_write(struct bcma_drv_cc_b *ccb, u32 offset, u32 value)
+{
+ struct bcma_bus *bus = ccb->core->bus;
+
+ writel(offset, ccb->mii + 0x00);
+ bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
+ writel(value, ccb->mii + 0x04);
+ bcma_wait_reg(bus, ccb->mii + 0x00, 0x0100, 0x0000, 100);
+}
+EXPORT_SYMBOL_GPL(bcma_chipco_b_mii_write);
+
+int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb)
+{
+ if (ccb->setup_done)
+ return 0;
+
+ ccb->setup_done = 1;
+ ccb->mii = ioremap_nocache(ccb->core->addr_s[1], BCMA_CORE_SIZE);
+ if (!ccb->mii)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void bcma_core_chipcommon_b_free(struct bcma_drv_cc_b *ccb)
+{
+ if (ccb->mii)
+ iounmap(ccb->mii);
+}
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index aec9f850b4a8..706b9ae0dcfb 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -76,7 +76,7 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
}
-#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC)
+#if IS_BUILTIN(CONFIG_BCM47XX)
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
{
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
@@ -215,9 +215,13 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->set = bcma_gpio_set_value;
chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output;
-#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC)
+#if IS_BUILTIN(CONFIG_BCM47XX)
chip->to_irq = bcma_gpio_to_irq;
#endif
+#if IS_BUILTIN(CONFIG_OF)
+ if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
+ chip->of_node = cc->core->dev.of_node;
+#endif
switch (cc->core->bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM5357:
case BCMA_CHIP_ID_BCM53572:
@@ -251,5 +255,6 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
int bcma_gpio_unregister(struct bcma_drv_cc *cc)
{
bcma_gpio_irq_domain_exit(cc);
- return gpiochip_remove(&cc->gpio);
+ gpiochip_remove(&cc->gpio);
+ return 0;
}
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index 11115bbe115c..004d6aa671ce 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -21,6 +21,14 @@
#include <linux/serial_reg.h>
#include <linux/time.h>
+enum bcma_boot_dev {
+ BCMA_BOOT_DEV_UNK = 0,
+ BCMA_BOOT_DEV_ROM,
+ BCMA_BOOT_DEV_PARALLEL,
+ BCMA_BOOT_DEV_SERIAL,
+ BCMA_BOOT_DEV_NAND,
+};
+
static const char * const part_probes[] = { "bcm47xxpart", NULL };
static struct physmap_flash_data bcma_pflash_data = {
@@ -229,11 +237,51 @@ u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
}
EXPORT_SYMBOL(bcma_cpu_clock);
+static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus)
+{
+ struct bcma_drv_cc *cc = &bus->drv_cc;
+ u8 cc_rev = cc->core->id.rev;
+
+ if (cc_rev == 42) {
+ struct bcma_device *core;
+
+ core = bcma_find_core(bus, BCMA_CORE_NS_ROM);
+ if (core) {
+ switch (bcma_aread32(core, BCMA_IOST) &
+ BCMA_NS_ROM_IOST_BOOT_DEV_MASK) {
+ case BCMA_NS_ROM_IOST_BOOT_DEV_NOR:
+ return BCMA_BOOT_DEV_SERIAL;
+ case BCMA_NS_ROM_IOST_BOOT_DEV_NAND:
+ return BCMA_BOOT_DEV_NAND;
+ case BCMA_NS_ROM_IOST_BOOT_DEV_ROM:
+ default:
+ return BCMA_BOOT_DEV_ROM;
+ }
+ }
+ } else {
+ if (cc_rev == 38) {
+ if (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)
+ return BCMA_BOOT_DEV_NAND;
+ else if (cc->status & BIT(5))
+ return BCMA_BOOT_DEV_ROM;
+ }
+
+ if ((cc->capabilities & BCMA_CC_CAP_FLASHT) ==
+ BCMA_CC_FLASHT_PARA)
+ return BCMA_BOOT_DEV_PARALLEL;
+ else
+ return BCMA_BOOT_DEV_SERIAL;
+ }
+
+ return BCMA_BOOT_DEV_SERIAL;
+}
+
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
{
struct bcma_bus *bus = mcore->core->bus;
struct bcma_drv_cc *cc = &bus->drv_cc;
struct bcma_pflash *pflash = &cc->pflash;
+ enum bcma_boot_dev boot_dev;
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
case BCMA_CC_FLASHT_STSER:
@@ -269,6 +317,20 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
bcma_nflash_init(cc);
}
}
+
+ /* Determine flash type this SoC boots from */
+ boot_dev = bcma_boot_dev(bus);
+ switch (boot_dev) {
+ case BCMA_BOOT_DEV_PARALLEL:
+ case BCMA_BOOT_DEV_SERIAL:
+ /* TODO: Init NVRAM using BCMA_SOC_FLASH2 window */
+ break;
+ case BCMA_BOOT_DEV_NAND:
+ /* TODO: Init NVRAM using BCMA_SOC_FLASH1 window */
+ break;
+ default:
+ break;
+ }
}
void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 294a7dd25190..1e5ac0a79696 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -208,6 +208,9 @@ static int bcma_host_pci_probe(struct pci_dev *dev,
bus->boardinfo.vendor = bus->host_pci->subsystem_vendor;
bus->boardinfo.type = bus->host_pci->subsystem_device;
+ /* Initialize struct, detect chip */
+ bcma_init_bus(bus);
+
/* Register */
err = bcma_bus_register(bus);
if (err)
@@ -282,6 +285,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xA8DB */
{ 0, },
};
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
index 3475e600011a..335cbcfd945b 100644
--- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c
@@ -7,6 +7,9 @@
#include "bcma_private.h"
#include "scan.h"
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
#include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_soc.h>
@@ -134,12 +137,16 @@ static void bcma_host_soc_block_write(struct bcma_device *core,
static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
{
+ if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
+ return ~0;
return readl(core->io_wrap + offset);
}
static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
u32 value)
{
+ if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
+ return;
writel(value, core->io_wrap + offset);
}
@@ -161,7 +168,6 @@ static const struct bcma_host_ops bcma_host_soc_ops = {
int __init bcma_host_soc_register(struct bcma_soc *soc)
{
struct bcma_bus *bus = &soc->bus;
- int err;
/* iomap only first core. We have to read some register on this core
* to scan the bus.
@@ -173,11 +179,100 @@ int __init bcma_host_soc_register(struct bcma_soc *soc)
/* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops;
+ bus->host_pdev = NULL;
- /* Register */
+ /* Initialize struct, detect chip */
+ bcma_init_bus(bus);
+
+ return 0;
+}
+
+int __init bcma_host_soc_init(struct bcma_soc *soc)
+{
+ struct bcma_bus *bus = &soc->bus;
+ int err;
+
+ /* Scan bus and initialize it */
err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
if (err)
iounmap(bus->mmio);
return err;
}
+
+#ifdef CONFIG_OF
+static int bcma_host_soc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct bcma_bus *bus;
+ int err;
+
+ /* Alloc */
+ bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+ /* Map MMIO */
+ bus->mmio = of_iomap(np, 0);
+ if (!bus->mmio)
+ return -ENOMEM;
+
+ /* Host specific */
+ bus->hosttype = BCMA_HOSTTYPE_SOC;
+ bus->ops = &bcma_host_soc_ops;
+ bus->host_pdev = pdev;
+
+ /* Initialize struct, detect chip */
+ bcma_init_bus(bus);
+
+ /* Register */
+ err = bcma_bus_register(bus);
+ if (err)
+ goto err_unmap_mmio;
+
+ platform_set_drvdata(pdev, bus);
+
+ return err;
+
+err_unmap_mmio:
+ iounmap(bus->mmio);
+ return err;
+}
+
+static int bcma_host_soc_remove(struct platform_device *pdev)
+{
+ struct bcma_bus *bus = platform_get_drvdata(pdev);
+
+ bcma_bus_unregister(bus);
+ iounmap(bus->mmio);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id bcma_host_soc_of_match[] = {
+ { .compatible = "brcm,bus-axi", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match);
+
+static struct platform_driver bcma_host_soc_driver = {
+ .driver = {
+ .name = "bcma-host-soc",
+ .of_match_table = bcma_host_soc_of_match,
+ },
+ .probe = bcma_host_soc_probe,
+ .remove = bcma_host_soc_remove,
+};
+
+int __init bcma_host_soc_register_driver(void)
+{
+ return platform_driver_register(&bcma_host_soc_driver);
+}
+
+void __exit bcma_host_soc_unregister_driver(void)
+{
+ platform_driver_unregister(&bcma_host_soc_driver);
+}
+#endif /* CONFIG_OF */
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 0ff8d58831ef..d1656c2f70af 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/bcma/bcma.h>
#include <linux/slab.h>
+#include <linux/of_address.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -120,16 +121,103 @@ static void bcma_release_core_dev(struct device *dev)
kfree(core);
}
-static int bcma_register_cores(struct bcma_bus *bus)
+static bool bcma_is_core_needed_early(u16 core_id)
+{
+ switch (core_id) {
+ case BCMA_CORE_NS_NAND:
+ case BCMA_CORE_NS_QSPI:
+ return true;
+ }
+
+ return false;
+}
+
+#ifdef CONFIG_OF
+static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+ struct device_node *node;
+ u64 size;
+ const __be32 *reg;
+
+ if (!parent || !parent->dev.of_node)
+ return NULL;
+
+ for_each_child_of_node(parent->dev.of_node, node) {
+ reg = of_get_address(node, 0, &size, NULL);
+ if (!reg)
+ continue;
+ if (of_translate_address(node, reg) == core->addr)
+ return node;
+ }
+ return NULL;
+}
+
+static void bcma_of_fill_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+ struct device_node *node;
+
+ node = bcma_of_find_child_device(parent, core);
+ if (node)
+ core->dev.of_node = node;
+}
+#else
+static void bcma_of_fill_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+}
+#endif /* CONFIG_OF */
+
+static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
+{
+ int err;
+
+ core->dev.release = bcma_release_core_dev;
+ core->dev.bus = &bcma_bus_type;
+ dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
+
+ switch (bus->hosttype) {
+ case BCMA_HOSTTYPE_PCI:
+ core->dev.parent = &bus->host_pci->dev;
+ core->dma_dev = &bus->host_pci->dev;
+ core->irq = bus->host_pci->irq;
+ break;
+ case BCMA_HOSTTYPE_SOC:
+ core->dev.dma_mask = &core->dev.coherent_dma_mask;
+ if (bus->host_pdev) {
+ core->dma_dev = &bus->host_pdev->dev;
+ core->dev.parent = &bus->host_pdev->dev;
+ bcma_of_fill_device(bus->host_pdev, core);
+ } else {
+ core->dma_dev = &core->dev;
+ }
+ break;
+ case BCMA_HOSTTYPE_SDIO:
+ break;
+ }
+
+ err = device_register(&core->dev);
+ if (err) {
+ bcma_err(bus, "Could not register dev for core 0x%03X\n",
+ core->id.id);
+ put_device(&core->dev);
+ return;
+ }
+ core->dev_registered = true;
+}
+
+static int bcma_register_devices(struct bcma_bus *bus)
{
struct bcma_device *core;
- int err, dev_id = 0;
+ int err;
list_for_each_entry(core, &bus->cores, list) {
/* We support that cores ourself */
switch (core->id.id) {
case BCMA_CORE_4706_CHIPCOMMON:
case BCMA_CORE_CHIPCOMMON:
+ case BCMA_CORE_NS_CHIPCOMMON_B:
case BCMA_CORE_PCI:
case BCMA_CORE_PCIE:
case BCMA_CORE_PCIE2:
@@ -138,39 +226,16 @@ static int bcma_register_cores(struct bcma_bus *bus)
continue;
}
+ /* Early cores were already registered */
+ if (bcma_is_core_needed_early(core->id.id))
+ continue;
+
/* Only first GMAC core on BCM4706 is connected and working */
if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
core->core_unit > 0)
continue;
- core->dev.release = bcma_release_core_dev;
- core->dev.bus = &bcma_bus_type;
- dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
-
- switch (bus->hosttype) {
- case BCMA_HOSTTYPE_PCI:
- core->dev.parent = &bus->host_pci->dev;
- core->dma_dev = &bus->host_pci->dev;
- core->irq = bus->host_pci->irq;
- break;
- case BCMA_HOSTTYPE_SOC:
- core->dev.dma_mask = &core->dev.coherent_dma_mask;
- core->dma_dev = &core->dev;
- break;
- case BCMA_HOSTTYPE_SDIO:
- break;
- }
-
- err = device_register(&core->dev);
- if (err) {
- bcma_err(bus,
- "Could not register dev for core 0x%03X\n",
- core->id.id);
- put_device(&core->dev);
- continue;
- }
- core->dev_registered = true;
- dev_id++;
+ bcma_register_core(bus, core);
}
#ifdef CONFIG_BCMA_DRIVER_MIPS
@@ -247,6 +312,12 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_chipcommon_early_init(&bus->drv_cc);
}
+ /* Cores providing flash access go before SPROM init */
+ list_for_each_entry(core, &bus->cores, list) {
+ if (bcma_is_core_needed_early(core->id.id))
+ bcma_register_core(bus, core);
+ }
+
/* Try to get SPROM */
err = bcma_sprom_get(bus);
if (err == -ENOENT) {
@@ -261,6 +332,13 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_chipcommon_init(&bus->drv_cc);
}
+ /* Init CC core */
+ core = bcma_find_core(bus, BCMA_CORE_NS_CHIPCOMMON_B);
+ if (core) {
+ bus->drv_cc_b.core = core;
+ bcma_core_chipcommon_b_init(&bus->drv_cc_b);
+ }
+
/* Init MIPS core */
core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
if (core) {
@@ -297,7 +375,7 @@ int bcma_bus_register(struct bcma_bus *bus)
}
/* Register found cores */
- bcma_register_cores(bus);
+ bcma_register_devices(bus);
bcma_info(bus, "Bus registered\n");
@@ -315,6 +393,8 @@ void bcma_bus_unregister(struct bcma_bus *bus)
else if (err)
bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
+ bcma_core_chipcommon_b_free(&bus->drv_cc_b);
+
cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
@@ -334,8 +414,6 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
struct bcma_device *core;
struct bcma_device_id match;
- bcma_init_bus(bus);
-
match.manuf = BCMA_MANUF_BCM;
match.id = bcma_cc_core_id(bus);
match.class = BCMA_CL_SIM;
@@ -494,6 +572,11 @@ static int __init bcma_modinit(void)
if (err)
return err;
+ err = bcma_host_soc_register_driver();
+ if (err) {
+ pr_err("SoC host initialization failed\n");
+ err = 0;
+ }
#ifdef CONFIG_BCMA_HOST_PCI
err = bcma_host_pci_init();
if (err) {
@@ -511,6 +594,7 @@ static void __exit bcma_modexit(void)
#ifdef CONFIG_BCMA_HOST_PCI
bcma_host_pci_exit();
#endif
+ bcma_host_soc_unregister_driver();
bus_unregister(&bcma_bus_type);
}
module_exit(bcma_modexit)
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index b4764c6bcf17..14b56561a36f 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -276,7 +276,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
struct bcma_device *core)
{
u32 tmp;
- u8 i, j;
+ u8 i, j, k;
s32 cia, cib;
u8 ports[2], wrappers[2];
@@ -314,6 +314,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
/* Some specific cores don't need wrappers */
switch (core->id.id) {
case BCMA_CORE_4706_MAC_GBIT_COMMON:
+ case BCMA_CORE_NS_CHIPCOMMON_B:
/* Not used yet: case BCMA_CORE_OOB_ROUTER: */
break;
default:
@@ -367,6 +368,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
core->addr = tmp;
/* get & parse slave ports */
+ k = 0;
for (i = 0; i < ports[1]; i++) {
for (j = 0; ; j++) {
tmp = bcma_erom_get_addr_desc(bus, eromptr,
@@ -376,9 +378,9 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
/* pr_debug("erom: slave port %d "
* "has %d descriptors\n", i, j); */
break;
- } else {
- if (i == 0 && j == 0)
- core->addr1 = tmp;
+ } else if (k < ARRAY_SIZE(core->addr_s)) {
+ core->addr_s[k] = tmp;
+ k++;
}
}
}
@@ -421,10 +423,13 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
core->io_addr = ioremap_nocache(core->addr, BCMA_CORE_SIZE);
if (!core->io_addr)
return -ENOMEM;
- core->io_wrap = ioremap_nocache(core->wrap, BCMA_CORE_SIZE);
- if (!core->io_wrap) {
- iounmap(core->io_addr);
- return -ENOMEM;
+ if (core->wrap) {
+ core->io_wrap = ioremap_nocache(core->wrap,
+ BCMA_CORE_SIZE);
+ if (!core->io_wrap) {
+ iounmap(core->io_addr);
+ return -ENOMEM;
+ }
}
}
return 0;
@@ -434,9 +439,7 @@ void bcma_init_bus(struct bcma_bus *bus)
{
s32 tmp;
struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
-
- if (bus->init_done)
- return;
+ char chip_id[8];
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
@@ -447,10 +450,11 @@ void bcma_init_bus(struct bcma_bus *bus)
chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
- bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
- chipinfo->id, chipinfo->rev, chipinfo->pkg);
- bus->init_done = true;
+ snprintf(chip_id, ARRAY_SIZE(chip_id),
+ (chipinfo->id > 0x9999) ? "%d" : "0x%04X", chipinfo->id);
+ bcma_info(bus, "Found chip with id %s, rev 0x%02X and package 0x%02X\n",
+ chip_id, chipinfo->rev, chipinfo->pkg);
}
int bcma_bus_scan(struct bcma_bus *bus)
@@ -460,8 +464,6 @@ int bcma_bus_scan(struct bcma_bus *bus)
int err, core_num = 0;
- bcma_init_bus(bus);
-
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);