arm64: dts: rockchip: add efuse device node for rk3366
[firefly-linux-kernel-4.4.55.git] / drivers / of / platform.c
index e0a6514ab46c20eb902453c3b321774d1e787ba0..af98343614d8eeebeabc1fa0c74337029cd70335 100644 (file)
@@ -25,6 +25,7 @@
 
 const struct of_device_id of_default_bus_match_table[] = {
        { .compatible = "simple-bus", },
+       { .compatible = "simple-mfd", },
 #ifdef CONFIG_ARM_AMBA
        { .compatible = "arm,amba-bus", },
 #endif /* CONFIG_ARM_AMBA */
@@ -51,10 +52,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np)
 }
 EXPORT_SYMBOL(of_find_device_by_node);
 
-#if defined(CONFIG_PPC_DCR)
-#include <asm/dcr.h>
-#endif
-
 #ifdef CONFIG_OF_ADDRESS
 /*
  * The following routines scan a subtree and registers a device for
@@ -68,66 +65,35 @@ EXPORT_SYMBOL(of_find_device_by_node);
  * of_device_make_bus_id - Use the device node data to assign a unique name
  * @dev: pointer to device structure that is linked to a device tree node
  *
- * This routine will first try using either the dcr-reg or the reg property
- * value to derive a unique name.  As a last resort it will use the node
- * name followed by a unique number.
+ * This routine will first try using the translated bus address to
+ * derive a unique name. If it cannot, then it will prepend names from
+ * parent nodes until a unique name can be derived.
  */
 void of_device_make_bus_id(struct device *dev)
 {
-       static atomic_t bus_no_reg_magic;
        struct device_node *node = dev->of_node;
        const __be32 *reg;
        u64 addr;
-       const __be32 *addrp;
-       int magic;
-
-#ifdef CONFIG_PPC_DCR
-       /*
-        * If it's a DCR based device, use 'd' for native DCRs
-        * and 'D' for MMIO DCRs.
-        */
-       reg = of_get_property(node, "dcr-reg", NULL);
-       if (reg) {
-#ifdef CONFIG_PPC_DCR_NATIVE
-               dev_set_name(dev, "d%x.%s", *reg, node->name);
-#else /* CONFIG_PPC_DCR_NATIVE */
-               u64 addr = of_translate_dcr_address(node, *reg, NULL);
-               if (addr != OF_BAD_ADDR) {
-                       dev_set_name(dev, "D%llx.%s",
-                                    (unsigned long long)addr, node->name);
-                       return;
-               }
-#endif /* !CONFIG_PPC_DCR_NATIVE */
-       }
-#endif /* CONFIG_PPC_DCR */
-
-       /*
-        * For MMIO, get the physical address
-        */
-       reg = of_get_property(node, "reg", NULL);
-       if (reg) {
-               if (of_can_translate_address(node)) {
-                       addr = of_translate_address(node, reg);
-               } else {
-                       addrp = of_get_address(node, 0, NULL, NULL);
-                       if (addrp)
-                               addr = of_read_number(addrp, 1);
-                       else
-                               addr = OF_BAD_ADDR;
-               }
-               if (addr != OF_BAD_ADDR) {
-                       dev_set_name(dev, "%llx.%s",
-                                    (unsigned long long)addr, node->name);
+
+       /* Construct the name, using parent nodes if necessary to ensure uniqueness */
+       while (node->parent) {
+               /*
+                * If the address can be translated, then that is as much
+                * uniqueness as we need. Make it the first component and return
+                */
+               reg = of_get_property(node, "reg", NULL);
+               if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
+                       dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
+                                    (unsigned long long)addr, node->name,
+                                    dev_name(dev));
                        return;
                }
-       }
 
-       /*
-        * No BusID, use the node name and add a globally incremented
-        * counter (and pray...)
-        */
-       magic = atomic_add_return(1, &bus_no_reg_magic);
-       dev_set_name(dev, "%s.%d", node->name, magic - 1);
+               /* format arguments only used if dev_name() resolves to NULL */
+               dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",
+                            strrchr(node->full_name, '/') + 1, dev_name(dev));
+               node = node->parent;
+       }
 }
 
 /**
@@ -149,9 +115,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
                return NULL;
 
        /* count the io and irq resources */
-       if (of_can_translate_address(np))
-               while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-                       num_reg++;
+       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
+               num_reg++;
        num_irq = of_irq_count(np);
 
        /* Populate the resource table */
@@ -168,14 +133,13 @@ struct platform_device *of_device_alloc(struct device_node *np,
                        rc = of_address_to_resource(np, i, res);
                        WARN_ON(rc);
                }
-               WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
+               if (of_irq_to_resource_table(np, res, num_irq) != num_irq)
+                       pr_debug("not all legacy IRQ resources mapped for %s\n",
+                                np->name);
        }
 
        dev->dev.of_node = of_node_get(np);
-#if defined(CONFIG_MICROBLAZE)
-       dev->dev.dma_mask = &dev->archdata.dma_mask;
-#endif
-       dev->dev.parent = parent;
+       dev->dev.parent = parent ? : &platform_bus;
 
        if (bus_id)
                dev_set_name(&dev->dev, "%s", bus_id);
