Add Shikra SPL board implementation, build rules, and linker
wrapper, board configuration header, and QCLIB handoff data.
Configure early reset handling and MMC boot selection.

Decode the Shikra boot configuration and map eMMC and SD
sources to SPL MMC devices for boot-device and FIT partition
selection.

Signed-off-by: Abhilash V <[email protected]>
---
 arch/arm/mach-snapdragon/board_spl.c          |   4 +-
 board/qualcomm/shikra/Makefile                |   3 +
 board/qualcomm/shikra/shikra-spl-wrap-elf.lds |  18 ++
 board/qualcomm/shikra/spl-shikra.c            | 194 ++++++++++++++++++
 include/configs/shikra.h                      |  11 +
 5 files changed, 228 insertions(+), 2 deletions(-)
 create mode 100644 board/qualcomm/shikra/Makefile
 create mode 100644 board/qualcomm/shikra/shikra-spl-wrap-elf.lds
 create mode 100644 board/qualcomm/shikra/spl-shikra.c
 create mode 100644 include/configs/shikra.h

diff --git a/arch/arm/mach-snapdragon/board_spl.c 
b/arch/arm/mach-snapdragon/board_spl.c
index 4e3b2527a7b..31a06b1e002 100644
--- a/arch/arm/mach-snapdragon/board_spl.c
+++ b/arch/arm/mach-snapdragon/board_spl.c
@@ -141,13 +141,13 @@ u32 spl_mmc_boot_mode(struct mmc *mmc, const u32 
boot_device)
  *
  * Return: Partition number to boot from, or default partition on error
  */
