summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2013-04-04 14:20:32 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2013-04-04 14:20:32 +0200
commitc4da77611c7b04778eeba2a153447a81fd3a4c49 (patch)
tree315fd447e2751c331e3931d3691a3b2acc128b83 /common
parent70867916a716880b925790bd7fed308d7fd2e112 (diff)
parent90ab1ee199843abd6409be3a5fdf532ce0ff6cc4 (diff)
downloadbarebox-c4da77611c7b04778eeba2a153447a81fd3a4c49.tar.gz
barebox-c4da77611c7b04778eeba2a153447a81fd3a4c49.tar.xz
Merge branch 'for-next/oftree'
Diffstat (limited to 'common')
-rw-r--r--common/memory.c70
-rw-r--r--common/oftree.c314
2 files changed, 44 insertions, 340 deletions
diff --git a/common/memory.c b/common/memory.c
index 81641f0527..7ec211b8da 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -21,7 +21,6 @@
#include <memory.h>
#include <of.h>
#include <init.h>
-#include <libfdt.h>
#include <linux/ioport.h>
#include <asm-generic/memory_layout.h>
#include <asm/sections.h>
@@ -164,71 +163,38 @@ int release_sdram_region(struct resource *res)
#ifdef CONFIG_OFTREE
-/*
- * Get cells len in bytes
- * if #NNNN-cells property is 2 then len is 8
- * otherwise len is 4
- */
-static int get_cells_len(struct fdt_header *fdt, char *nr_cells_name)
-{
- const u32 *cell;
-
- cell = fdt_getprop(fdt, 0, nr_cells_name, NULL);
- if (cell && *cell == 2)
- return 8;
-
- return 4;
-}
-
-/*
- * Write a 4 or 8 byte big endian cell
- */
-static void write_cell(u8 *addr, u64 val, int size)
-{
- int shift = (size - 1) * 8;
-
- while (size-- > 0) {
- *addr++ = (val >> shift) & 0xff;
- shift -= 8;
- }
-}
-
-static int of_memory_fixup(struct fdt_header *fdt)
+static int of_memory_fixup(struct device_node *node)
{
struct memory_bank *bank;
- int err, nodeoffset;
+ int err;
int addr_cell_len, size_cell_len, len = 0;
+ struct device_node *memnode;
u8 tmp[16 * 16]; /* Up to 64-bit address + 64-bit size */
- /* update, or add and update /memory node */
- nodeoffset = fdt_get_path_or_create(fdt, "/memory");
- if (nodeoffset < 0)
- return nodeoffset;
+ memnode = of_create_node(node, "/memory");
+ if (!memnode)
+ return -ENOMEM;
- err = fdt_setprop(fdt, nodeoffset, "device_type", "memory",
- sizeof("memory"));
- if (err < 0) {
- printf("WARNING: could not set %s %s.\n", "device_type",
- fdt_strerror(err));
+ err = of_set_property(memnode, "device_type", "memory", sizeof("memory"), 1);
+ if (err)
return err;
- }
- addr_cell_len = get_cells_len(fdt, "#address-cells");
- size_cell_len = get_cells_len(fdt, "#size-cells");
+ addr_cell_len = of_n_addr_cells(memnode);
+ size_cell_len = of_n_size_cells(memnode);
for_each_memory_bank(bank) {
- write_cell(tmp + len, bank->start, addr_cell_len);
- len += addr_cell_len;
- write_cell(tmp + len, bank->size, size_cell_len);
- len += size_cell_len;
+ of_write_number(tmp + len, bank->start, addr_cell_len);
+ len += addr_cell_len * 4;
+ of_write_number(tmp + len, bank->size, size_cell_len);
+ len += size_cell_len * 4;
}
- err = fdt_setprop(fdt, nodeoffset, "reg", tmp, len);
- if (err < 0) {
- printf("WARNING: could not set %s %s.\n",
- "reg", fdt_strerror(err));
+ err = of_set_property(memnode, "reg", tmp, len, 1);
+ if (err) {
+ pr_err("could not set reg %s.\n", strerror(-err));
return err;
}
+
return 0;
}
diff --git a/common/oftree.c b/common/oftree.c
index 82e5ddd60b..776d301186 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -5,7 +5,6 @@
#include <command.h>
#include <fs.h>
#include <malloc.h>
-#include <libfdt.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
#include <errno.h>
@@ -99,266 +98,24 @@ void of_print_property(const void *data, int len)
}
}
-static void printf_indent(int level, const char *fmt, ...)
+static int of_fixup_bootargs(struct device_node *root)
{
- va_list args;
-
- printf("%*s", level * 8, "");
-
- va_start (args, fmt);
- vprintf(fmt, args);
- va_end (args);
-}
-
-int fdt_print(struct fdt_header *working_fdt, const char *pathp)
-{
- const void *nodep; /* property node pointer */
- int nodeoffset; /* node offset from libfdt */
- int nextoffset; /* next node offset from libfdt */
- uint32_t tag; /* tag */
- int len; /* length of the property */
- int level = 0; /* keep track of nesting level */
- const struct fdt_property *fdt_prop;
-
- nodeoffset = fdt_path_offset(working_fdt, pathp);
- if (nodeoffset < 0) {
- /*
- * Not found or something else bad happened.
- */
- printf("libfdt fdt_path_offset() returned %s\n",
- fdt_strerror(nodeoffset));
- return 1;
- }
-
- while (level >= 0) {
- tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset);
- switch (tag) {
- case FDT_BEGIN_NODE:
- pathp = fdt_get_name(working_fdt, nodeoffset, NULL);
- if (pathp == NULL)
- pathp = "/* NULL pointer error */";
- if (*pathp == '\0')
- pathp = "/"; /* root is nameless */
- printf_indent(level, "%s {\n",pathp);
- level++;
- if (level >= MAX_LEVEL) {
- printf("Nested too deep, aborting.\n");
- return 1;
- }
- break;
- case FDT_END_NODE:
- level--;
- printf_indent(level, "};\n");
- if (level == 0) {
- level = -1; /* exit the loop */
- }
- break;
- case FDT_PROP:
- fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset,
- sizeof(*fdt_prop));
- pathp = fdt_string(working_fdt,
- fdt32_to_cpu(fdt_prop->nameoff));
- len = fdt32_to_cpu(fdt_prop->len);
- nodep = fdt_prop->data;
- if (len < 0) {
- printf("libfdt fdt_getprop(): %s\n",
- fdt_strerror(len));
- return 1;
- } else if (len == 0) {
- /* the property has no value */
- printf_indent(level, "%s;\n", pathp);
- } else {
- printf_indent(level, "%s = ", pathp);
- of_print_property(nodep, len);
- printf(";\n");
- }
- break;
- case FDT_NOP:
- printf_indent(level, "/* NOP */\n");
- break;
- case FDT_END:
- return 1;
- default:
- printf("Unknown tag 0x%08X\n", tag);
- return 1;
- }
- nodeoffset = nextoffset;
- }
- return 0;
-}
-
-/**
- * fdt_find_and_setprop: Find a node and set it's property
- *
- * @fdt: ptr to device tree
- * @node: path of node
- * @prop: property name
- * @val: ptr to new value
- * @len: length of new property value
- * @create: flag to create the property if it doesn't exist
- *
- * Convenience function to directly set a property given the path to the node.
- */
-int fdt_find_and_setprop(struct fdt_header *fdt, const char *node,
- const char *prop, const void *val, int len, int create)
-{
- int nodeoff = fdt_path_offset(fdt, node);
-
- if (nodeoff < 0)
- return nodeoff;
-
- if ((!create) && (fdt_get_property(fdt, nodeoff, prop, NULL) == NULL))
- return 0; /* create flag not set; so exit quietly */
-
- return fdt_setprop(fdt, nodeoff, prop, val, len);
-}
-
-void do_fixup_by_path(struct fdt_header *fdt, const char *path,
- const char *prop, const void *val, int len, int create)
-{
- int rc = fdt_find_and_setprop(fdt, path, prop, val, len, create);
- if (rc)
- printf("Unable to update property %s:%s, err=%s\n",
- path, prop, fdt_strerror(rc));
-}
-
-void do_fixup_by_path_u32(struct fdt_header *fdt, const char *path,
- const char *prop, u32 val, int create)
-{
- val = cpu_to_fdt32(val);
- do_fixup_by_path(fdt, path, prop, &val, sizeof(val), create);
-}
-
-void do_fixup_by_compatible(struct fdt_header *fdt, const char *compatible,
- const char *prop, const void *val, int len, int create)
-{
- int off = -1;
-
- off = fdt_node_offset_by_compatible(fdt, -1, compatible);
- while (off != -FDT_ERR_NOTFOUND) {
- if (create || (fdt_get_property(fdt, off, prop, 0) != NULL))
- fdt_setprop(fdt, off, prop, val, len);
- off = fdt_node_offset_by_compatible(fdt, off, compatible);
- }
-}
-
-void do_fixup_by_compatible_u32(struct fdt_header *fdt, const char *compatible,
- const char *prop, u32 val, int create)
-{
- val = cpu_to_fdt32(val);
- do_fixup_by_compatible(fdt, compatible, prop, &val, 4, create);
-}
-
-void do_fixup_by_compatible_string(struct fdt_header *fdt, const char *compatible,
- const char *prop, const char *val, int create)
-{
- do_fixup_by_compatible(fdt, compatible, prop, val, strlen(val) + 1,
- create);
-}
-
-int fdt_get_path_or_create(struct fdt_header *fdt, const char *path)
-{
- int nodeoffset;
-
- nodeoffset = fdt_path_offset (fdt, path);
- if (nodeoffset < 0) {
- nodeoffset = fdt_add_subnode(fdt, 0, path + 1);
- if (nodeoffset < 0) {
- printf("WARNING: could not create %s %s.\n",
- path, fdt_strerror(nodeoffset));
- return -EINVAL;
- }
- }
-
- return nodeoffset;
-}
-
-int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end, int force)
-{
- int nodeoffset;
- int err, j, total;
- u32 tmp;
- const char *path;
- uint64_t addr, size;
-
- /* Find the "chosen" node */
- nodeoffset = fdt_path_offset(fdt, "/chosen");
-
- /* If there is no "chosen" node in the blob return */
- if (nodeoffset < 0) {
- printf("fdt_initrd: %s\n", fdt_strerror(nodeoffset));
- return nodeoffset;
- }
+ struct device_node *node;
+ const char *str;
+ int err;
- /* just return if initrd_start/end aren't valid */
- if ((initrd_start == 0) || (initrd_end == 0))
+ str = linux_bootargs_get();
+ if (!str)
return 0;
- total = fdt_num_mem_rsv(fdt);
-
- /*
- * Look for an existing entry and update it. If we don't find
- * the entry, we will j be the next available slot.
- */
- for (j = 0; j < total; j++) {
- err = fdt_get_mem_rsv(fdt, j, &addr, &size);
- if (addr == initrd_start) {
- fdt_del_mem_rsv(fdt, j);
- break;
- }
- }
-
- err = fdt_add_mem_rsv(fdt, initrd_start, initrd_end - initrd_start);
- if (err < 0) {
- printf("fdt_initrd: %s\n", fdt_strerror(err));
- return err;
- }
-
- path = fdt_getprop(fdt, nodeoffset, "linux,initrd-start", NULL);
- if (!path || force) {
- tmp = __cpu_to_be32(initrd_start);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-start", &tmp, sizeof(tmp));
- if (err < 0) {
- printf("WARNING: "
- "could not set linux,initrd-start %s.\n",
- fdt_strerror(err));
- return err;
- }
- tmp = __cpu_to_be32(initrd_end);
- err = fdt_setprop(fdt, nodeoffset,
- "linux,initrd-end", &tmp, sizeof(tmp));
- if (err < 0) {
- printf("WARNING: could not set linux,initrd-end %s.\n",
- fdt_strerror(err));
-
- return err;
- }
- }
-
- return 0;
-}
-
-static int of_fixup_bootargs(struct fdt_header *fdt)
-{
- int nodeoffset;
- const char *str;
- int err;
+ node = of_create_node(root, "/chosen");
+ if (!node)
+ return -ENOMEM;
- nodeoffset = fdt_get_path_or_create(fdt, "/chosen");
- if (nodeoffset < 0)
- return nodeoffset;
- str = linux_bootargs_get();
- if (str) {
- err = fdt_setprop(fdt, nodeoffset,
- "bootargs", str, strlen(str)+1);
- if (err < 0)
- printf("WARNING: could not set bootargs %s.\n",
- fdt_strerror(err));
- }
+ err = of_set_property(node, "bootargs", str, strlen(str) + 1, 1);
- return 0;
+ return err;
}
static int of_register_bootargs_fixup(void)
@@ -368,13 +125,13 @@ static int of_register_bootargs_fixup(void)
late_initcall(of_register_bootargs_fixup);
struct of_fixup {
- int (*fixup)(struct fdt_header *);
+ int (*fixup)(struct device_node *);
struct list_head list;
};
static LIST_HEAD(of_fixup_list);
-int of_register_fixup(int (*fixup)(struct fdt_header *))
+int of_register_fixup(int (*fixup)(struct device_node *))
{
struct of_fixup *of_fixup = xzalloc(sizeof(*of_fixup));
@@ -389,13 +146,13 @@ int of_register_fixup(int (*fixup)(struct fdt_header *))
* Apply registered fixups for the given fdt. The fdt must have
* enough free space to apply the fixups.
*/
-int of_fix_tree(struct fdt_header *fdt)
+int of_fix_tree(struct device_node *node)
{
struct of_fixup *of_fixup;
int ret;
list_for_each_entry(of_fixup, &of_fixup_list, list) {
- ret = of_fixup->fixup(fdt);
+ ret = of_fixup->fixup(node);
if (ret)
return ret;
}
@@ -415,43 +172,24 @@ int of_fix_tree(struct fdt_header *fdt)
* It increases the size of the tree and applies the registered
* fixups.
*/
-struct fdt_header *of_get_fixed_tree(struct fdt_header *fdt)
+struct fdt_header *of_get_fixed_tree(struct device_node *node)
{
int ret;
- void *fixfdt, *internalfdt = NULL;
- int size, align;
+ struct fdt_header *fdt;
- if (!fdt) {
- fdt = internalfdt = of_flatten_dtb();
- if (!fdt)
+ if (!node) {
+ node = of_get_root_node();
+ if (!node)
return NULL;
}
- size = fdt_totalsize(fdt);
-
- /*
- * ARM Linux uses a single 1MiB section (with 1MiB alignment)
- * for mapping the devicetree, so we are not allowed to cross
- * 1MiB boundaries.
- */
- align = 1 << fls(size + OFTREE_SIZE_INCREASE - 1);
-
- fixfdt = xmemalign(align, size + OFTREE_SIZE_INCREASE);
- ret = fdt_open_into(fdt, fixfdt, size + OFTREE_SIZE_INCREASE);
-
- free(internalfdt);
-
- if (ret)
- goto out_free;
-
- ret = of_fix_tree(fixfdt);
+ ret = of_fix_tree(node);
if (ret)
- goto out_free;
-
- return fixfdt;
+ return NULL;
-out_free:
- free(fixfdt);
+ fdt = of_flatten_dtb(node);
+ if (!fdt)
+ return NULL;
- return NULL;
+ return fdt;
}