Prepare QUP firmware support before serial-engine children
are probed during SPL initialization.

Enable QUP wrapper clocks before firmware detection.
Initialize the boot MMC before the last-stage init event.

This makes QUP firmware available from the boot medium.
Release the dynamic firmware buffer after children are
probed so SPL can reserve memory for the MMU page table.

Signed-off-by: Abhilash V <[email protected]>
---
 board/qualcomm/shikra/spl-shikra.c | 118 +++++++++++++++++++++++++++++
 1 file changed, 118 insertions(+)

diff --git a/board/qualcomm/shikra/spl-shikra.c 
b/board/qualcomm/shikra/spl-shikra.c
index 9bab677cce5..1a385877dd5 100644
--- a/board/qualcomm/shikra/spl-shikra.c
+++ b/board/qualcomm/shikra/spl-shikra.c
@@ -3,6 +3,7 @@
  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 #include <blk.h>
+#include <clk.h>
 #include <cpu_func.h>
 #include <asm/io.h>
 #include <asm/sections.h>
@@ -16,6 +17,7 @@
 #include <malloc.h>
 #include <mach/qclib.h>
 #include <mach/spl.h>
+#include <mmc.h>
 #include <part.h>
 #include <spl.h>
 
@@ -148,6 +150,109 @@ enum {
 };
 
 #if defined(CONFIG_SPL_BUILD)
+/**
+ * shikra_prepare_qup_clocks() - Enable QUP wrapper clocks.
+ *
+ * Enable wrapper clocks before detecting the QUP firmware state.
+ *
+ * Return: 0 on success, or a negative error code.
+ */
+static int shikra_prepare_qup_clocks(void)
+{
+       struct clk_bulk clks;
+       struct uclass *uc;
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get(UCLASS_MISC, &uc);
+       if (ret)
+               return ret;
+
+       uclass_foreach_dev(dev, uc) {
+               if (!device_is_compatible(dev, "qcom,geni-se-qup"))
+                       continue;
+
+               ret = clk_get_bulk(dev, &clks);
+               if (ret)
+                       return ret;
+
+               ret = clk_enable_bulk(&clks);
+               if (ret)
+                       clk_release_bulk(&clks);
+
+               return ret;
+       }
+
+       return -ENODEV;
+}
+
+/**
+ * shikra_prepare_boot_mmc() - Initialize the boot MMC device.
+ *
+ * Make the boot MMC device available before loading QUP firmware.
+ *
+ * Return: 0 on success, or a negative error code.
+ */
+static int shikra_prepare_boot_mmc(void)
+{
+       struct udevice *dev;
+       struct mmc *mmc;
+       u8 boot_device_cfg;
+       int seq, ret;
+
+       boot_device_cfg =
+               (readl(IPQ_SPL_BOOTCFG_REG_ADDR) & IPQ_SPL_BOOTCFG_DEV_MASK) >>
+               IPQ_SPL_BOOTCFG_DEV_SHFT;
+
+       switch (boot_device_cfg) {
+       case IPQ_SPL_BOOTCFG_DEV_MMC:
+               seq = 0;
+               break;
+       case IPQ_SPL_BOOTCFG_DEV_SD_EMMC:
+               seq = 1;
+               break;
+       default:
+               return 0;
+       }
+
+       ret = uclass_get_device_by_seq(UCLASS_MMC, seq, &dev);
+       if (ret)
+               return ret;
+
+       mmc = mmc_get_mmc_dev(dev);
+       if (!mmc)
+               return -ENODEV;
+
+       return mmc_init(mmc);
+}
+
+/**
+ * shikra_release_qupfw() - Free the QUP firmware buffer.
+ *
+ * Free the dynamic QUPFW buffer before allocating the MMU table.
+ */
+static void shikra_release_qupfw(void)
+{
+#if !IS_ENABLED(CONFIG_QCOM_GENI_MINICORE)
+       struct uclass *uc;
+       struct udevice *dev;
+       void *fw;
+
+       if (uclass_get(UCLASS_MISC, &uc))
+               return;
+
+       uclass_foreach_dev(dev, uc) {
+               if (!device_is_compatible(dev, "qcom,geni-se-qup"))
+                       continue;
+
+               fw = dev_get_priv(dev);
+               if (fw)
+                       free(fw);
+               return;
+       }
+#endif
+}
+
 void board_init_f(ulong dummy)
 {
        int ret = 0;
@@ -162,7 +267,20 @@ void board_init_f(ulong dummy)
                goto fail;
        }
 
+       ret = shikra_prepare_qup_clocks();
+       if (ret) {
+               pr_debug("failed to prepare QUP clocks (%d)\n", ret);
+               goto fail;
+       }
+
+       ret = shikra_prepare_boot_mmc();
+       if (ret) {
+               pr_debug("failed to prepare boot MMC (%d)\n", ret);
+               goto fail;
+       }
+
        event_notify_null(EVT_LAST_STAGE_INIT);
+       shikra_release_qupfw();
 
        preloader_console_init();
 
-- 
2.34.1

Reply via email to