Identify the boot media loader driver and load the FIT image that has the
binaries to initialize the DDR, U-Boot proper etc.

Reviewed-by: Balaji Selvanathan <[email protected]>
Reviewed-by: Simon Glass <[email protected]>
Signed-off-by: Varadarajan Narayanan <[email protected]>
---
 arch/arm/mach-snapdragon/board_spl.c | 155 ++++++++++++++++++++++++++++++++++-
 1 file changed, 153 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-snapdragon/board_spl.c 
b/arch/arm/mach-snapdragon/board_spl.c
index 2445ae8b17d..2655803b31e 100644
--- a/arch/arm/mach-snapdragon/board_spl.c
+++ b/arch/arm/mach-snapdragon/board_spl.c
@@ -5,12 +5,15 @@
  * Copyright (c) 2026 Michael Srba <[email protected]>
  */
 
+#include <asm/sections.h>
 #include <hang.h>
+#include <init.h>
+#include <mach/qclib.h>
 #include <spl.h>
 #include <soc/qcom/smem.h>
 
 /* in SPL, we always use internal DT */
-int board_fdt_blob_setup(void **fdtp)
+int __weak board_fdt_blob_setup(void **fdtp)
 {
        return -EEXIST;
 }
@@ -86,7 +89,7 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 boot_device)
  *
  * Return: Partition number to boot from, or default partition on error
  */
-int spl_mmc_boot_partition(const u32 boot_device)
+int __weak spl_mmc_boot_partition(const u32 boot_device)
 {
        int p_no;
        struct blk_desc *desc;
@@ -120,3 +123,151 @@ unsigned long spl_mmc_get_uboot_raw_sector(struct mmc 
*mmc, ulong raw_sect)
        return 0;
 }
 #endif /* CONFIG_IS_ENABLED(MMC) */
+
+void qcom_spl_malloc_init_f(void)
+{
+       if (!CONFIG_IS_ENABLED(SYS_MALLOC_F))
+               return;
+       /*
+        * Set up by crt0.S
+        */
+       assert(gd->malloc_base);
+       gd->malloc_limit = CONFIG_VAL(SYS_MALLOC_F_LEN);
+       gd->malloc_ptr = 0;
+
+       mem_malloc_init(gd->malloc_base, gd->malloc_limit);
+       gd->flags |= GD_FLG_FULL_MALLOC_INIT;
+}
+
+/**
+ * spl_get_load_buffer() - Allocate a cache-aligned buffer for image loading.
+ * @offset:    Offset (unused, typically 0 for SPL).
+ * @size:      Size of the buffer to allocate.
+ *
+ * Return: Pointer to the allocated buffer, or NULL on failure.
+ */
+struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size)
+{
+#ifdef CONFIG_SPL_LOAD_FIT_ADDRESS
+       return (void *)CONFIG_SPL_LOAD_FIT_ADDRESS;
+#else
+       return NULL;
+#endif
+}
+
+/**
+ * board_spl_fit_buffer_addr() - Get the address of the FIT image buffer.
+ * @fit_size:  Size of the FIT image.
+ * @sectors:   Number of sectors.
+ * @bl_len:    Block length.
+ *
+ * Return: Address of the FIT image buffer.
+ */
+void *board_spl_fit_buffer_addr(ulong fit_size, int sectors, int bl_len)
+{
+       return spl_get_load_buffer(0, sectors * bl_len);
+}
+
+/**
+ * qcom_spl_loader_pre_ddr() - SPL loader for pre-DDR stage.
+ * @boot_device: Type of boot device.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+int qcom_spl_loader_pre_ddr(u8 boot_device)
+{
+       struct spl_image_loader *loader, *drv;
+       struct spl_image_info spl_image = { 0 };
+       struct spl_boot_device boot_dev = { .boot_device = boot_device, };
+       int ret = -ENODEV, n_ents;
+
+       drv = ll_entry_start(struct spl_image_loader, spl_image_loader);
+       n_ents = ll_entry_count(struct spl_image_loader, spl_image_loader);
+
+       for (loader = drv; loader && (loader != drv + n_ents); loader++) {
+               if (boot_device != loader->boot_device)
+                       continue;
+
+               ret = loader->load_image(&spl_image, &boot_dev);
+               if (!ret)
+                       break;
+
+               printf("%s: Error: %d\n", __func__, ret);
+       }
+
+       return ret;
+}
+
+/**
+ * board_fit_config_name_match() - Select the FIT config for the current
+ *                                boot stage.
+ * @name:      Candidate FIT config name.
+ *
+ * Generic default: match "pre-ddr" before DRAM is up, "post-ddr" after.
+ * A SoC with additional/different FIT configs should provide a strong
+ * override.
+ *
+ * Return: 0 on match, -EINVAL otherwise.
+ */
+int __weak board_fit_config_name_match(const char *name)
+{
+       if (!(gd->flags & GD_FLG_SPL_INIT)) {
+               if (!strcmp(name, "pre-ddr")) {
+                       printf("Selected FIT Config: %s\n", name);
+                       return 0;
+               }
+       } else {
+               if (!strcmp(name, "post-ddr")) {
+                       printf("Selected FIT Config: %s\n", name);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+/**
+ * board_init_f() - Generic SPL entry point.
+ * @dummy:     Unused.
+ *
+ * Generic default: clear BSS, set up malloc, run early init, load the
+ * pre-DDR image and invoke QCLIB when booting from PBL, then hand off to
+ * board_init_r(). A SoC with additional bring-up steps should provide a
+ * strong override.
+ */
+void __weak board_init_f(ulong dummy)
+{
+       int ret = 0;
+
+       memset(__bss_start, 0, __bss_end - __bss_start); /* Clear BSS */
+
+       qcom_spl_malloc_init_f();
+
+       ret = spl_early_init();
+       if (ret) {
+               pr_debug("spl_early_init() failed (%d)\n", ret);
+               goto fail;
+       }
+
+       event_notify_null(EVT_LAST_STAGE_INIT);
+
+       preloader_console_init();
+
+       ret = qcom_spl_loader_pre_ddr(spl_boot_device());
+       if (ret) {
+               pr_debug("qcom_spl_loader_pre_ddr() failed (%d)\n", ret);
+               goto fail;
+       }
+
+       ret = qcom_spl_invoke_qclib();
+       if (ret) {
+               pr_debug("qcom_spl_invoke_qclib() failed (%d)\n", ret);
+               goto fail;
+       }
+
+       board_init_r(NULL, 0);
+
+fail:
+       if (ret)
+               reset_cpu();
+}

-- 
2.34.1

Reply via email to