Add helpers for adding QCLIB interface-table entries and FIT blobs, expose the DDR self-refresh exit address, preserve U-Boot global data across the QCLIB call, and provide weak reset hooks for SoC-specific SPL code.
Signed-off-by: Abhilash V <[email protected]> --- arch/arm/mach-snapdragon/board_spl.c | 50 ++++++++++++ arch/arm/mach-snapdragon/include/mach/qclib.h | 16 +++- arch/arm/mach-snapdragon/include/mach/spl.h | 3 + arch/arm/mach-snapdragon/qclib.c | 77 +++++++++++++++---- 4 files changed, 130 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-snapdragon/board_spl.c b/arch/arm/mach-snapdragon/board_spl.c index 3293eab8f81..4e3b2527a7b 100644 --- a/arch/arm/mach-snapdragon/board_spl.c +++ b/arch/arm/mach-snapdragon/board_spl.c @@ -6,8 +6,11 @@ */ #include <asm/sections.h> +#include <blk.h> +#include <dm/uclass.h> #include <hang.h> #include <init.h> +#include <linux/err.h> #include <mach/qclib.h> #include <spl.h> #include <soc/qcom/smem.h> @@ -27,6 +30,53 @@ __weak void reset_cpu(void) hang(); } +void __weak qcom_spl_soc_shrm_reset(void) +{ +} + +void __weak qcom_spl_soc_rpm_reset(void) +{ +} + +/** + * qcom_spl_get_boot_blk_desc() - Get the boot medium's block device. + * @descp: Set to the resolved block device on success. + * + * Maps the already-detected boot device to the uclass/devnum pair. + * + * Return: 0 on success, or a negative error code if the boot device is + * unsupported or its block device cannot be found. + */ +int qcom_spl_get_boot_blk_desc(struct blk_desc **descp) +{ + enum uclass_id uclass_id; + int devnum; + + switch (spl_boot_device()) { + case BOOT_DEVICE_MMC1: + uclass_id = UCLASS_MMC; + devnum = 0; + break; + case BOOT_DEVICE_MMC2: + case BOOT_DEVICE_MMC2_2: + uclass_id = UCLASS_MMC; + devnum = 1; + break; + case BOOT_DEVICE_UFS: + uclass_id = UCLASS_SCSI; + devnum = 0; + break; + default: + return -ENOSYS; + } + + *descp = blk_get_devnum_by_uclass_id(uclass_id, devnum); + if (!*descp) + return -ENODEV; + + return 0; +} + #if IS_ENABLED(CONFIG_SPL_SMEM) /** * qcom_spl_populate_smem() - Populate shared memory (SMEM) information. diff --git a/arch/arm/mach-snapdragon/include/mach/qclib.h b/arch/arm/mach-snapdragon/include/mach/qclib.h index b44874c514e..10865b03ea1 100644 --- a/arch/arm/mach-snapdragon/include/mach/qclib.h +++ b/arch/arm/mach-snapdragon/include/mach/qclib.h @@ -65,11 +65,25 @@ void qclib_set_qcsdi_address(u64 address); u64 qclib_get_log_buffer_entry(void); void qclib_set_log_buffer_entry(u64 address); +/* DDR self-refresh exit address accessors, populated post-QCLIB */ +u64 qclib_get_ddr_sr_exit_address(void); +void qclib_set_ddr_sr_exit_address(u64 address); + +/* Interface-table entry helpers */ +int qclib_add_iftbl_entry(struct interface_table *table, + const char *name, u64 address, u32 size); +int qclib_add_iftbl_fit_blob(struct interface_table *table, + const void *fit, int images_node, + const char *name, u32 size); + /* * __weak SoC extension points. A board's spl-<soc>.c may provide a strong - * override for any of these; the defaults in qclib.c are all no-ops. + * override for any of these; the defaults are provided by the common + * Snapdragon SPL implementation. */ bool qcom_spl_soc_check_dload_mode(void); +void qcom_spl_soc_shrm_reset(void); +void qcom_spl_soc_rpm_reset(void); int qcom_spl_soc_pre_qclib_routine(void); int qcom_spl_soc_qclib_override(struct interface_table *table, const void *fit, int images_node); diff --git a/arch/arm/mach-snapdragon/include/mach/spl.h b/arch/arm/mach-snapdragon/include/mach/spl.h index 50cc8dc4e8f..a32a85c48fd 100644 --- a/arch/arm/mach-snapdragon/include/mach/spl.h +++ b/arch/arm/mach-snapdragon/include/mach/spl.h @@ -6,8 +6,11 @@ #ifndef __SPL_H__ #define __SPL_H__ +struct blk_desc; + 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); #endif /* __SPL_H__ */ diff --git a/arch/arm/mach-snapdragon/qclib.c b/arch/arm/mach-snapdragon/qclib.c index 7f25f37b5d9..b9a74863c1c 100644 --- a/arch/arm/mach-snapdragon/qclib.c +++ b/arch/arm/mach-snapdragon/qclib.c @@ -2,7 +2,8 @@ /* * QCLIB interface-table protocol: generic, SoC-agnostic orchestration of the * hand-off to the QCLIB firmware image, plus __weak extension points a - * per-board spl-<soc>.c may override to populate SoC-specific table entries. + * per-board spl-<soc>.c may override to populate SoC-specific table entries + * and provide SoC-specific reset sequences. */ #include <cpu_func.h> @@ -15,6 +16,17 @@ static u64 g_qcsdi_address __section(".data"); static u64 g_log_buffer_entry __section(".data"); +static u64 g_ddr_sr_exit_address __section(".data"); + +u64 qclib_get_ddr_sr_exit_address(void) +{ + return g_ddr_sr_exit_address; +} + +void qclib_set_ddr_sr_exit_address(u64 address) +{ + g_ddr_sr_exit_address = address; +} u64 qclib_get_qcsdi_address(void) { @@ -36,6 +48,42 @@ void qclib_set_log_buffer_entry(u64 address) g_log_buffer_entry = address; } +int qclib_add_iftbl_entry(struct interface_table *table, + const char *name, u64 address, u32 size) +{ + uint entry_idx = table->num_entries; + + if (entry_idx >= table->max_entries) + return -ENOSPC; + + memset(&table->if_table_entries[entry_idx], 0, + sizeof(table->if_table_entries[entry_idx])); + memcpy(table->if_table_entries[entry_idx].entry_name, name, strlen(name)); + table->if_table_entries[entry_idx].address = address; + table->if_table_entries[entry_idx].size = size; + table->num_entries = entry_idx + 1; + + return 0; +} + +int qclib_add_iftbl_fit_blob(struct interface_table *table, + const void *fit, int images_node, + const char *name, u32 size) +{ + int node, ret; + u64 address; + + node = fdt_subnode_offset(fit, images_node, name); + if (node < 0) + return -ENOENT; + + ret = qcom_spl_get_fit_img_entry_point((void *)fit, node, &address); + if (ret) + return ret; + + return qclib_add_iftbl_entry(table, name, address, size); +} + bool __weak qcom_spl_soc_check_dload_mode(void) { return false; @@ -43,6 +91,8 @@ bool __weak qcom_spl_soc_check_dload_mode(void) int __weak qcom_spl_soc_pre_qclib_routine(void) { + qcom_spl_soc_shrm_reset(); + return 0; } @@ -60,7 +110,7 @@ int __weak qcom_spl_soc_post_qclib_routine(struct interface_table *if_tbl) int __weak qclib_populate_interface_table(struct interface_table *if_tbl, const void *fit, int images_node) { - struct interface_table_entry *log_buffer_entry; + int ret; memset(if_tbl, 0, sizeof(struct interface_table)); memcpy(if_tbl->magic_key, MAGIC_KEY, strlen(MAGIC_KEY)); @@ -68,17 +118,10 @@ int __weak qclib_populate_interface_table(struct interface_table *if_tbl, if_tbl->num_entries = 0; if_tbl->max_entries = MAX_ENTRIES; - /* - * Reserve the "qclib_log_buffer" slot ??? common to every SoC. - * QCLIB fills in the address itself; SPL just allocates the entry. - */ - log_buffer_entry = &if_tbl->if_table_entries[if_tbl->num_entries]; - memcpy(log_buffer_entry->entry_name, QCLIB_LOG_BUFFER, - strlen(QCLIB_LOG_BUFFER)); - log_buffer_entry->address = 0; - log_buffer_entry->size = 0; - log_buffer_entry->attributes = 0; - if_tbl->num_entries++; + /* Reserve the common qclib_log_buffer slot. */ + ret = qclib_add_iftbl_entry(if_tbl, QCLIB_LOG_BUFFER, 0, 0); + if (ret) + return ret; return qcom_spl_soc_qclib_override(if_tbl, fit, images_node); } @@ -146,9 +189,13 @@ int qcom_spl_invoke_qclib(void) register void *x0 asm("x0") = &if_tbl; register void *x1 asm("x1") = NULL; register u64 x8 asm("x8") = entry_point; + u64 saved_x18; - asm volatile ("blr x8" - : "+r" (x0) + /* U-Boot keeps global data in x18 on AArch64. */ + asm volatile ("str x18, %1\n\t" + "blr x8\n\t" + "ldr x18, %1" + : "+r" (x0), "=m" (saved_x18) : "r" (x1), "r" (x8) : "x2", "x3", "x4", "x5", "x6", "x7", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", -- 2.34.1
