[PATCH v2 08/16] lib: fdt: Add fdtdec_setup_mem_size_base_highest

Sean Anderson seanga2 at gmail.com
Mon Oct 12 20:13:37 CEST 2020


This is very similar to fdtdec_setup_mem_size_base_lowest, except we pick
the highest ram bank, instead of the lowest. This is helpful for boards
which use separate but contiguous ram banks, as it leaves the most space
for loading programs.

Signed-off-by: Sean Anderson <seanga2 at gmail.com>
Reviewed-by: Simon Glass <sjg at chromium.org>
---

(no changes since v1)

 include/fdtdec.h | 19 ++++++++++++++++++-
 lib/fdtdec.c     | 34 +++++++++++++++++++++++++++++-----
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index 62d1660973..6a8e235674 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -944,7 +944,7 @@ int fdtdec_setup_mem_size_base(void);
  * 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.
+ * 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
@@ -956,6 +956,23 @@ int fdtdec_setup_mem_size_base(void);
  */
 int fdtdec_setup_mem_size_base_lowest(void);
 
+/**
+ * fdtdec_setup_mem_size_base_highest() - decode and setup gd->ram_size and
+ * gd->ram_start by highest available memory top
+ *
+ * Decode the /memory 'reg' property to determine the highest end of the memory
+ * 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_highest(void);
+
 /**
  * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram
  *
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index ee1bd41b08..78b34bf4da 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1123,7 +1123,7 @@ int fdtdec_setup_memory_banksize(void)
 	return 0;
 }
 
-int fdtdec_setup_mem_size_base_lowest(void)
+static int fdtdec_setup_mem_size_base_superlative(bool lowest)
 {
 	int bank, ret, reg = 0;
 	struct resource res;
@@ -1131,7 +1131,16 @@ int fdtdec_setup_mem_size_base_lowest(void)
 	phys_size_t size;
 	ofnode mem = ofnode_null();
 
-	gd->ram_base = (unsigned long)~0;
+	/*
+	 * Size must be 1 so we don't underflow when doing the subtraction below
+	 * when lowest = false. Hopefully any real ram banks will have a greater
+	 * size :)
+	 */
+	gd->ram_size = 1;
+	if (lowest)
+		gd->ram_base = (unsigned long)~0;
+	else
+		gd->ram_base = 0;
 
 	mem = get_next_memory_node(mem);
 	if (!ofnode_valid(mem)) {
@@ -1158,17 +1167,32 @@ int fdtdec_setup_mem_size_base_lowest(void)
 		base = (unsigned long)res.start;
 		size = (phys_size_t)(res.end - res.start + 1);
 
-		if (gd->ram_base > base && size) {
+		if (!size)
+			continue;
+
+		if ((lowest && gd->ram_base > base) ||
+		    (!lowest && gd->ram_base + gd->ram_size - 1 < res.end)) {
 			gd->ram_base = base;
 			gd->ram_size = size;
-			debug("%s: Initial DRAM base %lx size %lx\n",
-			      __func__, base, (unsigned long)size);
 		}
 	}
 
+	if (gd->ram_size)
+		debug("%s: Initial DRAM base %lx size %lx\n", __func__,
+		      gd->ram_base, (unsigned long)gd->ram_size);
 	return 0;
 }
 
+int fdtdec_setup_mem_size_base_lowest(void)
+{
+	return fdtdec_setup_mem_size_base_superlative(true);
+}
+
+int fdtdec_setup_mem_size_base_highest(void)
+{
+	return fdtdec_setup_mem_size_base_superlative(false);
+}
+
 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\
 	CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO)
-- 
2.28.0



More information about the U-Boot mailing list