]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/fdt_support.c
karo: configs: Update the tx6*_defconfig files from defconfigs generated with 'make...
[karo-tx-uboot.git] / common / fdt_support.c
index a405cb8039b0a753afe0a8747f8257edd3f5f9c2..6a5f761cadd13a974c936b8f6890615c6c7dbf82 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <common.h>
+#include <inttypes.h>
 #include <stdio_dev.h>
 #include <linux/ctype.h>
 #include <linux/types.h>
@@ -193,6 +194,31 @@ static inline int fdt_setprop_uxx(void *fdt, int nodeoffset, const char *name,
                return fdt_setprop_u32(fdt, nodeoffset, name, (uint32_t)val);
 }
 
+int fdt_root(void *fdt)
+{
+       char *serial;
+       int err;
+
+       err = fdt_check_header(fdt);
+       if (err < 0) {
+               printf("fdt_root: %s\n", fdt_strerror(err));
+               return err;
+       }
+
+       serial = getenv("serial#");
+       if (serial) {
+               err = fdt_setprop(fdt, 0, "serial-number", serial,
+                                 strlen(serial) + 1);
+
+               if (err < 0) {
+                       printf("WARNING: could not set serial-number %s.\n",
+                              fdt_strerror(err));
+                       return err;
+               }
+       }
+
+       return 0;
+}
 
 int fdt_initrd(void *fdt, ulong initrd_start, ulong initrd_end)
 {
@@ -370,22 +396,22 @@ static int fdt_pack_reg(const void *fdt, void *buf, u64 *address, u64 *size,
                        int n)
 {
        int i;
-       int address_len = fdt_address_cells(fdt, 0);
-       int size_len = fdt_size_cells(fdt, 0);
+       int address_cells = fdt_address_cells(fdt, 0);
+       int size_cells = fdt_size_cells(fdt, 0);
        char *p = buf;
 
        for (i = 0; i < n; i++) {
-               if (address_len == 2)
+               if (address_cells == 2)
                        *(fdt64_t *)p = cpu_to_fdt64(address[i]);
                else
                        *(fdt32_t *)p = cpu_to_fdt32(address[i]);
-               p += address_len;
+               p += 4 * address_cells;
 
-               if (size_len == 2)
+               if (size_cells == 2)
                        *(fdt64_t *)p = cpu_to_fdt64(size[i]);
                else
                        *(fdt32_t *)p = cpu_to_fdt32(size[i]);
-               p += size_len;
+               p += 4 * size_cells;
        }
 
        return p - (char *)buf;
@@ -428,6 +454,9 @@ int fdt_fixup_memory_banks(void *blob, u64 start[], u64 size[], int banks)
                return err;
        }
 
+       if (!banks)
+               return 0;
+
        len = fdt_pack_reg(blob, tmp, start, size, banks);
 
        err = fdt_setprop(blob, nodeoffset, "reg", tmp, len);
@@ -531,7 +560,8 @@ int fdt_shrink_to_minimum(void *blob)
        ret = fdt_add_mem_rsv(blob, (uintptr_t)blob, actualsize);
        if (ret < 0)
                return ret;
-
+       if (getenv("fdtsize"))
+               setenv_hex("fdtsize", actualsize);
        return actualsize;
 }
 
@@ -701,7 +731,7 @@ struct reg_cell {
        unsigned int r1;
 };
 
