Merge patch series "U-boot: arm: Refine the booting on Total Compute"

Leo Yan <leo.yan@arm.com> says:

This patch series is to refine the booting on Arm Total Compuate
platform.

It changes to use the info passed in DTB for initialization DRAM info,
and dynamically initializes the booting envoironment variables.

Another big change is to use an envoironment file for boot commands,
based on it, the series extends to support multiple block devices
(MMC and virtio). And the env file is extended for booting Debian.

The last commit is to update memory mapping info based on the DRAM info
passed via DT binding.

Link: https://lore.kernel.org/r/20241025171821.624702-1-leo.yan@arm.com
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 787f983..7282c41 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1398,6 +1398,8 @@
 	select DM_SERIAL
 	select DM_MMC
 	select DM_GPIO
+	imply OF_HAS_PRIOR_STAGE
+	imply MISC_INIT_R
 
 config TARGET_LS2080A_EMU
 	bool "Support ls2080a_emu"
diff --git a/board/armltd/total_compute/Makefile b/board/armltd/total_compute/Makefile
index 8b10458..f1ef5a0 100644
--- a/board/armltd/total_compute/Makefile
+++ b/board/armltd/total_compute/Makefile
@@ -4,3 +4,4 @@
 # Usama Arif <usama.arif@arm.com>
 
 obj-y	:= total_compute.o
+obj-y	+= lowlevel_init.o
diff --git a/board/armltd/total_compute/lowlevel_init.S b/board/armltd/total_compute/lowlevel_init.S
new file mode 100644
index 0000000..3c06937
--- /dev/null
+++ b/board/armltd/total_compute/lowlevel_init.S
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2024 Arm Limited
+ */
+
+.global save_boot_params
+save_boot_params:
+	/* The firmware provided FDT address via x1 */
+	adr	x8, fw_dtb_pointer
+	str	x1, [x8]
+
+	b	save_boot_params_ret
diff --git a/board/armltd/total_compute/total_compute.c b/board/armltd/total_compute/total_compute.c
index e1b4f49..1336d2e 100644
--- a/board/armltd/total_compute/total_compute.c
+++ b/board/armltd/total_compute/total_compute.c
@@ -7,21 +7,18 @@
 #include <config.h>
 #include <dm.h>
 #include <dm/platform_data/serial_pl01x.h>
+#include <cpu_func.h>
+#include <env.h>
+#include <linux/sizes.h>
+
 #include <asm/armv8/mmu.h>
 #include <asm/global_data.h>
-
-static const struct pl01x_serial_plat serial_plat = {
-	.base = UART0_BASE,
-	.type = TYPE_PL011,
-	.clock = CFG_PL011_CLOCK,
-};
+#include <asm/system.h>
 
-U_BOOT_DRVINFO(total_compute_serials) = {
-	.name = "serial_pl01x",
-	.plat = &serial_plat,
-};
+/* +1 is end of list which needs to be empty */
+#define TC_MEM_MAP_MAX		(1 + CONFIG_NR_DRAM_BANKS + 1)
 
