pr_debug("%s()\n", __func__);
pr_debug(" starting at: %pOF\n", root);
- device_links_supplier_sync_state_pause();
for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc) {
break;
}
}
- device_links_supplier_sync_state_resume();
-
of_node_set_flag(root, OF_POPULATED_BUS);
of_node_put(root);
}
EXPORT_SYMBOL_GPL(of_platform_default_populate);
-bool of_link_is_valid(struct device_node *con, struct device_node *sup)
-{
- of_node_get(sup);
- /*
- * Don't allow linking a device node as a consumer of one of its
- * descendant nodes. By definition, a child node can't be a functional
- * dependency for the parent node.
- */
- while (sup) {
- if (sup == con) {
- of_node_put(sup);
- return false;
- }
- sup = of_get_next_parent(sup);
- }
- return true;
-}
-
-static int of_link_to_phandle(struct device *dev, struct device_node *sup_np)
-{
- struct platform_device *sup_dev;
- u32 dl_flags = DL_FLAG_AUTOPROBE_CONSUMER;
- int ret = 0;
-
- /*
- * Since we are trying to create device links, we need to find
- * the actual device node that owns this supplier phandle.
- * Often times it's the same node, but sometimes it can be one
- * of the parents. So walk up the parent till you find a
- * device.
- */
- while (sup_np && !of_find_property(sup_np, "compatible", NULL))
- sup_np = of_get_next_parent(sup_np);
- if (!sup_np)
- return 0;
-
- if (!of_link_is_valid(dev->of_node, sup_np)) {
- of_node_put(sup_np);
- return 0;
- }
- sup_dev = of_find_device_by_node(sup_np);
- of_node_put(sup_np);
- if (!sup_dev)
- return -ENODEV;
- if (!device_link_add(dev, &sup_dev->dev, dl_flags))
- ret = -ENODEV;
- put_device(&sup_dev->dev);
- return ret;
-}
-
-static struct device_node *parse_prop_cells(struct device_node *np,
- const char *prop, int index,
- const char *binding,
- const char *cell)
-{
- struct of_phandle_args sup_args;
-
- /* Don't need to check property name for every index. */
- if (!index && strcmp(prop, binding))
- return NULL;
-
- if (of_parse_phandle_with_args(np, binding, cell, index, &sup_args))
- return NULL;
-
- return sup_args.np;
-}
-
-static struct device_node *parse_clocks(struct device_node *np,
- const char *prop, int index)
-{
- return parse_prop_cells(np, prop, index, "clocks", "#clock-cells");
-}
-
-static struct device_node *parse_interconnects(struct device_node *np,
- const char *prop, int index)
-{
- return parse_prop_cells(np, prop, index, "interconnects",
- "#interconnect-cells");
-}
-
-static int strcmp_suffix(const char *str, const char *suffix)
-{
- unsigned int len, suffix_len;
-
- len = strlen(str);
- suffix_len = strlen(suffix);
- if (len <= suffix_len)
- return -1;
- return strcmp(str + len - suffix_len, suffix);
-}
-
-static struct device_node *parse_regulators(struct device_node *np,
- const char *prop, int index)
-{
- if (index || strcmp_suffix(prop, "-supply"))
- return NULL;
-
- return of_parse_phandle(np, prop, 0);
-}
-
-/**
- * struct supplier_bindings - Information for parsing supplier DT binding
- *
- * @parse_prop: If the function cannot parse the property, return NULL.
- * Otherwise, return the phandle listed in the property
- * that corresponds to the index.
- */
-struct supplier_bindings {
- struct device_node *(*parse_prop)(struct device_node *np,
- const char *name, int index);
-};
-
-static const struct supplier_bindings bindings[] = {
- { .parse_prop = parse_clocks, },
- { .parse_prop = parse_interconnects, },
- { .parse_prop = parse_regulators, },
- { },
-};
-
-static bool of_link_property(struct device *dev, struct device_node *con_np,
- const char *prop)
-{
- struct device_node *phandle;
- const struct supplier_bindings *s = bindings;
- unsigned int i = 0;
- bool done = true, matched = false;
-
- while (!matched && s->parse_prop) {
- while ((phandle = s->parse_prop(con_np, prop, i))) {
- matched = true;
- i++;
- if (of_link_to_phandle(dev, phandle))
- /*
- * Don't stop at the first failure. See
- * Documentation for bus_type.add_links for
- * more details.
- */
- done = false;
- }
- s++;
- }
- return done ? 0 : -ENODEV;
-}
-
-static bool of_devlink;
-core_param(of_devlink, of_devlink, bool, 0);
-
-static int of_link_to_suppliers(struct device *dev)
-{
- struct property *p;
- bool done = true;
-
- if (!of_devlink)
- return 0;
- if (unlikely(!dev->of_node))
- return 0;
-
- for_each_property_of_node(dev->of_node, p)
- if (of_link_property(dev, dev->of_node, p->name))
- done = false;
-
- return done ? 0 : -ENODEV;
-}
-
#ifndef CONFIG_PPC
static const struct of_device_id reserved_mem_matches[] = {
{ .compatible = "qcom,rmtfs-mem" },
if (!of_have_populated_dt())
return -ENODEV;
- platform_bus_type.add_links = of_link_to_suppliers;
- device_links_supplier_sync_state_pause();
/*
* Handle certain compatibles explicitly, since we don't want to create
* platform_devices for every node in /reserved-memory with a
return 0;
}
arch_initcall_sync(of_platform_default_populate_init);
-
-static int __init of_platform_sync_state_init(void)
-{
- device_links_supplier_sync_state_resume();
- return 0;
-}
-late_initcall_sync(of_platform_sync_state_init);
#endif
int of_platform_device_destroy(struct device *dev, void *data)