]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/fdt_support.c
Merge branch 'u-boot-ti/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / common / fdt_support.c
index fe85a8be1c381cc4a97e6795d74eb99b7dd0dc4e..7927a83b896988441d3358a0071c55c26c4c2bb5 100644 (file)
@@ -32,18 +32,6 @@ static int get_cells_len(const void *fdt, const char *nr_cells_name)
        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;
-       }
-}
-
 /**
  * fdt_getprop_u32_default_node - Return a node's property or a default
  *
@@ -212,22 +200,32 @@ static int fdt_fixup_stdout(void *fdt, int chosenoff)
 }
 #endif
 
+static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name,
+                                 uint64_t val, int is_u64)
+{
+       if (is_u64)
+               return fdt_setprop_u64(fdt, nodeoffset, name, val);
+       else
+               return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
+}
+
+
 int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
 {
-       int   nodeoffset, addr_cell_len;
+       int   nodeoffset;
        int   err, j, total;
-       fdt64_t  tmp;
+       int is_u64;
        uint64_t addr, size;
 
+       /* just return if the size of initrd is zero */
+       if (initrd_start == initrd_end)
+               return 0;
+
        /* find or create "/chosen" node. */
        nodeoffset = fdt_find_or_add_subnode(fdt, 0, "chosen");
        if (nodeoffset < 0)
                return nodeoffset;
 
-       /* just return if initrd_start/end aren't valid */
-       if ((initrd_start == 0) || (initrd_end == 0))
-               return 0;
-
        total = fdt_num_mem_rsv(fdt);
 
        /*
@@ -248,19 +246,20 @@ int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
                return err;
        }
 
-       addr_cell_len = get_cells_len(fdt, "#address-cells");
+       is_u64 = (get_cells_len(fdt, "#address-cells") == 8);
+
+       err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-start",
+                             (uint64_t)initrd_start, is_u64);
 
-       write_cell((u8 *)&tmp, initrd_start, addr_cell_len);
-       err = fdt_setprop(fdt, nodeoffset,
-                         "linux,initrd-start", &tmp, addr_cell_len);
        if (err < 0) {
                printf("WARNING: could not set linux,initrd-start %s.\n",
                       fdt_strerror(err));
                return err;
        }
-       write_cell((u8 *)&tmp, initrd_end, addr_cell_len);
-       err = fdt_setprop(fdt, nodeoffset,
-                       "linux,initrd-end", &tmp, addr_cell_len);
+
+       err = fdt_setprop_uxx(fdt, nodeoffset, "linux,initrd-end",
+                             (uint64_t)initrd_end, is_u64);
+
        if (err < 0) {
                printf("WARNING: could not set linux,initrd-end %s.\n",
                       fdt_strerror(err));
@@ -380,6 +379,34 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
        do_fixup_by_compat(fdt, compat, prop, &tmp, 4, create);
 }
 
+/*
+ * fdt_pack_reg - pack address and size array into the "reg"-suitable stream
+ */
+static int fdt_pack_reg(const void *fdt, void *buf, uint64_t *address,
+                       uint64_t *size, int n)
+{
+       int i;
+       int address_len = get_cells_len(fdt, "#address-cells");
+       int size_len = get_cells_len(fdt, "#size-cells");
+       char *p = buf;
+
+       for (i = 0; i < n; i++) {
+               if (address_len == 8)
+                       *(fdt64_t *)p = cpu_to_fdt64(address[i]);
+               else
+                       *(fdt32_t *)p = cpu_to_fdt32(address[i]);
+               p += address_len;
+
+               if (size_len == 8)
+                       *(fdt64_t *)p = cpu_to_fdt64(size[i]);
+               else
+                       *(fdt32_t *)p = cpu_to_fdt32(size[i]);
+               p += size_len;
+       }
+
+       return p - (char *)buf;
+}
+
 #ifdef CONFIG_NR_DRAM_BANKS
 #define MEMORY_BANKS_MAX CONFIG_NR_DRAM_BANKS
 #else
@@ -388,9 +415,8 @@ void do_fixup_by_compat_u32(void *fdt, const char *compat,
 int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
 {
        int err, nodeoffset;
-       int addr_cell_len, size_cell_len, len;
+       int len;
        u8 tmp[MEMORY_BANKS_MAX * 16]; /* Up to 64-bit address + 64-bit size */
-       int bank;
 
        if (banks > MEMORY_BANKS_MAX) {
                printf("%s: num banks %d exceeds hardcoded limit %d."
@@ -418,16 +444,7 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
                return err;
        }
 
-       addr_cell_len = get_cells_len(blob, "#address-cells");
-       size_cell_len = get_cells_len(blob, "#size-cells");
-
-       for (bank = 0, len = 0; bank < banks; bank++) {
-               write_cell(tmp + len, start[bank], addr_cell_len);
-               len += addr_cell_len;
-
-               write_cell(tmp + len, size[bank], size_cell_len);
-               len += size_cell_len;
-       }
+       len = fdt_pack_reg(blob, tmp, start, size, banks);
 
        err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
        if (err < 0) {