bcma: register bcma as device tree driver
[firefly-linux-kernel-4.4.55.git] / drivers / bcma / main.c
index 0ff8d58831ef30fcbe7a5452baa8b00e3fdababa..d1656c2f70afa43198066681f6a02ded26eab80b 100644 (file)
@@ -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)