The TF-A DRAM bank setup currently assumes that the number of
banks reported by TF-A matches the number of entries available in
gd->bd->bi_dram[].  Limit the loop by CONFIG_NR_DRAM_BANKS so that
a platform with fewer configured DRAM banks does not write past the
array.

The reserved RAM setup also checks higher DRAM banks before falling
back to bank 0.  When a higher bank is empty and board_reserve_ram_top()
returns 0, the old test succeeds for a zero-sized bank.  This can set
gd->arch.resv_ram to 0.

On systems with CONFIG_GIC_V3_ITS this value is later used by
ls_gic_rd_tables_init() to place the GIC LPI tables:

  gd->arch.resv_ram - GIC_LPI_SIZE

If gd->arch.resv_ram is 0, the subtraction underflows and the GIC LPI
tables are placed at an invalid high address.

Skip empty banks when selecting the reserved RAM area and fail GIC LPI
table setup if no reserved RAM address was established.

This fixes LS1028A systems with 2 GiB of RAM, where TF-A reports only
one populated DRAM bank.

Tested on an LS1028ARDB with TF-A modified to report 2 GiB of RAM, and
on a custom LS1028A-based board equipped with 2 GiB of RAM.

Signed-off-by: Patryk Biel <[email protected]>
---
 arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 33 ++++++++++++++++++++++-----------
 arch/arm/cpu/armv8/fsl-layerscape/soc.c |  5 +++++
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c 
b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
index 
a047494b1fd1adcc015a34520d6e2d7f8fe34334..497bf11b8983b208680a028a23677573f9d1edfd
 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
@@ -1381,32 +1381,43 @@ static int tfa_dram_init_banksize(void)
                dram_size -= gd->bd->bi_dram[i].size;
 
                i++;
-       } while (dram_size);
+       } while (dram_size && i < CONFIG_NR_DRAM_BANKS);
+
+       if (dram_size)
+               printf("Warning: CONFIG_NR_DRAM_BANKS is too small, %llx bytes 
left unassigned\n",
+                      dram_size);
 
        if (i > 0)
                ret = 0;
 
 #if defined(CONFIG_RESV_RAM) && !defined(CONFIG_XPL_BUILD)
        /* Assign memory for MC */
-#ifdef CONFIG_SYS_DDR_BLOCK3_BASE
-       if (gd->bd->bi_dram[2].size >=
+#if defined(CONFIG_SYS_DDR_BLOCK3_BASE) && (CONFIG_NR_DRAM_BANKS >= 3)
+       if (gd->bd->bi_dram[2].size &&
+           gd->bd->bi_dram[2].size >=
            board_reserve_ram_top(gd->bd->bi_dram[2].size)) {
                gd->arch.resv_ram = gd->bd->bi_dram[2].start +
-                           gd->bd->bi_dram[2].size -
-                           board_reserve_ram_top(gd->bd->bi_dram[2].size);
+                       gd->bd->bi_dram[2].size -
+                       board_reserve_ram_top(gd->bd->bi_dram[2].size);
        } else
 #endif
        {
-               if (gd->bd->bi_dram[1].size >=
+#if defined(CFG_SYS_DDR_BLOCK2_BASE) && (CONFIG_NR_DRAM_BANKS >= 2)
+               if (gd->bd->bi_dram[1].size &&
+                   gd->bd->bi_dram[1].size >=
                    board_reserve_ram_top(gd->bd->bi_dram[1].size)) {
                        gd->arch.resv_ram = gd->bd->bi_dram[1].start +
                                gd->bd->bi_dram[1].size -
                                board_reserve_ram_top(gd->bd->bi_dram[1].size);
-               } else if (gd->bd->bi_dram[0].size >
-                          board_reserve_ram_top(gd->bd->bi_dram[0].size)) {
-                       gd->arch.resv_ram = gd->bd->bi_dram[0].start +
-                               gd->bd->bi_dram[0].size -
-                               board_reserve_ram_top(gd->bd->bi_dram[0].size);
+               } else
+#endif
+               {
+                       if (gd->bd->bi_dram[0].size >
+                           board_reserve_ram_top(gd->bd->bi_dram[0].size)) {
+                               gd->arch.resv_ram = gd->bd->bi_dram[0].start +
+                                       gd->bd->bi_dram[0].size -
+                                       
board_reserve_ram_top(gd->bd->bi_dram[0].size);
+                       }
                }
        }
 #endif /* CONFIG_RESV_RAM */
diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c 
b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
index 
d85a630f8a3cb722034b131b94529688af4f55fc..24ccb8bb0c4ce737559254ca84dcf0e8bdba3e64
 100644
--- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c
+++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c
@@ -65,6 +65,11 @@ int ls_gic_rd_tables_init(void *blob)
        u64 gic_lpi_base;
        int ret;
 
+       if (!gd->arch.resv_ram) {
+               debug("%s: failed to reserve memory for gic-lpi-tables\n", 
__func__);
+               return -ENOMEM;
+       }
+
        gic_lpi_base = ALIGN(gd->arch.resv_ram - GIC_LPI_SIZE, SZ_64K);
        ret = fdt_add_resv_mem_gic_rd_tables(blob, gic_lpi_base, GIC_LPI_SIZE);
        if (ret)

---
base-commit: f605dcee103c897b6f1a8873549a36949bd4e2a1
change-id: 20260713-up-fix-ddr-80af76ffe140

Best regards,
-- 
Patryk Biel <[email protected]>

Reply via email to