@@ -186,6 +150,11 @@ struct platform_device *of_device_alloc(struct device_node *np,
 }
 EXPORT_SYMBOL(of_device_alloc);
 
+static void of_dma_deconfigure(struct device *dev)
+{
+       arch_teardown_dma_ops(dev);
+}
+
 /**
  * of_platform_device_create_pdata - Alloc, initialize and register an of_device
  * @np: pointer to node to create device for
@@ -196,7 +165,7 @@ EXPORT_SYMBOL(of_device_alloc);
  * Returns pointer to created platform device, or NULL if a device was not
  * registered.  Unavailable devices will not get registered.
  */
-struct platform_device *of_platform_device_create_pdata(
+static struct platform_device *of_platform_device_create_pdata(
                                        struct device_node *np,
                                        const char *bus_id,
                                        void *platform_data,
@@ -204,31 +173,30 @@ struct platform_device *of_platform_device_create_pdata(
 {
        struct platform_device *dev;
 
-       if (!of_device_is_available(np))
+       if (!of_device_is_available(np) ||
+           of_node_test_and_set_flag(np, OF_POPULATED))
                return NULL;
 
        dev = of_device_alloc(np, bus_id, parent);
        if (!dev)
-               return NULL;
+               goto err_clear_flag;
 
-#if defined(CONFIG_MICROBLAZE)
-       dev->archdata.dma_mask = 0xffffffffUL;
-#endif
-       dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
-
-       /* We do not fill the DMA ops for platform devices by default.
-        * This is currently the responsibility of the platform code
-        * to do such, possibly using a device notifier
-        */
+       of_dma_configure(&dev->dev, dev->dev.of_node);
+       of_msi_configure(&dev->dev, dev->dev.of_node);
 
        if (of_device_add(dev) != 0) {
+               of_dma_deconfigure(&dev->dev);
                platform_device_put(dev);
-               return NULL;
+               goto err_clear_flag;
        }
 
        return dev;
+
+err_clear_flag:
+       of_node_clear_flag(np, OF_POPULATED);
+       return NULL;
 }
 
 /**
@@ -260,25 +228,26 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
 
        pr_debug("Creating amba device %s\n", node->full_name);
 
-       if (!of_device_is_available(node))
+       if (!of_device_is_available(node) ||
+           of_node_test_and_set_flag(node, OF_POPULATED))
                return NULL;
 
        dev = amba_device_alloc(NULL, 0, 0);
-       if (!dev)
-               return NULL;
+       if (!dev) {
+               pr_err("%s(): amba_device_alloc() failed for %s\n",
+                      __func__, node->full_name);
+               goto err_clear_flag;
+       }
 
        /* setup generic device info */
-       dev->dev.coherent_dma_mask = ~0;
        dev->dev.of_node = of_node_get(node);
-       dev->dev.parent = parent;
+       dev->dev.parent = parent ? : &platform_bus;
        dev->dev.platform_data = platform_data;
        if (bus_id)
                dev_set_name(&dev->dev, "%s", bus_id);
        else
                of_device_make_bus_id(&dev->dev);
-
-       /* setup amba-specific device info */
-       dev->dma_mask = ~0;
+       of_dma_configure(&dev->dev, dev->dev.of_node);
 
        /* Allow the HW Peripheral ID to be overridden */
        prop = of_get_property(node, "arm,primecell-periphid", NULL);
@@ -290,17 +259,25 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
                dev->irq[i] = irq_of_parse_and_map(node, i);
 
        ret = of_address_to_resource(node, 0, &dev->res);
-       if (ret)
+       if (ret) {
+               pr_err("%s(): of_address_to_resource() failed (%d) for %s\n",
+                      __func__, ret, node->full_name);
                goto err_free;
+       }
 
        ret = amba_device_add(dev, &iomem_resource);
-       if (ret)
+       if (ret) {
+               pr_err("%s(): amba_device_add() failed (%d) for %s\n",
+                      __func__, ret, node->full_name);
                goto err_free;
+       }
 
        return dev;
 
 err_free:
        amba_device_put(dev);
+err_clear_flag:
+       of_node_clear_flag(node, OF_POPULATED);
        return NULL;
 }
 #else /* CONFIG_ARM_AMBA */
@@ -374,6 +351,10 @@ static int of_platform_bus_create(struct device_node *bus,
        }
 
        if (of_device_is_compatible(bus, "arm,primecell")) {
+               /*
+                * Don't return an error here to keep compatibility with older
+                * device tree files.
+                */
                of_amba_device_create(bus, bus_id, platform_data, parent);
                return 0;
        }
@@ -390,6 +371,7 @@ static int of_platform_bus_create(struct device_node *bus,
                        break;
                }
        }
+       of_node_set_flag(bus, OF_POPULATED_BUS);
        return rc;
 }
 
