This is a common function that helps to resume from DDR. There are two
pointers which are fetched from DDR to resume, the TIFS context pointer
which points to the context in DDR. There is another pointer to the DM
loadaddr to jump back into DM.

Signed-off-by: Markus Schneider-Pargmann (TI.com) <[email protected]>
---
 arch/arm/mach-k3/am62xx-lpm-common.c | 52 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-k3/am62xx-lpm-common.h |  1 +
 2 files changed, 53 insertions(+)

diff --git a/arch/arm/mach-k3/am62xx-lpm-common.c 
b/arch/arm/mach-k3/am62xx-lpm-common.c
index 
54d86b0474df691e8568a9c38530c56cc1eb3a0a..fa068c60ce9ccf9cec89aeae1d224b07091a3298
 100644
--- a/arch/arm/mach-k3/am62xx-lpm-common.c
+++ b/arch/arm/mach-k3/am62xx-lpm-common.c
@@ -9,9 +9,12 @@
 #include <config.h>
 #include <asm/arch/hardware.h>
 #include <asm/io.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+#include <vsprintf.h>
 #include <wait_bit.h>
 
 #include "am62xx-lpm-common.h"
+#include "common.h"
 
 /*
  * Shared WKUP_CTRL_MMR0 definitions used to remove IO isolation
@@ -121,3 +124,52 @@ int __maybe_unused 
wkup_ctrl_remove_can_io_isolation_if_set(void)
                return wkup_ctrl_remove_can_io_isolation();
        return 0;
 }
+
+#if IS_ENABLED(CONFIG_K3_IODDR)
+static int lpm_restore_context(u64 ctx_addr)
+{
+       struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+       int ret;
+
+       ret = ti_sci->ops.lpm_ops.min_context_restore(ti_sci, ctx_addr);
+       if (ret)
+               printf("Failed to restore context from DDR %d\n", ret);
+
+       return ret;
+}
+
+struct lpm_meta_data {
+       u64 dm_jump_address;
+       u64 tifs_context_save_address;
+       u64 reserved[30];
+} __packed;
+
+void __noreturn lpm_resume_from_ddr(u64 meta_data_addr)
+{
+       struct lpm_meta_data lpm_data = *(struct lpm_meta_data 
*)(uintptr_t)meta_data_addr;
+       typedef void __noreturn (*image_entry_noargs_t)(void);
+       image_entry_noargs_t image_entry;
+       int ret;
+
+       ret = lpm_restore_context(lpm_data.tifs_context_save_address);
+       if (ret)
+               panic("Failed to restore context from 0x%x%08x\n",
+                     (u32)(lpm_data.tifs_context_save_address >> 32),
+                     (u32)lpm_data.tifs_context_save_address);
+
+       image_entry = (image_entry_noargs_t)(uintptr_t)lpm_data.dm_jump_address;
+       printf("Resuming from DDR, jumping to stored DM loadaddr 0x%x%08x, TIFS 
context restored from 0x%x%08x\n",
+              (u32)(lpm_data.dm_jump_address >> 32),
+              (u32)lpm_data.dm_jump_address,
+              (u32)(lpm_data.tifs_context_save_address >> 32),
+              (u32)lpm_data.tifs_context_save_address);
+
+       image_entry();
+}
+#else
+
+void __noreturn lpm_resume_from_ddr(u64 meta_data_addr)
+{
+       panic("No IO+DDR support");
+}
+#endif
diff --git a/arch/arm/mach-k3/am62xx-lpm-common.h 
b/arch/arm/mach-k3/am62xx-lpm-common.h
index 
2d110bcca0fc74ecd5424ae288d43519d0c05908..d5793759da4a05d355f5d88fbd8e103ebc46f9cc
 100644
--- a/arch/arm/mach-k3/am62xx-lpm-common.h
+++ b/arch/arm/mach-k3/am62xx-lpm-common.h
@@ -13,5 +13,6 @@
 
 bool wkup_ctrl_is_lpm_exit(void);
 int wkup_ctrl_remove_can_io_isolation_if_set(void);
+void lpm_resume_from_ddr(u64 meta_data_addr);
 
 #endif  /* _AM62XX_LPM_COMMON_H_ */

-- 
2.51.0

Reply via email to