Commit 3a1f2f38 authored by Joonyoung Shim's avatar Joonyoung Shim Committed by Krzysztof Kozlowski

ARM: exynos: Add CPU state management for Exynos542x under secure firmware

Add required CPU state management done via secure monitor call for
Exynos542x running unsed Secure Firmware.
Signed-off-by: default avatarJoonyoung 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: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarKrzysztof Kozlowski <krzk@kernel.org>
parent 47efaf6b
...@@ -91,6 +91,7 @@ extern u32 cp15_save_power; ...@@ -91,6 +91,7 @@ extern u32 cp15_save_power;
extern void __iomem *sysram_ns_base_addr; extern void __iomem *sysram_ns_base_addr;
extern void __iomem *sysram_base_addr; extern void __iomem *sysram_base_addr;
extern phys_addr_t sysram_base_phys;
extern void __iomem *pmu_base_addr; extern void __iomem *pmu_base_addr;
void exynos_sysram_init(void); void exynos_sysram_init(void);
......
...@@ -33,6 +33,7 @@ static struct platform_device exynos_cpuidle = { ...@@ -33,6 +33,7 @@ static struct platform_device exynos_cpuidle = {
}; };
void __iomem *sysram_base_addr __ro_after_init; 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 __iomem *sysram_ns_base_addr __ro_after_init;
void __init exynos_sysram_init(void) void __init exynos_sysram_init(void)
...@@ -43,6 +44,8 @@ void __init exynos_sysram_init(void) ...@@ -43,6 +44,8 @@ void __init exynos_sysram_init(void)
if (!of_device_is_available(node)) if (!of_device_is_available(node))
continue; continue;
sysram_base_addr = of_iomap(node, 0); sysram_base_addr = of_iomap(node, 0);
sysram_base_phys = of_translate_address(node,
of_get_address(node, 0, NULL, NULL));
break; break;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <asm/suspend.h> #include <asm/suspend.h>
#include "common.h" #include "common.h"
#include "smc.h"
#define REG_TABLE_END (-1U) #define REG_TABLE_END (-1U)
...@@ -62,6 +63,8 @@ struct exynos_pm_state { ...@@ -62,6 +63,8 @@ struct exynos_pm_state {
int cpu_state; int cpu_state;
unsigned int pmu_spare3; unsigned int pmu_spare3;
void __iomem *sysram_base; void __iomem *sysram_base;
phys_addr_t sysram_phys;
bool secure_firmware;
}; };
static const struct exynos_pm_data *pm_data __ro_after_init; static const struct exynos_pm_data *pm_data __ro_after_init;
...@@ -340,6 +343,10 @@ static void exynos5420_pm_prepare(void) ...@@ -340,6 +343,10 @@ static void exynos5420_pm_prepare(void)
pm_state.cpu_state = readl_relaxed(pm_state.sysram_base + pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
EXYNOS5420_CPU_STATE); EXYNOS5420_CPU_STATE);
writel_relaxed(0x0, 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(); exynos_pm_enter_sleep_mode();
...@@ -459,6 +466,11 @@ static void exynos5420_pm_resume(void) ...@@ -459,6 +466,11 @@ static void exynos5420_pm_resume(void)
/* Restore the sysram cpu state register */ /* Restore the sysram cpu state register */
writel_relaxed(pm_state.cpu_state, writel_relaxed(pm_state.cpu_state,
pm_state.sysram_base + EXYNOS5420_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, pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
S5P_CENTRAL_SEQ_OPTION); S5P_CENTRAL_SEQ_OPTION);
...@@ -658,8 +670,11 @@ void __init exynos_pm_init(void) ...@@ -658,8 +670,11 @@ void __init exynos_pm_init(void)
* Applicable as of now only to Exynos542x. If booted under secure * Applicable as of now only to Exynos542x. If booted under secure
* firmware, the non-secure region of sysram should be used. * 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; pm_state.sysram_base = sysram_ns_base_addr;
else pm_state.secure_firmware = true;
} else {
pm_state.sysram_base = sysram_base_addr; pm_state.sysram_base = sysram_base_addr;
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment