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
