From: KR Sowmiya <[email protected]>

Add support for loading the Config/Chip Data Table (CDT) from eMMC
during the Shikra SPL boot flow and registering it with QCLIB via
the interface table.

Signed-off-by: KR Sowmiya <[email protected]>
---
 arch/arm/mach-snapdragon/board_spl.c        | 96 +++++++++++++++++++++
 arch/arm/mach-snapdragon/include/mach/spl.h |  1 +
 arch/arm/mach-snapdragon/qclib.c            |  8 ++
 board/qualcomm/shikra/spl-shikra.c          | 15 ++++
 4 files changed, 120 insertions(+)

diff --git a/arch/arm/mach-snapdragon/board_spl.c 
b/arch/arm/mach-snapdragon/board_spl.c
index 31a06b1e002..725d0cfd1e6 100644
--- a/arch/arm/mach-snapdragon/board_spl.c
+++ b/arch/arm/mach-snapdragon/board_spl.c
@@ -10,6 +10,10 @@
 #include <dm/uclass.h>
 #include <hang.h>
 #include <init.h>
+#include <linux/kernel.h>
+#include <mach/spl.h>
+#include <memalign.h>
+#include <part.h>
 #include <linux/err.h>
 #include <mach/qclib.h>
 #include <spl.h>
@@ -38,6 +42,98 @@ void __weak qcom_spl_soc_rpm_reset(void)
 {
 }
 
+#if IS_ENABLED(CONFIG_QCOM_SPL_CDT_SUPPORTED)
+/**
+ * qcom_spl_cdt_load() - Load the CDT from the boot medium.
+ *
+ * This functions read the boot medium for CDT information which gets saved
+ * in IMEM location.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+int qcom_spl_cdt_load(void)
+{
+       struct blk_desc *desc;
+       struct disk_partition info;
+       lbaint_t blocks;
+       bool is_mmc;
+       int ret;
+
+       ret = qcom_spl_get_boot_blk_desc(&desc);
+       if (ret) {
+               pr_debug("CDT: boot device not supported for CDT staging 
(%d)\n",
+                        ret);
+               return ret;
+       }
+
+       is_mmc = desc->uclass_id == UCLASS_MMC;
+       if (is_mmc) {
+               ret = blk_dselect_hwpart(desc, 
CONFIG_QCOM_SPL_CDT_MMC_PARTITION_NUM);
+               if (ret)
+                       return ret;
+
+               part_init(desc);
+       }
+
+#if defined(CONFIG_QCOM_SPL_CDT_USE_PARTITION_NAME)
+       ret = part_get_info_by_name(desc, CONFIG_QCOM_SPL_CDT_PARTITION_NAME, 
&info);
+#elif defined(CONFIG_QCOM_SPL_CDT_USE_PARTITION_GUID)
+       ret = part_get_info_by_type_guid(desc, 
CONFIG_QCOM_SPL_CDT_PARTITION_GUID,
+                                        &info);
+#else
+       ret = -EINVAL;
+#endif
+       if (ret < 0) {
+               pr_err("CDT: partition not found (%d)\n", ret);
+               goto restore_hwpart;
+       }
+
+       blocks = DIV_ROUND_UP(CONFIG_QCOM_SPL_BOOTITEM_CDT_SIZE, info.blksz);
+       if (blocks > info.size)
+               blocks = info.size;
+
+       {
+               ALLOC_CACHE_ALIGN_BUFFER(u8, blk_buf, blocks * info.blksz);
+               size_t read_size = blocks * info.blksz;
+               size_t copy_size = min_t(size_t, 
CONFIG_QCOM_SPL_BOOTITEM_CDT_SIZE,
+                                        read_size);
+
+               if (blk_dread(desc, info.start, blocks, blk_buf) != blocks) {
+                       pr_err("CDT: failed to read CDT partition\n");
+                       ret = -EIO;
+                       goto restore_hwpart;
+               }
+
+               memset((u8 *)CONFIG_QCOM_SPL_BOOTIMEM_CDT_BASE, 0,
+                      CONFIG_QCOM_SPL_BOOTITEM_CDT_SIZE);
+               memcpy((u8 *)CONFIG_QCOM_SPL_BOOTIMEM_CDT_BASE, blk_buf, 
copy_size);
+       }
+
+       ret = 0;
+
+restore_hwpart:
+       /* Restore the default (user data) hardware partition, if eMMC. */
+       if (is_mmc) {
+               int rc = blk_dselect_hwpart(desc, 0);
+
+               if (rc) {
+                       if (!ret)
+                               ret = rc;
+                       return ret;
+               }
+
+               part_init(desc);
+       }
+
+       return ret;
+}
+#else
+int qcom_spl_cdt_load(void)
+{
+       return -ENOSYS;
+}
+#endif /* IS_ENABLED(CONFIG_QCOM_SPL_CDT_SUPPORTED) */
+
 /**
  * qcom_spl_get_boot_blk_desc() - Get the boot medium's block device.
  * @descp: Set to the resolved block device on success.
diff --git a/arch/arm/mach-snapdragon/include/mach/spl.h 
b/arch/arm/mach-snapdragon/include/mach/spl.h
index a32a85c48fd..ed3e5910e7a 100644
--- a/arch/arm/mach-snapdragon/include/mach/spl.h
+++ b/arch/arm/mach-snapdragon/include/mach/spl.h
@@ -12,5 +12,6 @@ void qcom_spl_malloc_init_f(void);
 int qcom_spl_loader_pre_ddr(u8 boot_device);
 void qcom_spl_error_handler(void *arg);
 int qcom_spl_get_boot_blk_desc(struct blk_desc **descp);
+int qcom_spl_cdt_load(void);
 
 #endif /* __SPL_H__ */