-static struct mm_region total_compute_mem_map[] = {
+static struct mm_region total_compute_mem_map[TC_MEM_MAP_MAX] = {
 	{
 		.virt = 0x0UL,
 		.phys = 0x0UL,
@@ -29,20 +26,49 @@
 		.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 			 PTE_BLOCK_NON_SHARE |
 			 PTE_BLOCK_PXN | PTE_BLOCK_UXN
-	}, {
-		.virt = 0x80000000UL,
-		.phys = 0x80000000UL,
-		.size = 0xff80000000UL,
-		.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
-			 PTE_BLOCK_INNER_SHARE
-	}, {
-		/* List terminator */
-		0,
 	}
 };
 
 struct mm_region *mem_map = total_compute_mem_map;
 
+/*
+ * Push the variable into the .data section so that it
+ * does not get cleared later.
+ */
+unsigned long __section(".data") fw_dtb_pointer;
+
+void *board_fdt_blob_setup(int *err)
+{
+	*err = 0;
+	if (fdt_magic(fw_dtb_pointer) != FDT_MAGIC) {
+		*err = -ENXIO;
+		return NULL;
+	}
+
+	return (void *)fw_dtb_pointer;
+}
+
+int misc_init_r(void)
+{
+	size_t base;
+
+	if (!env_get("fdt_addr_r"))
+		env_set_hex("fdt_addr_r", fw_dtb_pointer);
+
+	if (!env_get("kernel_addr_r")) {
+		/*
+		 * The kernel has to be 2M aligned and the first 64K at the
+		 * start of SDRAM is reserved for DTB.
+		 */
+		base = gd->ram_base + SZ_2M;
+		assert(IS_ALIGNED(base, SZ_2M));
+
+		env_set_hex("kernel_addr_r", base);
+	}
+
+	return 0;
+}
+
 int board_init(void)
 {
 	return 0;
@@ -50,19 +76,42 @@
 
 int dram_init(void)
 {
-	gd->ram_size = PHYS_SDRAM_1_SIZE;
-	return 0;
+	return fdtdec_setup_mem_size_base();
 }
 
 int dram_init_banksize(void)
 {
-	gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-	gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
+	return fdtdec_setup_memory_banksize();
+}
 
-	gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
-	gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE;
+void build_mem_map(void)
+{
+	int i;
 
-	return 0;
+	for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+		/*
+		 * The first node is for I/O device, start from node 1 for
+		 * updating DRAM info.
+		 */
+		mem_map[i + 1].virt = gd->bd->bi_dram[i].start;
+		mem_map[i + 1].phys = gd->bd->bi_dram[i].start;
+		mem_map[i + 1].size = gd->bd->bi_dram[i].size;
+		mem_map[i + 1].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+				       PTE_BLOCK_INNER_SHARE;
+	}
+}
+
+void enable_caches(void)
+{
+	build_mem_map();
+
+	icache_enable();
+	dcache_enable();
+}
+
+u64 get_page_table_size(void)
+{
+	return SZ_256K;
 }
 
 /* Nothing to be done here as handled by PSCI interface */
diff --git a/board/armltd/total_compute/total_compute.env b/board/armltd/total_compute/total_compute.env
new file mode 100644
index 0000000..7924632
--- /dev/null
+++ b/board/armltd/total_compute/total_compute.env
@@ -0,0 +1,39 @@
+/* DRAM1 + 0x2000_0000 */
+load_addr=0xa0000000
+/* DRAM1 + 0x0800_0000 */
+initrd_addr_r=0x88000000
+
+bootcmd=
+    virtio scan;
+    if virtio info; then
+        blk_dev=virtio;
+    else;
+        blk_dev=mmc;
+    fi;
+    echo block device is ${blk_dev};
+    if part number ${blk_dev} 0 vbmeta is_avb; then
+        echo '${blk_dev} with vbmeta partition detected.';
+        echo 'Starting Android Verified boot...';
+        avb init ${blk_dev} 0;
+        if avb verify; then
+            set bootargs $bootargs $avb_bootargs;
+            part start ${blk_dev} 0 boot boot_start;
+            part size ${blk_dev} 0 boot boot_size;
+            ${blk_dev} read ${load_addr} ${boot_start} ${boot_size};
+            bootm ${load_addr} ${load_addr} ${fdt_addr_r};
+        else;
+            echo 'AVB verification failed.';
+            exit;
+        fi;
+    elif part number ${blk_dev} 0 system is_non_avb_android; then
+        echo 'Booting Android non-AVB...';
+        booti ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r};
+    elif iminfo ${load_addr}; then
+        echo 'Booting FIT image...';
+        bootm ${load_addr} ${load_addr} ${fdt_addr_r};
+    else;
+        echo 'Booting Debian...';
+        set bootargs $bootargs root=/dev/mmcblk0p1 rw;
+        booti ${kernel_addr_r} - ${fdt_addr_r};
+    fi;
+    echo 'ERROR: No valid image to boot the system. Aborting boot sequence.';
diff --git a/configs/total_compute_defconfig b/configs/total_compute_defconfig
index b3d2e5c..e0d6199 100644
--- a/configs/total_compute_defconfig
+++ b/configs/total_compute_defconfig
@@ -18,7 +18,6 @@
 CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_DISTRO_DEFAULTS=y
 CONFIG_BOOTDELAY=5
-CONFIG_BOOTCOMMAND="if part number mmc 0 vbmeta is_avb; then  echo MMC with vbmeta partition detected.;  echo starting Android Verified boot.;  avb init 0;   if avb verify; then     set bootargs $bootargs $avb_bootargs;     part start mmc 0 boot boot_start;     part size mmc 0 boot boot_size;     mmc read ${load_addr} ${boot_start} ${boot_size};     bootm ${load_addr} ${load_addr} ${fdt_addr_r};   else;     echo AVB verification failed.;     exit;   fi; elif part number mmc 0 system is_non_avb_android; then   booti ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r};else;  echo Booting FIT image.;  bootm ${load_addr} ${load_addr} ${fdt_addr_r}; fi;"
 CONFIG_SYS_CBSIZE=512
 CONFIG_SYS_PBSIZE=544
 # CONFIG_DISPLAY_CPUINFO is not set
@@ -60,3 +59,4 @@
 CONFIG_SYS_MAX_FLASH_SECT=256
 # CONFIG_RANDOM_UUID is not set
 CONFIG_LIBAVB=y
+CONFIG_ENV_SOURCE_FILE=total_compute
diff --git a/include/configs/total_compute.h b/include/configs/total_compute.h
index a8bd8e2..5cc0166 100644
--- a/include/configs/total_compute.h
+++ b/include/configs/total_compute.h
@@ -11,37 +11,6 @@
 
 /* Link Definitions */
 
-/* AP non-secure UART base address */
-#define UART0_BASE		0x2A400000
-
-/* PL011 Serial Configuration */
-#define CFG_PL011_CLOCK	7372800
-
-/* Miscellaneous configurable options */
-
-/* Physical Memory Map */
-#define PHYS_SDRAM_1		0x80000000
-/* Top 48MB reserved for secure world use */
-#define DRAM_SEC_SIZE		0x03000000
-#define PHYS_SDRAM_1_SIZE	0x80000000 - DRAM_SEC_SIZE
-#define CFG_SYS_SDRAM_BASE	PHYS_SDRAM_1
-
-#define PHYS_SDRAM_2		0x8080000000
-#define PHYS_SDRAM_2_SIZE	0x180000000
-
-#define CFG_EXTRA_ENV_SETTINGS	\
-				"bootm_size=0x20000000\0"	\
-				"load_addr=0xa0000000\0"	\
-				"kernel_addr_r=0x80080000\0"	\
-				"initrd_addr_r=0x88000000\0"	\
-				"fdt_addr_r=0x83000000\0"
-/*
- * If vbmeta partition is present, boot Android with verification using AVB.
- * Else if system partition is present (no vbmeta partition), boot Android
- * without verification (for development purposes).
- * Else boot FIT image.
- */
-
 #define CFG_SYS_FLASH_BASE		0x0C000000
 
 #endif /* __TOTAL_COMPUTE_H */