-int __weak spl_mmc_boot_partition(const u32 boot_device)
+int __weak spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device)
 {
        int p_no;
        struct blk_desc *desc;
        struct disk_partition info;
 
-       desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0);
+       desc = mmc_get_blk_desc(mmc);
        if (!desc) {
                pr_err("%s: Block device not found\n", __func__);
                return -ENODEV;
diff --git a/board/qualcomm/shikra/Makefile b/board/qualcomm/shikra/Makefile
new file mode 100644
index 00000000000..eb3961a3ead
--- /dev/null
+++ b/board/qualcomm/shikra/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+obj-$(CONFIG_SPL) := spl-shikra.o
diff --git a/board/qualcomm/shikra/shikra-spl-wrap-elf.lds 
b/board/qualcomm/shikra/shikra-spl-wrap-elf.lds
new file mode 100644
index 00000000000..b2922cd2c2c
--- /dev/null
+++ b/board/qualcomm/shikra/shikra-spl-wrap-elf.lds
@@ -0,0 +1,18 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-only
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+PHDRS {
+       ptype PT_LOAD FLAGS(0x7);
+}
+
+ENTRY(_entry)
+
+SECTIONS {
+       . = CONFIG_PLATFORM_ELFENTRY;
+       _entry = . ;
+       data : {
+               *(.data)
+               . = ALIGN(4);
+       } :ptype
+}
diff --git a/board/qualcomm/shikra/spl-shikra.c 
b/board/qualcomm/shikra/spl-shikra.c
new file mode 100644
index 00000000000..b41877743b2
--- /dev/null
+++ b/board/qualcomm/shikra/spl-shikra.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#include <blk.h>
+#include <asm/io.h>
+#include <dm/uclass.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <mach/qclib.h>
+#include <mach/spl.h>
+#include <part.h>
+#include <spl.h>
+
+#define IPQ_SPL_BOOTCFG_REG_ADDR       0x1B46070
+#define IPQ_SPL_BOOTCFG_DEV_MASK       GENMASK(5, 1)
+#define IPQ_SPL_BOOTCFG_DEV_SHFT       0x1
+
+#define SHIKRA_DDR_INFORMATION         "ddr_information"
+#define SHIKRA_DDR_TRAINING_DATA       "ddr_training_data"
+#define SHIKRA_DDR_SR_EXIT             "ddr_sr_exit"
+#define SHIKRA_PMIC_COCOS              "pmic_cocos"
+#define SHIKRA_PMIC_WAILUA             "pmic_wailua"
+#define SHIKRA_DCB_LP4                 "dcb_lp4"
+#define SHIKRA_DCB_LP5                 "dcb_lp5"
+#define SHIKRA_ECC                     "ecc"
+
+#define SHIKRA_DDR_TRAINING_DATA_ADDR  0x0c368000
+#define SHIKRA_DDR_TRAINING_DATA_SIZE  0x8000
+#define SHIKRA_PMIC_COCOS_SIZE         0xbc00
+#define SHIKRA_PMIC_WAILUA_SIZE        0x6000
+#define SHIKRA_DCB_LP4_SIZE            0x4800
+#define SHIKRA_DCB_LP5_SIZE            0x4800
+#define SHIKRA_ECC_SIZE                        0x400
+
+#define SHIKRA_SHRM2_SPROC_CTRL_ADDR                   0x0c36000
+#define SHIKRA_SHRM2_SPROC_CTRL_CORE_SW_RESET_BMSK     BIT(1)
+#define SHIKRA_SHRM2_SPROC_CTRL_DEBUG_SW_RESET_BMSK    BIT(3)
+
+/* GCC_APCS_MISC contains the RPM reset control bit. */
+#define SHIKRA_GCC_APCS_MISC_ADDR                      0x01491000
+#define SHIKRA_GCC_APCS_MISC_RPM_RESET_BMSK            BIT(0)
+
+#define SHIKRA_RPM_STAGING_ADDR                        0x04690000
+#define SHIKRA_RPM_STAGING_SIZE                        0x1363c
+
+#define QCOM_SPL_FIT_IMG_PARTITION     "uefi_a"
+
+enum {
+       IPQ_SPL_BOOTCFG_DEV_MMC = 0x0,
+       IPQ_SPL_BOOTCFG_DEV_SD_EMMC     = 0x1,
+};
+
+int qcom_spl_soc_qclib_override(struct interface_table *table,
+                               const void *fit, int images_node)
+{
+       static const struct {
+               const char *name;
+               u32 size;
+       } fit_blobs[] = {
+               { SHIKRA_PMIC_COCOS, SHIKRA_PMIC_COCOS_SIZE },
+               { SHIKRA_PMIC_WAILUA, SHIKRA_PMIC_WAILUA_SIZE },
+               { SHIKRA_DCB_LP4, SHIKRA_DCB_LP4_SIZE },
+               { SHIKRA_DCB_LP5, SHIKRA_DCB_LP5_SIZE },
+               { SHIKRA_ECC, SHIKRA_ECC_SIZE },
+       };
+       uint i;
+       int ret;
+
+       table->global_attributes |= QCLIB_GA_ENABLE_UART_LOGGING;
+       for (i = 0; i < ARRAY_SIZE(fit_blobs); i++) {
+               ret = qclib_add_iftbl_fit_blob(table, fit, images_node,
+                                              fit_blobs[i].name, 
fit_blobs[i].size);
+               if (ret)
+                       return ret;
+       }
+
+       ret = qclib_add_iftbl_entry(table, SHIKRA_DDR_TRAINING_DATA,
+                                   SHIKRA_DDR_TRAINING_DATA_ADDR,
+                                   SHIKRA_DDR_TRAINING_DATA_SIZE);
+       if (ret)
+               return ret;
+       ret = qclib_add_iftbl_entry(table, SHIKRA_DDR_INFORMATION, 0, 0);
+       if (ret)
+               return ret;
+
+       return qclib_add_iftbl_entry(table, SHIKRA_DDR_SR_EXIT, 0, 0);
+}
+
+void qcom_spl_soc_shrm_reset(void)
+{
+       writel(SHIKRA_SHRM2_SPROC_CTRL_DEBUG_SW_RESET_BMSK |
+              SHIKRA_SHRM2_SPROC_CTRL_CORE_SW_RESET_BMSK,
+              (void *)SHIKRA_SHRM2_SPROC_CTRL_ADDR);
+       writel(SHIKRA_SHRM2_SPROC_CTRL_CORE_SW_RESET_BMSK,
+              (void *)SHIKRA_SHRM2_SPROC_CTRL_ADDR);
+       writel(0, (void *)SHIKRA_SHRM2_SPROC_CTRL_ADDR);
+}
+
+int qcom_spl_soc_pre_qclib_routine(void)
+{
+       qcom_spl_soc_shrm_reset();
+
+       return 0;
+}
+
+void qcom_spl_soc_rpm_reset(void)
+{
+       clrbits_le32((void *)SHIKRA_GCC_APCS_MISC_ADDR,
+                    SHIKRA_GCC_APCS_MISC_RPM_RESET_BMSK);
+}
+
+int spl_check_board_image(struct spl_image_info *spl_image,
+                         const struct spl_boot_device *bootdev)
+{
+       qcom_spl_soc_rpm_reset();
+
+       return 0;
+}
+
+int qcom_spl_soc_post_qclib_routine(struct interface_table *table)
+{
+       struct interface_table_entry entry;
+       int ret;
+
+       /*
+        * Clear the full memory region reserved for the RPM image before 
loading
+        * the post-DDR FIT, including its zero-initialized data.
+        */
+       memset((void *)SHIKRA_RPM_STAGING_ADDR, 0, SHIKRA_RPM_STAGING_SIZE);
+
+       ret = qcom_spl_get_iftbl_entry_by_name(table, SHIKRA_DDR_SR_EXIT,
+                                              &entry);
+       if (ret)
+               return ret;
+
+       qclib_set_ddr_sr_exit_address(entry.address);
+       return 0;
+}
+
+int spl_mmc_boot_partition(struct mmc *mmc, const u32 boot_device)
+{
+       struct blk_desc *desc;
+       struct disk_partition info;
+       int partition, ret;
+
+       if (!IS_ENABLED(CONFIG_MMC))
+               return -ENOSYS;
+
+       if (boot_device != BOOT_DEVICE_MMC1 &&
+           boot_device != BOOT_DEVICE_MMC2)
+               return -ENODEV;
+
+       ret = qcom_spl_get_boot_blk_desc(&desc);
+       if (ret)
+               return ret;
+
+       partition = part_get_info_by_name(desc, QCOM_SPL_FIT_IMG_PARTITION,
+                                         &info);
+       if (partition < 0)
+               return -ENOENT;
+
+       return partition;
+}
+
+/**
+ * spl_boot_device() - Get the boot device.
+ *
+ * Return: U-Boot SPL boot device identifier, or -EINVAL if the device is 
invalid.
+ */
+u32 spl_boot_device(void)
+{
+       int boot_device;
+
+       boot_device =
+               (readl(IPQ_SPL_BOOTCFG_REG_ADDR) & IPQ_SPL_BOOTCFG_DEV_MASK) >>
+               IPQ_SPL_BOOTCFG_DEV_SHFT;
+
+       switch (boot_device) {
+       case IPQ_SPL_BOOTCFG_DEV_MMC:
+               boot_device = BOOT_DEVICE_MMC1;
+               printf("Selected boot device: MMC\n");
+               break;
+       case IPQ_SPL_BOOTCFG_DEV_SD_EMMC:
+               boot_device = BOOT_DEVICE_MMC2;
+               printf("Selected boot device: SD MMC\n");
+               break;
+       default:
+               pr_err("Invalid boot device configured\n");
+               return -EINVAL;
+       }
+
+       return boot_device;
+}
diff --git a/include/configs/shikra.h b/include/configs/shikra.h
new file mode 100644
index 00000000000..7d88dc0e670
--- /dev/null
+++ b/include/configs/shikra.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#ifndef __CONFIGS_SHIKRA_H
+#define __CONFIGS_SHIKRA_H
+
+#include <linux/sizes.h>
+
+#endif
-- 
2.34.1

Reply via email to