colibri_imx6: fix video stdout in default environment
[oweals/u-boot.git] / lib / fdtdec.c
index d0ba8889733592001dc41d3a4a77a54270c6ce4c..1f2b763acc312a27490a11ecc3a2dd42e3dfced3 100644 (file)
@@ -7,10 +7,17 @@
 #include <common.h>
 #include <boot_fit.h>
 #include <dm.h>
+#include <hang.h>
+#include <init.h>
+#include <log.h>
+#include <malloc.h>
+#include <net.h>
 #include <dm/of_extra.h>
+#include <env.h>
 #include <errno.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
+#include <gzip.h>
 #include <mapmem.h>
 #include <linux/libfdt.h>
 #include <serial.h>
@@ -184,60 +191,6 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name)
 }
 
 #if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI)
-int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
-                       const char *prop_name, struct fdt_pci_addr *addr)
-{
-       const u32 *cell;
-       int len;
-       int ret = -ENOENT;
-
-       debug("%s: %s: ", __func__, prop_name);
-
-       /*
-        * If we follow the pci bus bindings strictly, we should check
-        * the value of the node's parent node's #address-cells and
-        * #size-cells. They need to be 3 and 2 accordingly. However,
-        * for simplicity we skip the check here.
-        */
-       cell = fdt_getprop(blob, node, prop_name, &len);
-       if (!cell)
-               goto fail;
-
-       if ((len % FDT_PCI_REG_SIZE) == 0) {
-               int num = len / FDT_PCI_REG_SIZE;
-               int i;
-
-               for (i = 0; i < num; i++) {
-                       debug("pci address #%d: %08lx %08lx %08lx\n", i,
-                             (ulong)fdt32_to_cpu(cell[0]),
-                             (ulong)fdt32_to_cpu(cell[1]),
-                             (ulong)fdt32_to_cpu(cell[2]));
-                       if ((fdt32_to_cpu(*cell) & type) == type) {
-                               addr->phys_hi = fdt32_to_cpu(cell[0]);
-                               addr->phys_mid = fdt32_to_cpu(cell[1]);
-                               addr->phys_lo = fdt32_to_cpu(cell[1]);
-                               break;
-                       }
-
-                       cell += (FDT_PCI_ADDR_CELLS +
-                                FDT_PCI_SIZE_CELLS);
-               }
-
-               if (i == num) {
-                       ret = -ENXIO;
-                       goto fail;
-               }
-
-               return 0;
-       }
-
-       ret = -EINVAL;
-
-fail:
-       debug("(not found)\n");
-       return ret;
-}
-
 int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
 {
        const char *list, *end;
@@ -274,7 +227,7 @@ int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
        return -ENOENT;
 }
 
-int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
+int fdtdec_get_pci_bar32(const struct udevice *dev, struct fdt_pci_addr *addr,
                         u32 *bar)
 {
        int barnum;
@@ -294,7 +247,7 @@ int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
                           uint64_t default_val)
 {
-       const uint64_t *cell64;
+       const unaligned_fdt64_t *cell64;
        int length;
 
        cell64 = fdt_getprop(blob, node, prop_name, &length);
@@ -859,17 +812,6 @@ int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
        return rc;
 }
 
-int fdtdec_get_child_count(const void *blob, int node)
-{
-       int subnode;
-       int num = 0;
-
-       fdt_for_each_subnode(subnode, blob, node)
-               num++;
-
-       return num;
-}
-
 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
                          u8 *array, int count)
 {
@@ -1261,6 +1203,35 @@ __weak void *board_fdt_blob_setup(void)
 }
 #endif
 
+int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size)
+{
+       const char *path;
+       int offset, err;
+
+       if (!is_valid_ethaddr(mac))
+               return -EINVAL;
+
+       path = fdt_get_alias(fdt, "ethernet");
+       if (!path)
+               return 0;
+
+       debug("ethernet alias found: %s\n", path);
+
+       offset = fdt_path_offset(fdt, path);
+       if (offset < 0) {
+               debug("ethernet alias points to absent node %s\n", path);
+               return -ENOENT;
+       }
+
+       err = fdt_setprop_inplace(fdt, offset, "local-mac-address", mac, size);
+       if (err < 0)
+               return err;
+
+       debug("MAC address: %pM\n", mac);
+
+       return 0;
+}
+
 static int fdtdec_init_reserved_memory(void *blob)
 {
        int na, ns, node, err;
@@ -1331,8 +1302,10 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename,
                        continue;
                }
 
