[PATCH 3/4] ARM: at91: pm: add support for sama5d2 secure suspend

Clément Léger clement.leger at bootlin.com
Tue Feb 22 07:08:45 PST 2022


When running with OP-TEE, the suspend control is handled securely.
Since the sama5d2 supports multiple suspend modes add a new
CONFIG_ATMEL_SECURE_PM which is mutually exclusive with CONFIG_ATMEL_PM
and allows to issue a SMC call to select the suspend mode.
"atmel.pm_modes" boot argument is still supported for compatibility
purposes but the standby value is actually ignored since PSCI suspend
is used and it only support one mode (suspend).

Signed-off-by: Clément Léger <clement.leger at bootlin.com>
---
 arch/arm/mach-at91/Kconfig          | 14 ++++++-
 arch/arm/mach-at91/Makefile         |  1 +
 arch/arm/mach-at91/pm_secure.c      | 64 +++++++++++++++++++++++++++++
 arch/arm/mach-at91/sam_secure.h     |  4 ++
 include/linux/platform_data/atmel.h |  2 +-
 5 files changed, 82 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/mach-at91/pm_secure.c

diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
index 02f6b108fd5d..bb11a914ad3e 100644
--- a/arch/arm/mach-at91/Kconfig
+++ b/arch/arm/mach-at91/Kconfig
@@ -201,14 +201,24 @@ config SOC_SAM_V7
 config SOC_SAMA5
 	bool
 	select ATMEL_AIC5_IRQ
-	select ATMEL_PM if PM
 	select ATMEL_SDRAMC
 	select MEMORY
 	select SOC_SAM_V7
 	select SRAM if PM
 
 config ATMEL_PM
-	bool
+	bool "Atmel PM support"
+	default y if SOC_SAMA5 && PM
+	depends on !ATMEL_SECURE_PM
+
+config ATMEL_SECURE_PM
+	bool "Atmel Secure PM support"
+	depends on SOC_SAMA5D2 && PM
+	help
+	  When running under a TEE, the suspend mode must be requested to be set
+	  at TEE level. When enable, this option will use secure monitor calls
+	  to set the suspend level.
+	  NOTE: This support is mutually exclusive with CONFIG_ATMEL_PM
 
 config SOC_SAMA7
 	bool
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 23620ccf7ab6..ebd88de8d0e7 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_SOC_SAMV7)		+= samv7.o
 
 # Power Management
 obj-$(CONFIG_ATMEL_PM)		+= pm.o pm_suspend.o pm_common.o
+obj-$(CONFIG_ATMEL_SECURE_PM)	+= pm_secure.o pm_common.o
 
 ifeq ($(CONFIG_CPU_V7),y)
 AFLAGS_pm_suspend.o := -march=armv7-a
diff --git a/arch/arm/mach-at91/pm_secure.c b/arch/arm/mach-at91/pm_secure.c
new file mode 100644
index 000000000000..2f63ff8c6226
--- /dev/null
+++ b/arch/arm/mach-at91/pm_secure.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2012, Bootlin
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/parser.h>
+#include <linux/string.h>
+#include "generic.h"
+#include "sam_secure.h"
+#include "pm.h"
+
+static int suspend_mode = AT91_PM_ULP0;
+
+static void at91_pm_secure_init(void)
+{
+	struct arm_smccc_res res;
+
+	res = sam_smccc_call(SAMA5_SMC_SIP_SET_SUSPEND_MODE, suspend_mode, 0);
+	if (res.a0 == 0) {
+		pr_info("AT91: Secure PM: suspend mode set to %s\n",
+			pm_modes[suspend_mode].pattern);
+		return;
+	}
+
+	pr_warn("AT91: Secure PM: %s mode not supported !\n",
+		pm_modes[suspend_mode].pattern);
+
+	res = sam_smccc_call(SAMA5_SMC_SIP_GET_SUSPEND_MODE, 0, 0);
+	if (res.a0 == 0) {
+		pr_warn("AT91: Secure PM: failed to get default mode\n");
+		return;
+	}
+	suspend_mode = res.a1;
+
+	pr_info("AT91: Secure PM: using default suspend mode %s\n",
+		pm_modes[suspend_mode].pattern);
+}
+
+void __init sama5_pm_init(void)
+{
+}
+
+void __init sama5d2_pm_init(void)
+{
+	at91_pm_secure_init();
+}
+
+int at91_suspend_entering_slow_clock(void)
+{
+	return (suspend_mode >= AT91_PM_ULP0);
+}
+EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
+
+static int __init at91_pm_modes_select(char *str)
+{
+	int dummy;
+
+	pr_warn("AT91: Secure PM: ignoring standby mode\n");
+
+	return at91_pm_common_modes_select(str, &dummy, &suspend_mode);
+}
+early_param("atmel.pm_modes", at91_pm_modes_select);
diff --git a/arch/arm/mach-at91/sam_secure.h b/arch/arm/mach-at91/sam_secure.h
index af19e24ca59e..b169317f61f6 100644
--- a/arch/arm/mach-at91/sam_secure.h
+++ b/arch/arm/mach-at91/sam_secure.h
@@ -8,6 +8,10 @@
 
 #include <linux/arm-smccc.h>
 
+/* Secure Monitor mode APIs */
+#define SAMA5_SMC_SIP_SET_SUSPEND_MODE	0x400
+#define SAMA5_SMC_SIP_GET_SUSPEND_MODE	0x401
+
 void __init sam_secure_init(void);
 struct arm_smccc_res sam_smccc_call(u32 fn, u32 arg0, u32 arg1);
 
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 73f63be509c4..cbb19712b4f0 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -7,7 +7,7 @@
 #define __ATMEL_H__
 
 /* FIXME: this needs a better location, but gets stuff building again */
-#ifdef CONFIG_ATMEL_PM
+#if defined(CONFIG_ATMEL_PM) || defined(CONFIG_ATMEL_SECURE_PM)
 extern int at91_suspend_entering_slow_clock(void);
 #else
 static inline int at91_suspend_entering_slow_clock(void)
-- 
2.34.1




More information about the linux-arm-kernel mailing list