]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - lib/fdtdec.c
fdt: Enhance flashmap function to deal with region properties
[karo-tx-uboot.git] / lib / fdtdec.c
index eb5aa20526fd509618311fdb3b4aab3c6379d46d..4dbd6aee853b8b03ec157d7189882e4f664074e7 100644 (file)
@@ -70,6 +70,9 @@ static const char * const compat_names[COMPAT_COUNT] = {
        COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"),
        COMPAT(TI_TPS65090, "ti,tps65090"),
        COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"),
+       COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
+       COMPAT(PARADE_PS8625, "parade,ps8625"),
+       COMPAT(COMPAT_INTEL_LPC, "intel,lpc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
@@ -380,6 +383,21 @@ int fdtdec_get_alias_node(const void *blob, const char *name)
        return fdt_path_offset(blob, prop);
 }
 
+int fdtdec_get_chosen_node(const void *blob, const char *name)
+{
+       const char *prop;
+       int chosen_node;
+       int len;
+
+       if (!blob)
+               return -FDT_ERR_NOTFOUND;
+       chosen_node = fdt_path_offset(blob, "/chosen");
+       prop = fdt_getprop(blob, chosen_node, name, &len);
+       if (!prop)
+               return -FDT_ERR_NOTFOUND;
+       return fdt_path_offset(blob, prop);
+}
+
 int fdtdec_check_fdt(void)
 {
        /*
@@ -651,20 +669,25 @@ char *fdtdec_get_config_string(const void *blob, const char *prop_name)
        return (char *)nodep;
 }
 
-int fdtdec_decode_region(const void *blob, int node,
-               const char *prop_name, void **ptrp, size_t *size)
+int fdtdec_decode_region(const void *blob, int node, const char *prop_name,
+                        fdt_addr_t *basep, fdt_size_t *sizep)
 {
        const fdt_addr_t *cell;
        int len;
 
-       debug("%s: %s\n", __func__, prop_name);
+       debug("%s: %s: %s\n", __func__, fdt_get_name(blob, node, NULL),
+             prop_name);
        cell = fdt_getprop(blob, node, prop_name, &len);
-       if (!cell || (len != sizeof(fdt_addr_t) * 2))
+       if (!cell || (len < sizeof(fdt_addr_t) * 2)) {
+               debug("cell=%p, len=%d\n", cell, len);
                return -1;
+       }
+
+       *basep = fdt_addr_to_cpu(*cell);
+       *sizep = fdt_size_to_cpu(cell[1]);
+       debug("%s: base=%08lx, size=%lx\n", __func__, (ulong)*basep,
+             (ulong)*sizep);
 
-       *ptrp = map_sysmem(fdt_addr_to_cpu(*cell), *size);
-       *size = fdt_size_to_cpu(cell[1]);
-       debug("%s: size=%zx\n", __func__, *size);
        return 0;
 }
 
@@ -680,6 +703,7 @@ int fdtdec_decode_region(const void *blob, int node,
 int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
                           struct fmap_entry *entry)
 {
+       const char *prop;
        u32 reg[2];
 
        if (fdtdec_get_int_array(blob, node, "reg", reg, 2)) {
@@ -688,6 +712,84 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name,
        }
        entry->offset = reg[0];
        entry->length = reg[1];
+       entry->used = fdtdec_get_int(blob, node, "used", entry->length);
+       prop = fdt_getprop(blob, node, "compress", NULL);
+       entry->compress_algo = prop && !strcmp(prop, "lzo") ?
+               FMAP_COMPRESS_LZO : FMAP_COMPRESS_NONE;
+       prop = fdt_getprop(blob, node, "hash", &entry->hash_size);
+       entry->hash_algo = prop ? FMAP_HASH_SHA256 : FMAP_HASH_NONE;
+       entry->hash = (uint8_t *)prop;
+
+       return 0;
+}
+
+static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
+{
+       u64 number = 0;
+
+       while (cells--)
+               number = (number << 32) | fdt32_to_cpu(*ptr++);
+
+       return number;
+}
+
+int fdt_get_resource(const void *fdt, int node, const char *property,
+                    unsigned int index, struct fdt_resource *res)
+{
+       const fdt32_t *ptr, *end;
+       int na, ns, len, parent;
+       unsigned int i = 0;
+
+       parent = fdt_parent_offset(fdt, node);
+       if (parent < 0)
+               return parent;
+
+       na = fdt_address_cells(fdt, parent);
+       ns = fdt_size_cells(fdt, parent);
+
+       ptr = fdt_getprop(fdt, node, property, &len);
+       if (!ptr)
+               return len;
+
+       end = ptr + len / sizeof(*ptr);
+
+       while (ptr + na + ns <= end) {
+               if (i == index) {
+                       res->start = res->end = fdtdec_get_number(ptr, na);
+                       res->end += fdtdec_get_number(&ptr[na], ns) - 1;
+                       return 0;
+               }
+
+               ptr += na + ns;
+               i++;
+       }
+
+       return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_get_named_resource(const void *fdt, int node, const char *property,
+                          const char *prop_names, const char *name,
+                          struct fdt_resource *res)
+{
+       int index;
+
+       index = fdt_find_string(fdt, node, prop_names, name);
+       if (index < 0)
+               return index;
+
+       return fdt_get_resource(fdt, node, property, index, res);
+}
+
+int fdtdec_pci_get_bdf(const void *fdt, int node, int *bdf)
+{
+       const fdt32_t *prop;
+       int len;
+
+       prop = fdt_getprop(fdt, node, "reg", &len);
+       if (!prop)
+               return len;
+
+       *bdf = fdt32_to_cpu(*prop) & 0xffffff;
 
        return 0;
 }