Add helper functions that are used by respective socs in lpm resume flow.

- save_certificate(void) is used to store the certificate information
in the reserved DDR memory for LPM.
- resume_to_dm_f(void) has the actual resume sequence which includes
decrypting atf back to original location and restoring context.
- resume_rproc_f(void) turn on the powerdomain of the rproc.

Signed-off-by: Prasanth Babu Mantena <[email protected]>
---
 arch/arm/mach-k3/common.h    |  14 +++++
 arch/arm/mach-k3/r5/common.c | 116 +++++++++++++++++++++++++++++++++++
 2 files changed, 130 insertions(+)

diff --git a/arch/arm/mach-k3/common.h b/arch/arm/mach-k3/common.h
index e970076d08e..321c86eb7bd 100644
--- a/arch/arm/mach-k3/common.h
+++ b/arch/arm/mach-k3/common.h
@@ -15,6 +15,7 @@
 
 #define K3_FIREWALL_BACKGROUND_BIT     (8)
 #define K3_SPEED_GRADE_UNKNOWN         '\0'
+#define FW_IMAGE_SIZE 0x80000
 
 struct fwl_data {
        const char *name;
@@ -41,6 +42,16 @@ enum k3_device_type {
        K3_DEVICE_TYPE_HS_SE,
 };
 
+struct lpm_addr_info {
+       u32 *context_save_addr;
+       u32 *atf_cert_addr;
+       u32 *optee_cert_addr;
+       u32 *dm_save_addr;
+       u32 size;
+};
+
+extern struct lpm_addr_info mem_addr_lpm;
+
 void setup_k3_mpu_regions(void);
 int early_console_init(void);
 void disable_linefill_optimization(void);
@@ -60,6 +71,9 @@ struct ti_sci_handle *get_ti_sci_handle(void);
 void do_board_detect(void);
 void ti_secure_image_check_binary(void **p_image, size_t *p_size);
 int shutdown_mcu_r5_core1(void);
+void save_certificate(void);
+u32 resume_to_dm_f(void);
+void resume_rproc_f(void);
 
 #if IS_ENABLED(CONFIG_SPL_OS_BOOT_SECURE) && !IS_ENABLED(CONFIG_ARM64)
 int k3_r5_falcon_bootmode(void);
diff --git a/arch/arm/mach-k3/r5/common.c b/arch/arm/mach-k3/r5/common.c
index 03638366046..e0bc57061b4 100644
--- a/arch/arm/mach-k3/r5/common.c
+++ b/arch/arm/mach-k3/r5/common.c
@@ -16,6 +16,9 @@
 #include <spl.h>
 #include <remoteproc.h>
 #include <elf.h>
+#include <clk.h>
+#include <power-domain.h>
+#include <dm/read.h>
 
 #include "../common.h"
 
@@ -45,6 +48,23 @@ static const char *image_os_match[IMAGE_AMT] = {
 
 static struct image_info fit_image_info[IMAGE_AMT];
 
+struct lpm_addr_info mem_addr_lpm;
+
+__weak int board_is_resuming(void)
+{
+       return 0;
+}
+
+__weak void lpm_process(void)
+{
+       return;
+}
+
+__weak int extract_lpm_region(void)
+{
+       return -EINVAL;
+}
+
 void init_env(void)
 {
 #ifdef CONFIG_SPL_ENV_SUPPORT
@@ -137,6 +157,25 @@ void release_resources_for_core_shutdown(void)
        }
 }
 
+void save_certificate(void)
+{
+       int ret;
+
+       if (!fit_image_info[IMAGE_ID_ATF].image_start || 
!fit_image_info[IMAGE_ID_OPTEE].image_start || 
!fit_image_info[IMAGE_ID_DM_FW].image_start) {
+               pr_err("Invalid images to save\n");
+               return;
+       }
+
+       ret = extract_lpm_region();
+       if (ret)
+               pr_err("Cannot find valid LPM address range..\n");
+       else {
+               memcpy(mem_addr_lpm.atf_cert_addr, (void 
*)fit_image_info[IMAGE_ID_ATF].image_start, 
fit_image_info[IMAGE_ID_ATF].image_len);
+               memcpy(mem_addr_lpm.optee_cert_addr, (void 
*)fit_image_info[IMAGE_ID_OPTEE].image_start, 
fit_image_info[IMAGE_ID_OPTEE].image_len);
+               memcpy(mem_addr_lpm.dm_save_addr, (void 
*)fit_image_info[IMAGE_ID_DM_FW].image_start, 
fit_image_info[IMAGE_ID_DM_FW].image_len);
+       }
+}
+
 void __noreturn jump_to_image(struct spl_image_info *spl_image)
 {
        typedef void __noreturn (*image_entry_noargs_t)(void);
@@ -170,6 +209,7 @@ void __noreturn jump_to_image(struct spl_image_info 
*spl_image)
        if (ret)
                panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
 
+       lpm_process();
 #if CONFIG_IS_ENABLED(FIT_IMAGE_POST_PROCESS)
        /* Authenticate ATF */
        void *image_addr = (void *)fit_image_info[IMAGE_ID_ATF].image_start;
@@ -254,6 +294,82 @@ void disable_linefill_optimization(void)
        asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
 }
 
+u32 resume_to_dm_f(void)
+{
+       struct ti_sci_handle *ti_sci = get_ti_sci_handle();
+       u32 loadaddr = 0, save_addr = 0;
+       int ret = 0;
+
+       loadaddr = (u32)mem_addr_lpm.dm_save_addr;
+       if (!valid_elf_image(loadaddr))
+               panic("%s: DM-Firmware image is not valid, it cannot be 
loaded\n",
+                     __func__);
+       loadaddr = load_elf_image_phdr(loadaddr);
+       save_addr = (uintptr_t)mem_addr_lpm.context_save_addr;
+       ret = ti_sci->ops.lpm_ops.lpm_save_addr(ti_sci, save_addr, 
mem_addr_lpm.size);
+       if (ret)
+               panic("TIFS lpm save addr fail : %x\n", ret);
+       /*
+        * TIFS minimal context restore
+        * This restores also the firewall
+       */
+       ret = ti_sci->ops.lpm_ops.restore_context(ti_sci, 0);
+       if (ret)
+               panic("TIFS min_context_restore failed (%d)\n", ret);
+       /*
+        * Restore TFA in msmc memory
+        */
+       ret = ti_sci->ops.lpm_ops.decrypt_tfa(ti_sci,
+                                             CONFIG_K3_ATF_LOAD_ADDR);
+       if (ret)
+               panic("%s: TIFS failed to decrytp TFA : %x\n", __func__, ret);
+               /* restore TFA resume vectore address in main core */
+       ret = ti_sci->ops.lpm_ops.core_resume(ti_sci);
+       if (ret)
+               panic("ATF failed to resume (%d)\n", ret);
+
+       return loadaddr;
+}
+
+void resume_rproc_f(void)
+{
+       struct power_domain rproc_pwrdmn;
+       unsigned long gtc_rate;
+       struct udevice *dev;
+       struct clk gtc_clk;
+       void *gtc_base;
+       int ret;
+
+       ret = uclass_get_device_by_seq(UCLASS_REMOTEPROC, 1, &dev);
+       if (ret)
+               panic("Unknown remote processor 1 (%d)\n", ret);
+
+       ret = power_domain_get_by_index(dev, &rproc_pwrdmn, 1);
+       if (ret)
+               panic("power_domain_get_rproc() failed: %d\n", ret);
+
+       ret = clk_get_by_index(dev, 0, &gtc_clk);
+       if (ret)
+               panic("clk_get failed: %d\n", ret);
+
+       gtc_base = dev_read_addr_ptr(dev);
+       if (!gtc_base)
+               panic("Get GTC address failed\n");
+
+       gtc_rate = clk_get_rate(&gtc_clk);
+
+#define GTC_CNTCR_REG  0x0
+#define GTC_CNTFID0_REG        0x20
+#define GTC_CNTR_EN    0x3
+       /* TFA expect the Global Timebase Counter to be set-up */
+       writel((u32)gtc_rate, gtc_base + GTC_CNTFID0_REG);
+       writel(GTC_CNTR_EN, gtc_base + GTC_CNTCR_REG);
+
+       ret = power_domain_on(&rproc_pwrdmn);
+       if (ret)
+               panic("power_domain_on failed: %d\n", ret);
+}
+
 int remove_fwl_region(struct fwl_data *fwl)
 {
        struct ti_sci_handle *sci = get_ti_sci_handle();
-- 
2.34.1

Reply via email to