Add the Shikra SPL board implementation, build rules, linker wrapper, and board configuration header. Configure QCLIB handoff data, early reset handling, and MMC boot-device and partition selection.
Signed-off-by: Abhilash V <[email protected]> --- board/qualcomm/shikra/Makefile | 3 + board/qualcomm/shikra/shikra-spl-wrap-elf.lds | 18 ++ board/qualcomm/shikra/spl-shikra.c | 202 ++++++++++++++++++ include/configs/shikra.h | 11 + 4 files changed, 234 insertions(+) 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/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..b967b0137b1 --- /dev/null +++ b/board/qualcomm/shikra/spl-shikra.c @@ -0,0 +1,202 @@ +// 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, + IPQ_SPL_BOOTCFG_DEV_EDL = 0x2, + IPQ_SPL_BOOTCFG_DEV_NAND = 0x3, + IPQ_SPL_BOOTCFG_DEV_EMMC_SD = 0x4, + IPQ_SPL_BOOTCFG_DEV_MAX +}; + +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(const u32 boot_device) +{ + struct blk_desc *desc; + struct disk_partition info; + int partition; + + if (!IS_ENABLED(CONFIG_MMC)) + return -ENOSYS; + + desc = blk_get_devnum_by_uclass_id(UCLASS_MMC, 0); + if (!desc) + return -ENODEV; + + 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 boot device identifier, or -EINVAL if the device is invalid. + */ +u32 spl_boot_device(void) +{ + u8 boot_device_cfg = + (readl(IPQ_SPL_BOOTCFG_REG_ADDR) & IPQ_SPL_BOOTCFG_DEV_MASK) >> + IPQ_SPL_BOOTCFG_DEV_SHFT; + u32 boot_device_smem; + + switch (boot_device_cfg) { + case IPQ_SPL_BOOTCFG_DEV_MMC: + boot_device_smem = BOOT_DEVICE_MMC1; + printf("Selected boot device: MMC\n"); + break; + case IPQ_SPL_BOOTCFG_DEV_SD_EMMC: + boot_device_smem = BOOT_DEVICE_MMC2; + printf("Selected boot device: SD MMC\n"); + break; + case IPQ_SPL_BOOTCFG_DEV_EDL: + boot_device_smem = BOOT_DEVICE_USB; + printf("Selected boot device: SPI-NAND\n"); + break; + case IPQ_SPL_BOOTCFG_DEV_NAND: + boot_device_smem = BOOT_DEVICE_NAND; + printf("Selected boot device: SPI-NAND\n"); + break; + default: + pr_err("Invalid boot device configured: %d\n", + boot_device_cfg); + return -EINVAL; + } + + return boot_device_smem; +} 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