@@ -423,8 +405,10 @@ int of_platform_bus_probe(struct device_node *root,
                if (!of_match_node(matches, child))
                        continue;
                rc = of_platform_bus_create(child, matches, NULL, parent, false);
-               if (rc)
+               if (rc) {
+                       of_node_put(child);
                        break;
+               }
        }
 
        of_node_put(root);
@@ -465,12 +449,133 @@ int of_platform_populate(struct device_node *root,
 
        for_each_child_of_node(root, child) {
                rc = of_platform_bus_create(child, matches, lookup, parent, true);
-               if (rc)
+               if (rc) {
+                       of_node_put(child);
                        break;
+               }
        }
+       of_node_set_flag(root, OF_POPULATED_BUS);
 
        of_node_put(root);
        return rc;
 }
 EXPORT_SYMBOL_GPL(of_platform_populate);
+
+int of_platform_default_populate(struct device_node *root,
+                                const struct of_dev_auxdata *lookup,
+                                struct device *parent)
+{
+       return of_platform_populate(root, of_default_bus_match_table, lookup,
+                                   parent);
+}
+EXPORT_SYMBOL_GPL(of_platform_default_populate);
+
+static int of_platform_device_destroy(struct device *dev, void *data)
+{
+       /* Do not touch devices not populated from the device tree */
+       if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
+               return 0;
+
+       /* Recurse for any nodes that were treated as busses */
+       if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+               device_for_each_child(dev, NULL, of_platform_device_destroy);
+
+       if (dev->bus == &platform_bus_type)
+               platform_device_unregister(to_platform_device(dev));
+#ifdef CONFIG_ARM_AMBA
+       else if (dev->bus == &amba_bustype)
+               amba_device_unregister(to_amba_device(dev));
+#endif
+
+       of_dma_deconfigure(dev);
+       of_node_clear_flag(dev->of_node, OF_POPULATED);
+       of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
+       return 0;
+}
+
+/**
+ * of_platform_depopulate() - Remove devices populated from device tree
+ * @parent: device which children will be removed
+ *
+ * Complementary to of_platform_populate(), this function removes children
+ * of the given device (and, recurrently, their children) that have been
+ * created from their respective device tree nodes (and only those,
+ * leaving others - eg. manually created - unharmed).
+ *
+ * Returns 0 when all children devices have been removed or
+ * -EBUSY when some children remained.
+ */
+void of_platform_depopulate(struct device *parent)
+{
+       if (parent->of_node && of_node_check_flag(parent->of_node, OF_POPULATED_BUS)) {
+               device_for_each_child(parent, NULL, of_platform_device_destroy);
+               of_node_clear_flag(parent->of_node, OF_POPULATED_BUS);
+       }
+}
+EXPORT_SYMBOL_GPL(of_platform_depopulate);
+
+#ifdef CONFIG_OF_DYNAMIC
+static int of_platform_notify(struct notifier_block *nb,
+                               unsigned long action, void *arg)
+{
+       struct of_reconfig_data *rd = arg;
+       struct platform_device *pdev_parent, *pdev;
+       bool children_left;
+
+       switch (of_reconfig_get_state_change(action, rd)) {
+       case OF_RECONFIG_CHANGE_ADD:
+               /* verify that the parent is a bus */
+               if (!of_node_check_flag(rd->dn->parent, OF_POPULATED_BUS))
+                       return NOTIFY_OK;       /* not for us */
+
+               /* already populated? (driver using of_populate manually) */
+               if (of_node_check_flag(rd->dn, OF_POPULATED))
+                       return NOTIFY_OK;
+
+               /* pdev_parent may be NULL when no bus platform device */
+               pdev_parent = of_find_device_by_node(rd->dn->parent);
+               pdev = of_platform_device_create(rd->dn, NULL,
+                               pdev_parent ? &pdev_parent->dev : NULL);
+               of_dev_put(pdev_parent);
+
+               if (pdev == NULL) {
+                       pr_err("%s: failed to create for '%s'\n",
+                                       __func__, rd->dn->full_name);
+                       /* of_platform_device_create tosses the error code */
+                       return notifier_from_errno(-EINVAL);
+               }
+               break;
+
+       case OF_RECONFIG_CHANGE_REMOVE:
+
+               /* already depopulated? */
+               if (!of_node_check_flag(rd->dn, OF_POPULATED))
+                       return NOTIFY_OK;
+
+               /* find our device by node */
+               pdev = of_find_device_by_node(rd->dn);
+               if (pdev == NULL)
+                       return NOTIFY_OK;       /* no? not meant for us */
+
+               /* unregister takes one ref away */
+               of_platform_device_destroy(&pdev->dev, &children_left);
+
+               /* and put the reference of the find */
+               of_dev_put(pdev);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block platform_of_notifier = {
+       .notifier_call = of_platform_notify,
+};
+
+void of_platform_register_reconfig_notifier(void)
+{
+       WARN_ON(of_reconfig_notifier_register(&platform_of_notifier));
+}
+#endif /* CONFIG_OF_DYNAMIC */
+
 #endif /* CONFIG_OF_ADDRESS */