-               if (addr == carveout->start && (addr + size) == carveout->end) {
-                       *phandlep = fdt_get_phandle(blob, node);
+               if (addr == carveout->start && (addr + size - 1) ==
+                                               carveout->end) {
+                       if (phandlep)
+                               *phandlep = fdt_get_phandle(blob, node);
                        return 0;
                }
        }
@@ -1361,13 +1334,15 @@ int fdtdec_add_reserved_memory(void *blob, const char *basename,
        if (node < 0)
                return node;
 
-       err = fdt_generate_phandle(blob, &phandle);
-       if (err < 0)
-               return err;
+       if (phandlep) {
+               err = fdt_generate_phandle(blob, &phandle);
+               if (err < 0)
+                       return err;
 
-       err = fdtdec_set_phandle(blob, node, phandle);
-       if (err < 0)
-               return err;
+               err = fdtdec_set_phandle(blob, node, phandle);
+               if (err < 0)
+                       return err;
+       }
 
        /* store one or two address cells */
        if (na > 1)
@@ -1450,14 +1425,9 @@ int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
                        const struct fdt_memory *carveout)
 {
        uint32_t phandle;
-       int err, offset;
+       int err, offset, len;
        fdt32_t value;
-
-       /* XXX implement support for multiple phandles */
-       if (index > 0) {
-               debug("invalid index %u\n", index);
-               return -FDT_ERR_BADOFFSET;
-       }
+       void *prop;
 
        err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
        if (err < 0) {
@@ -1473,18 +1443,45 @@ int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
 
        value = cpu_to_fdt32(phandle);
 
-       err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
+       if (!fdt_getprop(blob, offset, prop_name, &len)) {
+               if (len == -FDT_ERR_NOTFOUND)
+                       len = 0;
+               else
+                       return len;
+       }
+
+       if ((index + 1) * sizeof(value) > len) {
+               err = fdt_setprop_placeholder(blob, offset, prop_name,
+                                             (index + 1) * sizeof(value),
+                                             &prop);
+               if (err < 0) {
+                       debug("failed to resize reserved memory property: %s\n",
+                             fdt_strerror(err));
+                       return err;
+               }
+       }
+
+       err = fdt_setprop_inplace_namelen_partial(blob, offset, prop_name,
+                                                 strlen(prop_name),
+                                                 index * sizeof(value),
+                                                 &value, sizeof(value));
        if (err < 0) {
-               debug("failed to set %s property for node %s: %d\n", prop_name,
-                     node, err);
+               debug("failed to update %s property for node %s: %s\n",
+                     prop_name, node, fdt_strerror(err));
                return err;
        }
 
        return 0;
 }
 
+__weak int fdtdec_board_setup(const void *fdt_blob)
+{
+       return 0;
+}
+
 int fdtdec_setup(void)
 {
+       int ret;
 #if CONFIG_IS_ENABLED(OF_CONTROL)
 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
        void *fdt_blob;
@@ -1504,16 +1501,14 @@ int fdtdec_setup(void)
                puts("Failed to read control FDT\n");
                return -1;
        }
+# elif defined(CONFIG_OF_PRIOR_STAGE)
+       gd->fdt_blob = (void *)prior_stage_fdt_address;
 # endif
 # ifndef CONFIG_SPL_BUILD
        /* Allow the early environment to override the fdt address */
-#  if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
-       gd->fdt_blob = (void *)prior_stage_fdt_address;
-#  else
        gd->fdt_blob = map_sysmem
                (env_get_ulong("fdtcontroladdr", 16,
                               (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
-#  endif
 # endif
 
 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
@@ -1539,7 +1534,10 @@ int fdtdec_setup(void)
 # endif
 #endif
 
-       return fdtdec_prepare_fdt();
+       ret = fdtdec_prepare_fdt();
+       if (!ret)
+               ret = fdtdec_board_setup(gd->fdt_blob);
+       return ret;
 }
 
 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)