diff options
-rw-r--r-- | include/fdtdec.h | 17 | ||||
-rw-r--r-- | lib/fdtdec.c | 45 |
2 files changed, 62 insertions, 0 deletions
diff --git a/include/fdtdec.h b/include/fdtdec.h index 760b392bdf..bc79389260 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -927,6 +927,23 @@ int fdtdec_decode_display_timing(const void *blob, int node, int index, int fdtdec_setup_mem_size_base(void); /** + * fdtdec_setup_mem_size_base_lowest() - decode and setup gd->ram_size and + * gd->ram_start by lowest available memory base + * + * Decode the /memory 'reg' property to determine the lowest start of the memory + * bank bank and populate the global data with it. + * + * This function should be called from a boards dram_init(). This helper + * function allows for boards to query the device tree for DRAM size and start + * address instead of hard coding the value in the case where the memory size + * and start address cannot be detected automatically. + * + * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or + * invalid + */ +int fdtdec_setup_mem_size_base_lowest(void); + +/** * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram * * Decode the /memory 'reg' property to determine the address and size of the diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 78576b530f..da94bc5e15 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1106,6 +1106,51 @@ int fdtdec_setup_memory_banksize(void) return 0; } + +int fdtdec_setup_mem_size_base_lowest(void) +{ + int bank, ret, mem, reg = 0; + struct fdt_resource res; + unsigned long base; + phys_size_t size; + const void *blob = gd->fdt_blob; + + gd->ram_base = (unsigned long)~0; + + mem = get_next_memory_node(blob, -1); + if (mem < 0) { + debug("%s: Missing /memory node\n", __func__); + return -EINVAL; + } + + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + ret = fdt_get_resource(blob, mem, "reg", reg++, &res); + if (ret == -FDT_ERR_NOTFOUND) { + reg = 0; + mem = get_next_memory_node(blob, mem); + if (mem == -FDT_ERR_NOTFOUND) + break; + + ret = fdt_get_resource(blob, mem, "reg", reg++, &res); + if (ret == -FDT_ERR_NOTFOUND) + break; + } + if (ret != 0) + return -EINVAL; + + base = (unsigned long)res.start; + size = (phys_size_t)(res.end - res.start + 1); + + if (gd->ram_base > base && size) { + gd->ram_base = base; + gd->ram_size = size; + debug("%s: Initial DRAM base %lx size %lx\n", + __func__, base, (unsigned long)size); + } + } + + return 0; +} #endif #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) |