of: let of_unflatten_dtb return the unflattened tree
In order to be able to handle multiple devicetrees, do not assume the tree to be unflattened is the barebox internal one. Instead, just return a pointer to it and assign the barebox internal root_node external to the unflatten function. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
3afab2a83e
commit
8a185a4ff2
|
@ -17,6 +17,7 @@
|
|||
#include <sizes.h>
|
||||
#include <io.h>
|
||||
#include <libfdt.h>
|
||||
#include <of.h>
|
||||
|
||||
#define FIRMWARE_DTB_BASE 0x1000
|
||||
|
||||
|
@ -63,19 +64,21 @@ static int hb_fixup(struct fdt_header *fdt)
|
|||
|
||||
static int highbank_mem_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct device_node *root, *np;
|
||||
int ret;
|
||||
|
||||
/* load by the firmware at 0x1000 */
|
||||
fdt = IOMEM(FIRMWARE_DTB_BASE);
|
||||
|
||||
ret = of_unflatten_dtb(fdt);
|
||||
if (ret) {
|
||||
root = of_unflatten_dtb(NULL, fdt);
|
||||
if (!root) {
|
||||
pr_warn("no dtb found at 0x1000 use default configuration\n");
|
||||
fdt = NULL;
|
||||
goto not_found;
|
||||
}
|
||||
|
||||
of_set_root_node(root);
|
||||
|
||||
np = of_find_node_by_path("/memory");
|
||||
if (!np) {
|
||||
pr_warn("no memory node use default configuration\n");
|
||||
|
@ -109,7 +112,7 @@ static int highbank_devices_init(void)
|
|||
highbank_register_xgmac(0);
|
||||
highbank_register_xgmac(1);
|
||||
} else {
|
||||
fdt = of_get_fixed_tree(fdt);
|
||||
fdt = of_get_fixed_tree(NULL);
|
||||
add_mem_device("dtb", (unsigned long)fdt, fdt_totalsize(fdt),
|
||||
IORESOURCE_MEM_WRITEABLE);
|
||||
devfs_add_partition("ram0", FIRMWARE_DTB_BASE, SZ_64K, DEVFS_PARTITION_FIXED, "firmware-dtb");
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <malloc.h>
|
||||
#include <libfdt.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/err.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
|
@ -52,6 +53,7 @@ static int do_oftree(int argc, char *argv[])
|
|||
int save = 0;
|
||||
int free_of = 0;
|
||||
int ret;
|
||||
struct device_node *n, *root;
|
||||
|
||||
while ((opt = getopt(argc, argv, "dpfn:ls")) > 0) {
|
||||
switch (opt) {
|
||||
|
@ -135,7 +137,17 @@ static int do_oftree(int argc, char *argv[])
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = of_unflatten_dtb(fdt);
|
||||
n = of_get_root_node();
|
||||
|
||||
root = of_unflatten_dtb(n, fdt);
|
||||
if (IS_ERR(root))
|
||||
ret = PTR_ERR(root);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
if (!n)
|
||||
ret = of_set_root_node(root);
|
||||
|
||||
if (ret) {
|
||||
printf("parse oftree: %s\n", strerror(-ret));
|
||||
goto out;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <sizes.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
/**
|
||||
* struct alias_prop - Alias property in 'aliases' node
|
||||
|
@ -561,6 +562,18 @@ struct device_node *of_get_root_node(void)
|
|||
return root_node;
|
||||
}
|
||||
|
||||
int of_set_root_node(struct device_node *node)
|
||||
{
|
||||
if (node && root_node)
|
||||
return -EBUSY;
|
||||
|
||||
root_node = node;
|
||||
|
||||
of_alias_scan();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int of_node_disabled(struct device_node *node)
|
||||
{
|
||||
struct property *p;
|
||||
|
@ -611,15 +624,10 @@ struct device_node *of_new_node(struct device_node *parent, const char *name)
|
|||
{
|
||||
struct device_node *node;
|
||||
|
||||
if (!parent && root_node)
|
||||
return NULL;
|
||||
|
||||
node = xzalloc(sizeof(*node));
|
||||
node->parent = parent;
|
||||
if (parent)
|
||||
list_add_tail(&node->parent_list, &parent->children);
|
||||
else
|
||||
root_node = node;
|
||||
|
||||
INIT_LIST_HEAD(&node->children);
|
||||
INIT_LIST_HEAD(&node->properties);
|
||||
|
@ -927,9 +935,7 @@ void of_free(struct device_node *node)
|
|||
free(node);
|
||||
|
||||
if (node == root_node)
|
||||
root_node = NULL;
|
||||
|
||||
of_alias_scan();
|
||||
of_set_root_node(NULL);
|
||||
}
|
||||
|
||||
static void __of_probe(struct device_node *node)
|
||||
|
@ -1021,11 +1027,15 @@ out:
|
|||
return dn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a flat device tree binary blob and store it in the barebox
|
||||
* internal tree format,
|
||||
/**
|
||||
* of_unflatten_dtb - unflatten a fdt blob
|
||||
* @root - node in which the fdt blob should be merged into or NULL
|
||||
* @fdt - the fdt blob to unflatten
|
||||
*
|
||||
* Parse a flat device tree binary blob and return a pointer to the
|
||||
* unflattened tree.
|
||||
*/
|
||||
int of_unflatten_dtb(struct fdt_header *fdt)
|
||||
struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *fdt)
|
||||
{
|
||||
const void *nodep; /* property node pointer */
|
||||
int nodeoffset; /* node offset from libfdt */
|
||||
|
@ -1034,8 +1044,9 @@ int of_unflatten_dtb(struct fdt_header *fdt)
|
|||
int len; /* length of the property */
|
||||
const struct fdt_property *fdt_prop;
|
||||
const char *pathp;
|
||||
struct device_node *node = NULL, *n, *root = NULL;
|
||||
struct device_node *node = NULL, *n;
|
||||
struct property *p;
|
||||
int ret;
|
||||
|
||||
nodeoffset = fdt_path_offset(fdt, "/");
|
||||
if (nodeoffset < 0) {
|
||||
|
@ -1044,12 +1055,14 @@ int of_unflatten_dtb(struct fdt_header *fdt)
|
|||
*/
|
||||
printf ("libfdt fdt_path_offset() returned %s\n",
|
||||
fdt_strerror(nodeoffset));
|
||||
return -EINVAL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
root = of_new_node(NULL, NULL);
|
||||
if (!root)
|
||||
return -ENOMEM;
|
||||
if (!root) {
|
||||
root = of_new_node(NULL, NULL);
|
||||
if (!root)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
|
||||
|
@ -1093,16 +1106,18 @@ int of_unflatten_dtb(struct fdt_header *fdt)
|
|||
case FDT_NOP:
|
||||
break;
|
||||
case FDT_END:
|
||||
of_alias_scan();
|
||||
return 0;
|
||||
return root;
|
||||
default:
|
||||
printf("Unknown tag 0x%08X\n", tag);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
nodeoffset = nextoffset;
|
||||
}
|
||||
err:
|
||||
of_free(root);
|
||||
|
||||
return 0;
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static int __of_flatten_dtb(void *fdt, struct device_node *node)
|
||||
|
|
|
@ -133,7 +133,7 @@ void of_print_nodes(struct device_node *node, int indent);
|
|||
int of_probe(void);
|
||||
int of_parse_dtb(struct fdt_header *fdt);
|
||||
void of_free(struct device_node *node);
|
||||
int of_unflatten_dtb(struct fdt_header *fdt);
|
||||
struct device_node *of_unflatten_dtb(struct device_node *root, struct fdt_header *fdt);
|
||||
struct device_node *of_new_node(struct device_node *parent, const char *name);
|
||||
struct property *of_new_property(struct device_node *node, const char *name,
|
||||
const void *data, int len);
|
||||
|
@ -150,6 +150,7 @@ int of_parse_partitions(const char *cdevname,
|
|||
struct device_node *node);
|
||||
|
||||
struct device_node *of_get_root_node(void);
|
||||
int of_set_root_node(struct device_node *);
|
||||
int of_alias_get_id(struct device_node *np, const char *stem);
|
||||
int of_device_is_stdout_path(struct device_d *dev);
|
||||
const char *of_get_model(void);
|
||||
|
|
Loading…
Reference in New Issue