diff options
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r-- | drivers/of/base.c | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c index 193bae7fa0..42b8d24874 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -15,6 +15,7 @@ * GNU General Public License for more details. */ #include <common.h> +#include <deep-probe.h> #include <of.h> #include <of_address.h> #include <errno.h> @@ -1682,6 +1683,9 @@ int of_modalias_node(struct device_node *node, char *modalias, int len) } EXPORT_SYMBOL_GPL(of_modalias_node); +static struct device_node *of_chosen; +static const char *of_model; + struct device_node *of_get_root_node(void) { return root_node; @@ -1694,11 +1698,26 @@ int of_set_root_node(struct device_node *node) root_node = node; + of_chosen = of_find_node_by_path("/chosen"); + of_property_read_string(root_node, "model", &of_model); + + if (of_model) + barebox_set_model(of_model); + of_alias_scan(); return 0; } +static int barebox_of_populate(void) +{ + if (IS_ENABLED(CONFIG_OFDEVICE) && deep_probe_is_supported()) + return of_probe(); + + return 0; +} +of_populate_initcall(barebox_of_populate); + int barebox_register_of(struct device_node *root) { if (root_node) @@ -1707,8 +1726,11 @@ int barebox_register_of(struct device_node *root) of_set_root_node(root); of_fix_tree(root); - if (IS_ENABLED(CONFIG_OFDEVICE)) - return of_probe(); + if (IS_ENABLED(CONFIG_OFDEVICE)) { + of_clk_init(root, NULL); + if (!deep_probe_is_supported()) + return of_probe(); + } return 0; } @@ -1720,7 +1742,7 @@ int barebox_register_fdt(const void *dtb) if (root_node) return -EBUSY; - root = of_unflatten_dtb(dtb); + root = of_unflatten_dtb(dtb, INT_MAX); if (IS_ERR(root)) { pr_err("Cannot unflatten dtb: %pe\n", root); return PTR_ERR(root); @@ -2275,9 +2297,6 @@ int of_add_memory(struct device_node *node, bool dump) return ret; } -static struct device_node *of_chosen; -static const char *of_model; - const char *of_get_model(void) { return of_model; @@ -2300,6 +2319,9 @@ static int of_probe_memory(void) struct device_node *memory = root_node; int ret = 0; + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return 0; + /* Parse all available node with "memory" device_type */ while (1) { int err; @@ -2315,6 +2337,7 @@ static int of_probe_memory(void) return ret; } +mem_initcall(of_probe_memory); static void of_platform_device_create_root(struct device_node *np) { @@ -2331,32 +2354,35 @@ static void of_platform_device_create_root(struct device_node *np) free(dev); } +static const struct of_device_id reserved_mem_matches[] = { + { .compatible = "nvmem-rmem" }, + {} +}; + int of_probe(void) { - struct device_node *firmware; - int ret; + struct device_node *node; if(!root_node) return -ENODEV; - of_chosen = of_find_node_by_path("/chosen"); - of_property_read_string(root_node, "model", &of_model); - - if (of_model) - barebox_set_model(of_model); - - ret = of_probe_memory(); + /* + * Handle certain compatibles explicitly, since we don't want to create + * platform_devices for every node in /reserved-memory with a + * "compatible", + */ + for_each_matching_node(node, reserved_mem_matches) + of_platform_device_create(node, NULL); - firmware = of_find_node_by_path("/firmware"); - if (firmware) - of_platform_populate(firmware, NULL, NULL); + node = of_find_node_by_path("/firmware"); + if (node) + of_platform_populate(node, NULL, NULL); of_platform_device_create_root(root_node); - of_clk_init(root_node, NULL); of_platform_populate(root_node, of_default_bus_match_table, NULL); - return ret; + return 0; } /** @@ -2409,6 +2435,7 @@ struct device_node *of_copy_node(struct device_node *parent, const struct device struct property *pp; np = of_new_node(parent, other->name); + np->phandle = other->phandle; list_for_each_entry(pp, &other->properties, list) of_new_property(np, pp->name, pp->value, pp->length); @@ -2419,15 +2446,24 @@ struct device_node *of_copy_node(struct device_node *parent, const struct device return np; } +struct device_node *of_dup(const struct device_node *root) +{ + return of_copy_node(NULL, root); +} + void of_delete_node(struct device_node *node) { struct device_node *n, *nt; struct property *p, *pt; - struct device_d *dev; if (!node) return; + if (node == root_node) { + pr_err("Won't delete root device node\n"); + return; + } + list_for_each_entry_safe(p, pt, &node->properties, list) of_delete_property(p); @@ -2439,28 +2475,18 @@ void of_delete_node(struct device_node *node) list_del(&node->list); } - dev = of_find_device_by_node(node); - if (dev) - dev->device_node = NULL; - free(node->name); free(node->full_name); free(node); - - if (node == root_node) - of_set_root_node(NULL); } -int of_device_is_stdout_path(struct device_d *dev) +struct device_node *of_get_stdoutpath(unsigned int *baudrate) { struct device_node *dn; const char *name; const char *p; char *q; - if (!dev->device_node) - return 0; - name = of_get_property(of_chosen, "stdout-path", NULL); if (!name) name = of_get_property(of_chosen, "linux,stdout-path", NULL); @@ -2468,10 +2494,7 @@ int of_device_is_stdout_path(struct device_d *dev) if (!name) return 0; - /* This could make use of strchrnul if it were available */ - p = strchr(name, ':'); - if (!p) - p = name + strlen(name); + p = strchrnul(name, ':'); q = xstrndup(name, p - name); @@ -2479,7 +2502,24 @@ int of_device_is_stdout_path(struct device_d *dev) free(q); - return dn == dev->device_node; + if (baudrate && *p) { + unsigned rate = simple_strtoul(p + 1, NULL, 10); + if (rate) + *baudrate = rate; + } + + return dn; +} + +int of_device_is_stdout_path(struct device_d *dev, unsigned int *baudrate) +{ + unsigned int tmp = *baudrate; + + if (!dev || !dev->device_node || dev->device_node != of_get_stdoutpath(&tmp)) + return false; + + *baudrate = tmp; + return true; } /** |