summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2020-07-09 14:09:52 +0200
committerMichal Simek <michal.simek@xilinx.com>2020-08-20 09:49:20 +0200
commit7fce7396659c162f55b1747d84599d822b11c6a7 (patch)
tree716392f8de1c2b51602f47b5d53e4bae12a086ea /lib
parent11b1dcec09f035e3b70a2fc63913ab00991ecba7 (diff)
lib: fdt: Introduce fdtdec_setup_mem_size_base_lowest()
New function should be called from board dram_init() because it initialized gd->ram_base/ram_size. It finds the lowest available memory. On systems with multiple memory nodes finding out the first memory node by fdtdec_setup_mem_size_base() is not enough because this memory can be above actual U-Boot VA mapping. Currently only mapping till 39bit is supported (Full 44bit mapping was removed by commit 7985cdf74b28 ("arm64: Remove non-full-va map code")). If DT starts with the first memory node above 39bit address then system can be unpredictable. The function is available only when multiple memory bank support is enabled. Calling fdtdec_setup_memory_banksize() from dram_init() is not possible because fdtdec_setup_memory_banksize() is saving dram information to bd structure which is placed on stack but not initialized at this time. Also stack is placed at location setup in dram_init(). Signed-off-by: Michal Simek <michal.simek@xilinx.com> Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/fdtdec.c45
1 files changed, 45 insertions, 0 deletions
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)