ARM: exynos: Add CPU state management for Exynos542x under secure firmware
authorJoonyoung Shim <jy0922.shim@samsung.com>
Mon, 18 Feb 2019 14:34:11 +0000 (15:34 +0100)
committerKrzysztof Kozlowski <krzk@kernel.org>
Tue, 19 Mar 2019 20:07:47 +0000 (21:07 +0100)
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>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/exynos.c
arch/arm/mach-exynos/suspend.c

index 1b8699e940989b5e9f45e26650da0811f0a2e812..c93356a8d662beaeddb1f6f871455479f5f281db 100644 (file)
@@ -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);
 
index 865dcc4c3181a1e4540e094baa0ef976d876b0b5..9aa483366ebcbcde3597fe5e2a9911d2840508a4 100644 (file)
@@ -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;
        }
 
index c1e082ab2a1ee68585433db666ddf67d5e006fdb..42f36843892e8e3bc7d0a23bbec5ed9d330f3494 100644 (file)
@@ -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,10 @@ 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 +466,11 @@ 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 +670,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;
+       }
 }