[3/4] ARM: exynos: Add CPU state management for Exynos542x under secure firmware

Message ID 20190218143412.6865-4-m.szyprowski@samsung.com
State New
Headers show
Series
  • Odroid XU3/4: add system suspend/resume support
Related show

Commit Message

Marek Szyprowski Feb. 18, 2019, 2:34 p.m.
From: Joonyoung Shim <jy0922.shim@samsung.com>


Add required CPU state management done via secure monitor call for
Exynos542x running unsed Secure Firmware.

Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>

[mszyprow: rewrote code to use defines and sysram base address instead
 of the magic numbers, added second smc call in pm_resume, rephrased
 subject and commit message]
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

---
 arch/arm/mach-exynos/common.h  |  1 +
 arch/arm/mach-exynos/exynos.c  |  3 +++
 arch/arm/mach-exynos/suspend.c | 17 +++++++++++++++--
 3 files changed, 19 insertions(+), 2 deletions(-)

-- 
2.17.1

Comments

Krzysztof Kozlowski Feb. 19, 2019, 11:30 a.m. | #1
On Mon, 18 Feb 2019 at 15:34, Marek Szyprowski <m.szyprowski@samsung.com> wrote:
>

> From: Joonyoung Shim <jy0922.shim@samsung.com>

>

> Add required CPU state management done via secure monitor call for

> Exynos542x running unsed Secure Firmware.

>

> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>

> [mszyprow: rewrote code to use defines and sysram base address instead

>  of the magic numbers, added second smc call in pm_resume, rephrased

>  subject and commit message]

> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

> ---

>  arch/arm/mach-exynos/common.h  |  1 +

>  arch/arm/mach-exynos/exynos.c  |  3 +++

>  arch/arm/mach-exynos/suspend.c | 17 +++++++++++++++--

>  3 files changed, 19 insertions(+), 2 deletions(-)

>

> diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h

> index 1b8699e94098..c93356a8d662 100644

> --- a/arch/arm/mach-exynos/common.h

> +++ b/arch/arm/mach-exynos/common.h

> @@ -91,6 +91,7 @@ extern u32 cp15_save_power;

>

>  extern void __iomem *sysram_ns_base_addr;

>  extern void __iomem *sysram_base_addr;

> +extern phys_addr_t sysram_base_phys;

>  extern void __iomem *pmu_base_addr;

>  void exynos_sysram_init(void);

>

> diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c

> index 865dcc4c3181..9aa483366ebc 100644

> --- a/arch/arm/mach-exynos/exynos.c

> +++ b/arch/arm/mach-exynos/exynos.c

> @@ -33,6 +33,7 @@ static struct platform_device exynos_cpuidle = {

>  };

>

>  void __iomem *sysram_base_addr __ro_after_init;

> +phys_addr_t sysram_base_phys __ro_after_init;

>  void __iomem *sysram_ns_base_addr __ro_after_init;

>

>  void __init exynos_sysram_init(void)

> @@ -43,6 +44,8 @@ void __init exynos_sysram_init(void)

>                 if (!of_device_is_available(node))

>                         continue;

>                 sysram_base_addr = of_iomap(node, 0);

> +               sysram_base_phys = of_translate_address(node,

> +                                          of_get_address(node, 0, NULL, NULL));

>                 break;

>         }

>

> diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c

> index c1e082ab2a1e..3ac84f621d99 100644

> --- a/arch/arm/mach-exynos/suspend.c

> +++ b/arch/arm/mach-exynos/suspend.c

> @@ -31,6 +31,7 @@

>  #include <asm/suspend.h>

>

>  #include "common.h"

> +#include "smc.h"

>

>  #define REG_TABLE_END (-1U)

>

> @@ -62,6 +63,8 @@ struct exynos_pm_state {

>         int cpu_state;

>         unsigned int pmu_spare3;

>         void __iomem *sysram_base;

> +       phys_addr_t sysram_phys;

> +       bool secure_firmware;

>  };

>

>  static const struct exynos_pm_data *pm_data __ro_after_init;

> @@ -340,6 +343,9 @@ static void exynos5420_pm_prepare(void)

>         pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +

>                                            EXYNOS5420_CPU_STATE);

>         writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);

> +       if (pm_state.secure_firmware)

> +               exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +

> +                                                  EXYNOS5420_CPU_STATE), 0, 0);

>

>         exynos_pm_enter_sleep_mode();

>

> @@ -459,6 +465,10 @@ static void exynos5420_pm_resume(void)

>         /* Restore the sysram cpu state register */

>         writel_relaxed(pm_state.cpu_state,

>                        pm_state.sysram_base + EXYNOS5420_CPU_STATE);

> +       if (pm_state.secure_firmware)

> +               exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +

> +                                                        EXYNOS5420_CPU_STATE),

