[RFC PATCH 17/19] r5: comomon.c: Add helper functions needed in LPM resume sequence

Prasanth Babu Mantena p-mantena at ti.com
Fri Mar 13 14:58:58 CET 2026


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 <p-mantena at ti.com>
---
 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



More information about the U-Boot mailing list