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          |  8 ++
 arch/arm/mach-snapdragon/include/mach/qclib.h | 16 +++-
 arch/arm/mach-snapdragon/qclib.c              | 77 +++++++++++++++----
 3 files changed, 85 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-snapdragon/board_spl.c 
b/arch/arm/mach-snapdragon/board_spl.c
index 3293eab8f81..5aa84a3a6d1 100644
--- a/arch/arm/mach-snapdragon/board_spl.c
+++ b/arch/arm/mach-snapdragon/board_spl.c
@@ -27,6 +27,14 @@ __weak void reset_cpu(void)
        hang();
 }
 
+void __weak qcom_spl_soc_shrm_reset(void)
+{
+}
+
+void __weak qcom_spl_soc_rpm_reset(void)
+{
+}
+
 #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/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

Reply via email to