diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-05-09 08:49:43 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-05-09 08:49:43 +0200 |
commit | 4cb8e17aa3972e27f4b34e5bb2df9e7007824ac2 (patch) | |
tree | 942b24dcd275407d76f6b3ef85f6db9af1160163 /drivers/of | |
parent | 854df603da65bc56fe72218b402903f26155b0f0 (diff) | |
parent | 79fdb84a6b46f7c129225b57007b63e765747d52 (diff) | |
download | barebox-4cb8e17aa3972e27f4b34e5bb2df9e7007824ac2.tar.gz barebox-4cb8e17aa3972e27f4b34e5bb2df9e7007824ac2.tar.xz |
Merge branch 'for-next/misc'
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Makefile | 4 | ||||
-rw-r--r-- | drivers/of/base.c | 38 | ||||
-rw-r--r-- | drivers/of/fdt.c | 106 |
3 files changed, 108 insertions, 40 deletions
diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 0dc2f8d63e..773548e133 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,8 +1,8 @@ -obj-y += address.o base.o fdt.o platform.o +obj-y += address.o base.o fdt.o platform.o of_path.o obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o obj-$(CONFIG_OF_GPIO) += of_gpio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-y += partition.o obj-y += of_net.o obj-$(CONFIG_MTD) += of_mtd.o -obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o of_path.o +obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o diff --git a/drivers/of/base.c b/drivers/of/base.c index b4ef8e362f..cbe7b7cec4 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -30,6 +30,8 @@ #include <linux/amba/bus.h> #include <linux/err.h> +static struct device_node *root_node; + /* * Iterate over all nodes of a tree. As a devicetree does not * have a dedicated list head, the start node (usually the root @@ -39,6 +41,9 @@ static inline struct device_node *of_next_node(struct device_node *node) { struct device_node *next; + if (!node) + return root_node; + next = list_first_entry(&node->list, struct device_node, list); return next->parent ? next : NULL; @@ -68,8 +73,6 @@ struct alias_prop { static LIST_HEAD(aliases_lookup); -static struct device_node *root_node; - static struct device_node *of_aliases; #define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 @@ -277,12 +280,6 @@ struct device_node *of_find_node_by_phandle_from(phandle phandle, { struct device_node *node; - if (!root) - root = root_node; - - if (!root) - return NULL; - of_tree_for_each_node_from(node, root) if (node->phandle == phandle) return node; @@ -309,15 +306,7 @@ EXPORT_SYMBOL(of_find_node_by_phandle); phandle of_get_tree_max_phandle(struct device_node *root) { struct device_node *n; - phandle max; - - if (!root) - root = root_node; - - if (!root) - return 0; - - max = root->phandle; + phandle max = 0; of_tree_for_each_node_from(n, root) { if (n->phandle > max) @@ -430,9 +419,6 @@ struct device_node *of_find_node_by_name(struct device_node *from, { struct device_node *np; - if (!from) - from = root_node; - of_tree_for_each_node_from(np, from) if (np->name && !of_node_cmp(np->name, name)) return np; @@ -458,9 +444,6 @@ struct device_node *of_find_node_by_type(struct device_node *from, const char *device_type; int ret; - if (!from) - from = root_node; - of_tree_for_each_node_from(np, from) { ret = of_property_read_string(np, "device_type", &device_type); if (!ret && !of_node_cmp(device_type, type)) @@ -489,9 +472,6 @@ struct device_node *of_find_compatible_node(struct device_node *from, { struct device_node *np; - if (!from) - from = root_node; - of_tree_for_each_node_from(np, from) if (of_device_is_compatible(np, compatible)) return np; @@ -516,9 +496,6 @@ struct device_node *of_find_node_with_property(struct device_node *from, { struct device_node *np; - if (!from) - from = root_node; - of_tree_for_each_node_from(np, from) { struct property *pp = of_find_property(np, prop_name, NULL); if (pp) @@ -572,9 +549,6 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, if (match) *match = NULL; - if (!from) - from = root_node; - of_tree_for_each_node_from(np, from) { const struct of_device_id *m = of_match_node(matches, np); if (m) { diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 88f0523260..b2253aa7a2 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -46,6 +46,70 @@ static inline char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs return strstart + ofs; } +static int of_reservemap_num_entries(const struct fdt_header *fdt) +{ + const struct fdt_reserve_entry *r; + int n = 0; + + r = (void *)fdt + be32_to_cpu(fdt->off_mem_rsvmap); + + while (r->size) { + n++; + r++; + if (n == OF_MAX_RESERVE_MAP) + return -EINVAL; + } + + return n; +} + +/** + * of_unflatten_reservemap - store /memreserve/ entries in unflattened tree + * @root - The unflattened tree + * @fdt - the flattened device tree blob + * + * This stores the memreserve entries from the dtb in a newly created + * /memserve node in the unflattened device tree. The device tree + * flatten code moves the entries back to the /memreserve/ area in the + * flattened tree. + * + * Return: 0 for success or negative error code + */ +static int of_unflatten_reservemap(struct device_node *root, + const struct fdt_header *fdt) +{ + int n; + struct property *p; + struct device_node *memreserve; + __be32 cells; + + n = of_reservemap_num_entries(fdt); + if (n <= 0) + return n; + + memreserve = of_new_node(root, "memreserve"); + if (!memreserve) + return -ENOMEM; + + cells = cpu_to_be32(2); + + p = of_new_property(memreserve, "#address-cells", &cells, sizeof(__be32)); + if (!p) + return -ENOMEM; + + p = of_new_property(memreserve, "#size-cells", &cells, sizeof(__be32)); + if (!p) + return -ENOMEM; + + p = of_new_property(memreserve, "reg", + (void *)fdt + be32_to_cpu(fdt->off_mem_rsvmap), + n * sizeof(struct fdt_reserve_entry)); + if (!p) + return -ENOMEM; + + return 0; +} + /** * of_unflatten_dtb - unflatten a dtb binary blob * @infdt - the fdt blob to unflatten @@ -103,6 +167,10 @@ struct device_node *of_unflatten_dtb(const void *infdt) if (!root) return ERR_PTR(-ENOMEM); + ret = of_unflatten_reservemap(root, fdt); + if (ret) + goto err; + while (1) { tag = be32_to_cpu(*(uint32_t *)(infdt + dt_struct)); @@ -289,7 +357,7 @@ static inline int dt_add_string(struct fdt *fdt, const char *str) return ret; } -static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node) +static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node, int is_root) { struct property *p; struct device_node *n; @@ -322,7 +390,10 @@ static int __of_flatten_dtb(struct fdt *fdt, struct device_node *node) } list_for_each_entry(n, &node->children, parent_list) { - ret = __of_flatten_dtb(fdt, n); + if (is_root && !strcmp(n->name, "memreserve")) + continue; + + ret = __of_flatten_dtb(fdt, n, 0); if (ret) return ret; } @@ -347,8 +418,10 @@ void *of_flatten_dtb(struct device_node *node) int ret; struct fdt_header header = {}; struct fdt fdt = {}; - uint32_t ofs; + uint32_t ofs, off_mem_rsvmap; struct fdt_node_header *nh; + struct device_node *memreserve; + int len; header.magic = cpu_to_fdt32(FDT_MAGIC); header.version = cpu_to_fdt32(0x11); @@ -364,14 +437,24 @@ void *of_flatten_dtb(struct device_node *node) ofs = sizeof(struct fdt_header); - header.off_mem_rsvmap = cpu_to_fdt32(ofs); + off_mem_rsvmap = ofs; + header.off_mem_rsvmap = cpu_to_fdt32(off_mem_rsvmap); ofs += sizeof(struct fdt_reserve_entry) * OF_MAX_RESERVE_MAP; fdt.dt_nextofs = ofs; - ret = __of_flatten_dtb(&fdt, node); + ret = __of_flatten_dtb(&fdt, node, 1); if (ret) goto out_free; + + memreserve = of_find_node_by_name(node, "memreserve"); + if (memreserve) { + const void *entries = of_get_property(memreserve, "reg", &len); + + if (entries) + memcpy(fdt.dt + off_mem_rsvmap, entries, len); + } + nh = fdt.dt + fdt.dt_nextofs; nh->tag = cpu_to_fdt32(FDT_END); fdt.dt_nextofs = dt_next_ofs(fdt.dt_nextofs, sizeof(struct fdt_node_header)); @@ -453,7 +536,18 @@ void fdt_add_reserve_map(void *__fdt) struct of_reserve_map *res = &of_reserve_map; struct fdt_reserve_entry *fdt_res = __fdt + be32_to_cpu(fdt->off_mem_rsvmap); - int i; + int i, n; + + n = of_reservemap_num_entries(fdt); + if (n < 0) + return; + + if (n + res->num_entries + 2 > OF_MAX_FREE_RESERVE_MAP) { + pr_err("Too many entries in reserve map\n"); + return; + } + + fdt_res += n; for (i = 0; i < res->num_entries; i++) { of_write_number(&fdt_res->address, res->start[i], 2); |