-int fdt_del_subnodes(const void *blob, int parent_offset)
+static int fdt_del_subnodes(const void *blob, int parent_offset)
 {
        int off, ndepth;
        int ret;
@@ -709,18 +739,22 @@ int fdt_del_subnodes(const void *blob, int parent_offset)
        for (ndepth = 0, off = fdt_next_node(blob, parent_offset, &ndepth);
             (off >= 0) && (ndepth > 0);
             off = fdt_next_node(blob, off, &ndepth)) {
-               if (ndepth == 1) {
-                       debug("delete %s: offset: %x\n",
-                               fdt_get_name(blob, off, 0), off);
-                       ret = fdt_del_node((void *)blob, off);
-                       if (ret < 0) {
-                               printf("Can't delete node: %s\n",
-                                       fdt_strerror(ret));
-                               return ret;
-                       } else {
-                               ndepth = 0;
-                               off = parent_offset;
-                       }
+               if (ndepth < 0)
+                       break;
+               else if (ndepth != 1)
+                       continue;
+               else if (fdt_getprop(blob, off, "compatible", NULL))
+                       continue;
+               debug("delete %s: offset: %x\n",
+                       fdt_get_name(blob, off, 0), off);
+               ret = fdt_del_node((void *)blob, off);
+               if (ret < 0) {
+                       printf("Can't delete node: %s\n",
+                               fdt_strerror(ret));
+                       return ret;
+               } else {
+                       ndepth = 0;
+                       off = parent_offset;
                }
        }
        return 0;
@@ -730,11 +764,16 @@ int fdt_del_partitions(void *blob, int parent_offset)
 {
        const void *prop;
        int ndepth = 0;
-       int off;
+       int off = parent_offset;
        int ret;
 
-       off = fdt_next_node(blob, parent_offset, &ndepth);
-       if (off > 0 && ndepth == 1) {
+       while ((off = fdt_next_node(blob, off, &ndepth)) > 0) {
+               if (ndepth < 0)
+                       break;
+               else if (ndepth != 1)
+                       continue;
+               else if (fdt_getprop(blob, off, "compatible", NULL))
+                       continue;
                prop = fdt_getprop(blob, off, "label", NULL);
                if (prop == NULL) {
                        /*
@@ -760,7 +799,7 @@ int fdt_node_set_part_info(void *blob, int parent_offset,
        struct list_head *pentry;
        struct part_info *part;
        struct reg_cell cell;
-       int off, ndepth = 0;
+       int off = parent_offset, ndepth = 0;
        int part_num, ret;
        char buf[64];
 
@@ -772,10 +811,16 @@ int fdt_node_set_part_info(void *blob, int parent_offset,
         * Check if it is nand {}; subnode, adjust
         * the offset in this case
         */
-       off = fdt_next_node(blob, parent_offset, &ndepth);
-       if (off > 0 && ndepth == 1)
+       while ((off = fdt_next_node(blob, off, &ndepth)) > 0) {
+               if (ndepth < 0)
+                       break;
+               else if (ndepth != 1)
+                       continue;
+               else if (fdt_getprop(blob, off, "compatible", NULL))
+                       continue;
                parent_offset = off;
-
+               break;
+       }
        part_num = 0;
        list_for_each_prev(pentry, &dev->parts) {
                int newoff;
@@ -914,8 +959,6 @@ void fdt_del_node_and_alias(void *blob, const char *alias)
        fdt_delprop(blob, off, alias);
 }
 
-#define PRu64  "%llx"
-
 /* Max address size we deal with */
 #define OF_MAX_ADDR_CELLS      4
 #define OF_BAD_ADDR    ((u64)-1)
@@ -973,8 +1016,8 @@ static u64 of_bus_default_map(fdt32_t *addr, const fdt32_t *range,
        s  = of_read_number(range + na + pna, ns);
        da = of_read_number(addr, na);
 
-       debug("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n",
-           cp, s, da);
+       debug("OF: default map, cp=%" PRIu64 ", s=%" PRIu64
+             ", da=%" PRIu64 "\n", cp, s, da);
 
        if (da < cp || da >= (cp + s))
                return OF_BAD_ADDR;
@@ -1052,7 +1095,7 @@ static int of_translate_one(void * blob, int parent, struct of_bus *bus,
 
  finish:
        of_dump_addr("OF: parent translation for:", addr, pna);
-       debug("OF: with offset: "PRu64"\n", offset);
+       debug("OF: with offset: %" PRIu64 "\n", offset);
 
        /* Translate it into parent bus space */
        return pbus->translate(addr, offset, pna);
@@ -1086,7 +1129,7 @@ static u64 __of_translate_address(void *blob, int node_offset, const fdt32_t *in
                goto bail;
        bus = &of_busses[0];
 
-       /* Cound address cells & copy address locally */
+       /* Count address cells & copy address locally */
        bus->count_cells(blob, parent, &na, &ns);
        if (!OF_CHECK_COUNTS(na, ns)) {
                printf("%s: Bad cell count for %s\n", __FUNCTION__,
@@ -1178,7 +1221,8 @@ int fdt_node_offset_by_compat_reg(void *blob, const char *compat,
  */
 int fdt_alloc_phandle(void *blob)
 {
-       int offset, phandle = 0;
+       int offset;
+       uint32_t phandle = 0;
 
        for (offset = fdt_next_node(blob, -1, NULL); offset >= 0;
             offset = fdt_next_node(blob, offset, NULL)) {
@@ -1380,9 +1424,9 @@ int fdt_verify_alias_address(void *fdt, int anode, const char *alias, u64 addr)
 
        dt_addr = fdt_translate_address(fdt, node, reg);
        if (addr != dt_addr) {
-               printf("Warning: U-Boot configured device %s at address %llx,\n"
-                      " but the device tree has it address %llx.\n",
-                      alias, addr, dt_addr);
+               printf("Warning: U-Boot configured device %s at address %"
+                      PRIx64 ",\n but the device tree has it address %"
+                      PRIx64 ".\n", alias, addr, dt_addr);
                return 0;
        }
 
@@ -1498,3 +1542,94 @@ int fdt_read_range(void *fdt, int node, int n, uint64_t *child_addr,
 
        return 0;
 }
+
+/**
+ * fdt_setup_simplefb_node - Fill and enable a simplefb node
+ *
+ * @fdt: ptr to device tree
+ * @node: offset of the simplefb node
+ * @base_address: framebuffer base address
+ * @width: width in pixels
+ * @height: height in pixels
+ * @stride: bytes per line
+ * @format: pixel format string
+ *
+ * Convenience function to fill and enable a simplefb node.
+ */
+int fdt_setup_simplefb_node(void *fdt, int node, u64 base_address, u32 width,
+                           u32 height, u32 stride, const char *format)
+{
+       char name[32];
+       fdt32_t cells[4];
+       int i, addrc, sizec, ret;
+
+       of_bus_default_count_cells(fdt, fdt_parent_offset(fdt, node),
+                                  &addrc, &sizec);
+       i = 0;
+       if (addrc == 2)
+               cells[i++] = cpu_to_fdt32(base_address >> 32);
+       cells[i++] = cpu_to_fdt32(base_address);
+       if (sizec == 2)
+               cells[i++] = 0;
+       cells[i++] = cpu_to_fdt32(height * stride);
+
+       ret = fdt_setprop(fdt, node, "reg", cells, sizeof(cells[0]) * i);
+       if (ret < 0)
+               return ret;
+
+       snprintf(name, sizeof(name), "framebuffer@%" PRIx64, base_address);
+       ret = fdt_set_name(fdt, node, name);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "width", width);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "height", height);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_u32(fdt, node, "stride", stride);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_string(fdt, node, "format", format);
+       if (ret < 0)
+               return ret;
+
+       ret = fdt_setprop_string(fdt, node, "status", "okay");
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * Update native-mode in display-timings from display environment variable.
+ * The node to update are specified by path.
+ */
+int fdt_fixup_display(void *blob, const char *path, const char *display)
+{
+       int off, toff;
+
+       if (!display || !path)
+               return -FDT_ERR_NOTFOUND;
+
+       toff = fdt_path_offset(blob, path);
+       if (toff >= 0)
+               toff = fdt_subnode_offset(blob, toff, "display-timings");
+       if (toff < 0)
+               return toff;
+
+       for (off = fdt_first_subnode(blob, toff);
+            off >= 0;
+            off = fdt_next_subnode(blob, off)) {
+               uint32_t h = fdt_get_phandle(blob, off);
+               debug("%s:0x%x\n", fdt_get_name(blob, off, NULL),
+                     fdt32_to_cpu(h));
+               if (strcasecmp(fdt_get_name(blob, off, NULL), display) == 0)
+                       return fdt_setprop_u32(blob, toff, "native-mode", h);
+       }
+       return toff;
+}