[PATCH v4 2/2] mach-k3: add dynamic mmu fixups for SPL stage

Anshul Dalal anshuld at ti.com
Wed Jun 18 14:42:09 CEST 2025


On platforms with spl splash support i.e CONFIG_VIDEO=y, the top of DDR
is reserved for the framebuffer.

The size for the framebuffer is computed at runtime by video_reserve.
During the MMU configuration an entry corresponding to the framebuffer
should be dynamically created to properly map the required space for the
framebuffer.

Therefore this patch adds k3_spl_mem_map_init which adds the required
MMU entry by querying the gd after the framebuffer size has been
computed in spl_reserve_video_from_ram_top.

For non VIDEO=y platforms, the added k3_spl_mem_map_init function gets
optimized out of the final binary so overall, the spl size is not
impacted[1].

[1]: Tested on clang 19.1.7 and gcc 15.1.1

Signed-off-by: Anshul Dalal <anshuld at ti.com>
---
 arch/arm/mach-k3/arm64/arm64-mmu.c     | 44 ++++++++++++++++++++++++++
 arch/arm/mach-k3/common.c              | 13 ++++++--
 arch/arm/mach-k3/include/mach/k3-ddr.h |  3 ++
 3 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-k3/arm64/arm64-mmu.c b/arch/arm/mach-k3/arm64/arm64-mmu.c
index 135f842556d..0d9b4d062bf 100644
--- a/arch/arm/mach-k3/arm64/arm64-mmu.c
+++ b/arch/arm/mach-k3/arm64/arm64-mmu.c
@@ -49,6 +49,10 @@ struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
 		.size = SZ_128M,
 		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 			 PTE_BLOCK_INNER_SHARE
+	}, {
+		/* Framebuffer reserved, size set at runtime */
+		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+			 PTE_BLOCK_INNER_SHARE
 	}, {
 		/* List terminator */
 		0,
@@ -57,6 +61,46 @@ struct mm_region k3_mem_map[K3_MMU_REGIONS_COUNT] = {
 
 struct mm_region *mem_map = k3_mem_map;
 
+int k3_spl_mem_map_init(void)
+{
+	unsigned int i;
+	int k3_map_idx = -EINVAL;
+
+	for (i = 0; i < K3_MMU_REGIONS_COUNT; i++) {
+		if (k3_mem_map[i].virt == 0 && k3_mem_map[i].phys == 0 &&
+		    k3_mem_map[i].size == 0) {
+			k3_map_idx = i;
+			break;
+		}
+	}
+
+	if (k3_map_idx == -EINVAL) {
+		pr_err("%s: Failed to find fixup region in MMU memory map\n",
+		       __func__);
+		return -EINVAL;
+	}
+
+	if (k3_map_idx >= K3_MMU_REGIONS_COUNT - 1) {
+		pr_err("%s: Not enough space in MMU map for the added entry\n",
+		       __func__);
+		return -ENOMEM;
+	}
+
+	if (CONFIG_IS_ENABLED(VIDEO)) {
+		k3_mem_map[k3_map_idx].virt = gd_video_bottom();
+		k3_mem_map[k3_map_idx].phys = gd_video_bottom();
+		k3_mem_map[k3_map_idx].size =
+			gd_video_top() - gd_video_bottom();
+		k3_mem_map[k3_map_idx].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+					       PTE_BLOCK_INNER_SHARE;
+		k3_map_idx++;
+	}
+
+	k3_mem_map[k3_map_idx] = (const struct mm_region){ 0 };
+
+	return 0;
+}
+
 static int dt_reserved_cmp(const void *a, const void *b)
 {
 	const struct fdt_resource *val_a = a, *val_b = b;
diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c
index fc230f180d0..198ab4e85fe 100644
--- a/arch/arm/mach-k3/common.c
+++ b/arch/arm/mach-k3/common.c
@@ -15,6 +15,7 @@
 #include <asm/global_data.h>
 #include <linux/printk.h>
 #include "common.h"
+#include "mach/k3-ddr.h"
 #include <dm.h>
 #include <remoteproc.h>
 #include <asm/cache.h>
@@ -224,9 +225,6 @@ void spl_enable_cache(void)
 
 	dram_init();
 
-	/* reserve TLB table */
-	gd->arch.tlb_size = PGTABLE_SIZE;
-
 	gd->ram_top += get_effective_memsize();
 	gd->relocaddr = gd->ram_top;
 
@@ -234,6 +232,15 @@ void spl_enable_cache(void)
 	if (ret)
 		panic("Failed to reserve framebuffer memory (%d)\n", ret);
 
+	if (IS_ENABLED(CONFIG_ARM64)) {
+		ret = k3_spl_mem_map_init();
+		if (ret)
+			panic("Failed to perform MMU fixups: %d\n", ret);
+	}
+
+	/* reserve TLB table */
+	gd->arch.tlb_size = PGTABLE_SIZE;
+
 	gd->arch.tlb_addr = gd->relocaddr - gd->arch.tlb_size;
 	gd->arch.tlb_addr &= ~(0x10000 - 1);
 	debug("TLB table from %08lx to %08lx\n", gd->arch.tlb_addr,
diff --git a/arch/arm/mach-k3/include/mach/k3-ddr.h b/arch/arm/mach-k3/include/mach/k3-ddr.h
index 0b164ebf5e6..375a1a85945 100644
--- a/arch/arm/mach-k3/include/mach/k3-ddr.h
+++ b/arch/arm/mach-k3/include/mach/k3-ddr.h
@@ -17,6 +17,9 @@ int dram_init_banksize(void);
 void fixup_ddr_driver_for_ecc(struct spl_image_info *spl_image);
 void fixup_memory_node(struct spl_image_info *spl_image);
 
+/* Performs MMU memory map fixups at SPL stage */
+int k3_spl_mem_map_init(void);
+
 /*
  * Modifies the MMU memory map based on DDR size and reserved-memory
  * nodes in DT
-- 
2.49.0



More information about the U-Boot mailing list