From patchwork Fri Jul 10 12:40:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 241306 List-Id: U-Boot discussion From: michal.simek at xilinx.com (Michal Simek) Date: Fri, 10 Jul 2020 14:40:55 +0200 Subject: [PATCH v2 1/3] lib: fdt: Introduce fdtdec_setup_mem_size_base_lowest() In-Reply-To: References: Message-ID: 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 Reviewed-by: Simon Glass --- Changes in v2: - Separate Xilinx change from generic patch include/fdtdec.h | 17 +++++++++++++++++ lib/fdtdec.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/include/fdtdec.h b/include/fdtdec.h index 760b392bdfbc..bc79389260ab 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -926,6 +926,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 * diff --git a/lib/fdtdec.c b/lib/fdtdec.c index fa523ce2e908..a10120baa895 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) From patchwork Fri Jul 10 12:40:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 241307 List-Id: U-Boot discussion From: michal.simek at xilinx.com (Michal Simek) Date: Fri, 10 Jul 2020 14:40:56 +0200 Subject: [PATCH v2 2/3] lib: fdt: Convert fdtdes_setup_mem..() to livetree API In-Reply-To: References: Message-ID: Convert fdtdec_setup_mem_size_base(), get_next_memory_node(), fdtdec_setup_memory_banksize() and fdtdec_setup_mem_size_base_lowest() to livetree API. Tested on ZynqMP zcu104 board. Signed-off-by: Michal Simek Reviewed-by: Simon Glass --- Changes in v2: - new patch asked by Simon lib/fdtdec.c | 67 +++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index a10120baa895..39d73006e131 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -24,6 +24,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -1032,16 +1033,17 @@ int fdtdec_decode_display_timing(const void *blob, int parent, int index, int fdtdec_setup_mem_size_base(void) { - int ret, mem; - struct fdt_resource res; + int ret; + ofnode mem; + struct resource res; - mem = fdt_path_offset(gd->fdt_blob, "/memory"); - if (mem < 0) { + mem = ofnode_path("/memory"); + if (!ofnode_valid(mem)) { debug("%s: Missing /memory node\n", __func__); return -EINVAL; } - ret = fdt_get_resource(gd->fdt_blob, mem, "reg", 0, &res); + ret = ofnode_read_resource(mem, 0, &res); if (ret != 0) { debug("%s: Unable to decode first memory bank\n", __func__); return -EINVAL; @@ -1057,42 +1059,42 @@ int fdtdec_setup_mem_size_base(void) #if defined(CONFIG_NR_DRAM_BANKS) -static int get_next_memory_node(const void *blob, int mem) +ofnode get_next_memory_node(ofnode mem) { do { - mem = fdt_node_offset_by_prop_value(gd->fdt_blob, mem, - "device_type", "memory", 7); - } while (!fdtdec_get_is_enabled(blob, mem)); + mem = ofnode_by_prop_value(mem, "device_type", "memory", 7); + } while (!ofnode_is_available(mem)); return mem; } int fdtdec_setup_memory_banksize(void) { - int bank, ret, mem, reg = 0; - struct fdt_resource res; + int bank, ret, reg = 0; + struct resource res; + ofnode mem = ofnode_null(); - mem = get_next_memory_node(gd->fdt_blob, -1); - if (mem < 0) { + mem = get_next_memory_node(mem); + if (!ofnode_valid(mem)) { debug("%s: Missing /memory node\n", __func__); return -EINVAL; } for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { - ret = fdt_get_resource(gd->fdt_blob, mem, "reg", reg++, &res); - if (ret == -FDT_ERR_NOTFOUND) { + ret = ofnode_read_resource(mem, reg++, &res); + if (ret < 0) { reg = 0; - mem = get_next_memory_node(gd->fdt_blob, mem); - if (mem == -FDT_ERR_NOTFOUND) + mem = get_next_memory_node(mem); + if (ofnode_valid(mem)) break; - ret = fdt_get_resource(gd->fdt_blob, mem, "reg", reg++, &res); - if (ret == -FDT_ERR_NOTFOUND) + ret = ofnode_read_resource(mem, reg++, &res); + if (ret < 0) break; } - if (ret != 0) { + + if (ret != 0) return -EINVAL; - } gd->bd->bi_dram[bank].start = (phys_addr_t)res.start; gd->bd->bi_dram[bank].size = @@ -1109,32 +1111,33 @@ int fdtdec_setup_memory_banksize(void) int fdtdec_setup_mem_size_base_lowest(void) { - int bank, ret, mem, reg = 0; - struct fdt_resource res; + int bank, ret, reg = 0; + struct resource res; unsigned long base; phys_size_t size; - const void *blob = gd->fdt_blob; + ofnode mem = ofnode_null(); gd->ram_base = (unsigned long)~0; - mem = get_next_memory_node(blob, -1); - if (mem < 0) { + mem = get_next_memory_node(mem); + if (!ofnode_valid(mem)) { 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) { + ret = ofnode_read_resource(mem, reg++, &res); + if (ret < 0) { reg = 0; - mem = get_next_memory_node(blob, mem); - if (mem == -FDT_ERR_NOTFOUND) + mem = get_next_memory_node(mem); + if (ofnode_valid(mem)) break; - ret = fdt_get_resource(blob, mem, "reg", reg++, &res); - if (ret == -FDT_ERR_NOTFOUND) + ret = ofnode_read_resource(mem, reg++, &res); + if (ret < 0) break; } + if (ret != 0) return -EINVAL; From patchwork Fri Jul 10 12:40:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michal Simek X-Patchwork-Id: 241308 List-Id: U-Boot discussion From: michal.simek at xilinx.com (Michal Simek) Date: Fri, 10 Jul 2020 14:40:57 +0200 Subject: [PATCH v2 3/3] xilinx: versal: Use lowest memory for U-Boot In-Reply-To: References: Message-ID: Find and use the lowest memory for Versal to make sure that we keep u-boot as low as possible and never use memory above u-boot's maximum VA mapping. Signed-off-by: Michal Simek --- Changes in v2: - split from generic patch sent in v1 board/xilinx/versal/board.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/xilinx/versal/board.c b/board/xilinx/versal/board.c index 45cf1d2d0cad..3dc7044b213e 100644 --- a/board/xilinx/versal/board.c +++ b/board/xilinx/versal/board.c @@ -229,7 +229,7 @@ int dram_init_banksize(void) int dram_init(void) { - if (fdtdec_setup_mem_size_base() != 0) + if (fdtdec_setup_mem_size_base_lowest() != 0) return -EINVAL; return 0;