> +                                                        EXYNOS_AFTR_MAGIC, 0);


This indentation is weird - the magic should not be indented as
SMC_REG_ID_SFR_W() param. How about something like:

exynos_smc(SMC_CMD_REG,
           SMC_REG_ID_SFR_W(pm_state.sysram_phys + EXYNOS5420_CPU_STATE),
           EXYNOS_AFTR_MAGIC, 0);

or if it does not fit in 80-line, then:
        if (pm_state.secure_firmware)
                exynos_smc(SMC_CMD_REG,
                           SMC_REG_ID_SFR_W(pm_state.sysram_phys +
                                            EXYNOS5420_CPU_STATE),
                           EXYNOS_AFTR_MAGIC, 0);

I can fix it while applying, unless you are going to resend.

Best regards,
Krzysztof
Krzysztof Kozlowski March 19, 2019, 8:10 p.m. | #2
On Mon, Feb 18, 2019 at 03:34:11PM +0100, Marek Szyprowski wrote:
> From: Joonyoung Shim <jy0922.shim@samsung.com>

> 

> Add required CPU state management done via secure monitor call for

> Exynos542x running unsed Secure Firmware.

> 

> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com>

> [mszyprow: rewrote code to use defines and sysram base address instead

>  of the magic numbers, added second smc call in pm_resume, rephrased

>  subject and commit message]

> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>

> ---

>  arch/arm/mach-exynos/common.h  |  1 +

>  arch/arm/mach-exynos/exynos.c  |  3 +++

>  arch/arm/mach-exynos/suspend.c | 17 +++++++++++++++--


Thanks, applied.

Best regards,
Krzysztof

Patch

diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 1b8699e94098..c93356a8d662 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -91,6 +91,7 @@  extern u32 cp15_save_power;
 
 extern void __iomem *sysram_ns_base_addr;
 extern void __iomem *sysram_base_addr;
+extern phys_addr_t sysram_base_phys;
 extern void __iomem *pmu_base_addr;
 void exynos_sysram_init(void);
 
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 865dcc4c3181..9aa483366ebc 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -33,6 +33,7 @@  static struct platform_device exynos_cpuidle = {
 };
 
 void __iomem *sysram_base_addr __ro_after_init;
+phys_addr_t sysram_base_phys __ro_after_init;
 void __iomem *sysram_ns_base_addr __ro_after_init;
 
 void __init exynos_sysram_init(void)
@@ -43,6 +44,8 @@  void __init exynos_sysram_init(void)
 		if (!of_device_is_available(node))
 			continue;
 		sysram_base_addr = of_iomap(node, 0);
+		sysram_base_phys = of_translate_address(node,
+					   of_get_address(node, 0, NULL, NULL));
 		break;
 	}
 
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index c1e082ab2a1e..3ac84f621d99 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -31,6 +31,7 @@ 
 #include <asm/suspend.h>
 
 #include "common.h"
+#include "smc.h"
 
 #define REG_TABLE_END (-1U)
 
@@ -62,6 +63,8 @@  struct exynos_pm_state {
 	int cpu_state;
 	unsigned int pmu_spare3;
 	void __iomem *sysram_base;
+	phys_addr_t sysram_phys;
+	bool secure_firmware;
 };
 
 static const struct exynos_pm_data *pm_data __ro_after_init;
@@ -340,6 +343,9 @@  static void exynos5420_pm_prepare(void)
 	pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
 					   EXYNOS5420_CPU_STATE);
 	writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+	if (pm_state.secure_firmware)
+		exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+						   EXYNOS5420_CPU_STATE), 0, 0);
 
 	exynos_pm_enter_sleep_mode();
 
@@ -459,6 +465,10 @@  static void exynos5420_pm_resume(void)
 	/* Restore the sysram cpu state register */
 	writel_relaxed(pm_state.cpu_state,
 		       pm_state.sysram_base + EXYNOS5420_CPU_STATE);
+	if (pm_state.secure_firmware)
+		exynos_smc(SMC_CMD_REG, SMC_REG_ID_SFR_W(pm_state.sysram_phys +
+							 EXYNOS5420_CPU_STATE),
+							 EXYNOS_AFTR_MAGIC, 0);
 
 	pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
 			S5P_CENTRAL_SEQ_OPTION);
@@ -658,8 +668,11 @@  void __init exynos_pm_init(void)
 	 * Applicable as of now only to Exynos542x. If booted under secure
 	 * firmware, the non-secure region of sysram should be used.
 	 */
-	if (exynos_secure_firmware_available())
+	if (exynos_secure_firmware_available()) {
+		pm_state.sysram_phys = sysram_base_phys;
 		pm_state.sysram_base = sysram_ns_base_addr;
-	else
+		pm_state.secure_firmware = true;
+	} else {
 		pm_state.sysram_base = sysram_base_addr;
+	}
 }