diff --git a/arch/arm/mach-snapdragon/qclib.c b/arch/arm/mach-snapdragon/qclib.c
index b9a74863c1c..16308e0e77f 100644
--- a/arch/arm/mach-snapdragon/qclib.c
+++ b/arch/arm/mach-snapdragon/qclib.c
@@ -123,6 +123,14 @@ int __weak qclib_populate_interface_table(struct 
interface_table *if_tbl,
        if (ret)
                return ret;
 
+       if (IS_ENABLED(CONFIG_QCOM_SPL_CDT_SUPPORTED)) {
+               ret = qclib_add_iftbl_entry(if_tbl, 
CONFIG_QCOM_SPL_CDT_PARTITION_NAME,
+                                           CONFIG_QCOM_SPL_BOOTIMEM_CDT_BASE,
+                                           CONFIG_QCOM_SPL_BOOTITEM_CDT_SIZE);
+               if (ret)
+                       return ret;
+       }
+
        return qcom_spl_soc_qclib_override(if_tbl, fit, images_node);
 }
 
diff --git a/board/qualcomm/shikra/spl-shikra.c 
b/board/qualcomm/shikra/spl-shikra.c
index c2a5d2d692b..98912493c88 100644
--- a/board/qualcomm/shikra/spl-shikra.c
+++ b/board/qualcomm/shikra/spl-shikra.c
@@ -12,6 +12,7 @@
 #include <dm/uclass.h>
 #include <init.h>
 #include <linux/err.h>
+#include <linux/kernel.h>
 #include <linux/sizes.h>
 #include <linux/string.h>
 #include <malloc.h>
@@ -333,6 +334,12 @@ fail:
                reset_cpu();
 }
 #endif
+
+/**
+ * qcom_spl_soc_qclib_override() - Populate Shikra-specific interface table.
+ *
+ * Adds Shikra-specific blobs/entries to the QCLIB interface table.
+ */
 int qcom_spl_soc_qclib_override(struct interface_table *table,
                                const void *fit, int images_node)
 {
@@ -381,8 +388,16 @@ void qcom_spl_soc_shrm_reset(void)
 
 int qcom_spl_soc_pre_qclib_routine(void)
 {
+       int ret;
+
        qcom_spl_soc_shrm_reset();
 
+       if (IS_ENABLED(CONFIG_QCOM_SPL_CDT_SUPPORTED)) {
+               ret = qcom_spl_cdt_load();
+               if (ret)
+                       return ret;
+       }
+
        return 0;
 }
 
-- 
2.34.1

Reply via email to