diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-04 14:20:32 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2013-04-04 14:20:32 +0200 |
commit | c4da77611c7b04778eeba2a153447a81fd3a4c49 (patch) | |
tree | 315fd447e2751c331e3931d3691a3b2acc128b83 /common | |
parent | 70867916a716880b925790bd7fed308d7fd2e112 (diff) | |
parent | 90ab1ee199843abd6409be3a5fdf532ce0ff6cc4 (diff) | |
download | barebox-c4da77611c7b04778eeba2a153447a81fd3a4c49.tar.gz barebox-c4da77611c7b04778eeba2a153447a81fd3a4c49.tar.xz |
Merge branch 'for-next/oftree'
Diffstat (limited to 'common')
-rw-r--r-- | common/memory.c | 70 | ||||
-rw-r--r-- | common/oftree.c | 314 |
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; } |