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
