summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-exynos/suspend.c
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <krzk@kernel.org>2018-07-24 18:49:46 +0200
committerKrzysztof Kozlowski <krzk@kernel.org>2018-08-30 19:46:06 +0200
commite0b35c1ab5ac5f0453d1093770e119bd8d63d85c (patch)
tree172714124cdb99984c35b6b1d98a18cb27d06210 /arch/arm/mach-exynos/suspend.c
parentARM: exynos: Store Exynos5420 register state in one variable (diff)
downloadlinux-e0b35c1ab5ac5f0453d1093770e119bd8d63d85c.tar.xz
linux-e0b35c1ab5ac5f0453d1093770e119bd8d63d85c.zip
ARM: exynos: Fix imprecise abort during Exynos5422 suspend to RAM
Suspend to RAM on Odroid XU3/XU4/HC1 family (Exynos5422) causes imprecise abort: PM: Syncing filesystems ... done. Freezing user space processes ... (elapsed 0.003 seconds) done. OOM killer disabled. Freezing remaining freezable tasks ... (elapsed 0.003 seconds) done. wake enabled for irq 139 Disabling non-boot CPUs ... IRQ51 no longer affine to CPU1 IRQ52 no longer affine to CPU2 IRQ53 no longer affine to CPU3 IRQ54 no longer affine to CPU4 IRQ55 no longer affine to CPU5 IRQ56 no longer affine to CPU6 cpu cpu4: Dropping the link to regulator.40 IRQ57 no longer affine to CPU7 Unhandled fault: external abort on non-linefetch (0x1008) at 0xf081a028 Internal error: : 1008 [#1] PREEMPT SMP ARM with last call trace in exynos_suspend_enter(). The abort is caused by writing to register in secure part of sysram. Boards booted under secure firmware (e.g. Hardkernel Odroid boards) should access non-secure sysram. Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
Diffstat (limited to 'arch/arm/mach-exynos/suspend.c')
-rw-r--r--arch/arm/mach-exynos/suspend.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index 700d8d91ea93..bb8e3985acdb 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -63,6 +63,7 @@ struct exynos_pm_data {
struct exynos_pm_state {
int cpu_state;
unsigned int pmu_spare3;
+ void __iomem *sysram_base;
};
static const struct exynos_pm_data *pm_data __ro_after_init;
@@ -261,7 +262,7 @@ static int exynos5420_cpu_suspend(unsigned long arg)
unsigned int cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
unsigned int cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
- writel_relaxed(0x0, sysram_base_addr + EXYNOS5420_CPU_STATE);
+ writel_relaxed(0x0, pm_state.sysram_base + EXYNOS5420_CPU_STATE);
if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) {
mcpm_set_entry_vector(cpu, cluster, exynos_cpu_resume);
@@ -333,7 +334,7 @@ static void exynos5420_pm_prepare(void)
* needs to restore it back in case, the primary cpu fails to
* suspend for any reason.
*/
- pm_state.cpu_state = readl_relaxed(sysram_base_addr +
+ pm_state.cpu_state = readl_relaxed(pm_state.sysram_base +
EXYNOS5420_CPU_STATE);
exynos_pm_enter_sleep_mode();
@@ -453,7 +454,7 @@ static void exynos5420_pm_resume(void)
/* Restore the sysram cpu state register */
writel_relaxed(pm_state.cpu_state,
- sysram_base_addr + EXYNOS5420_CPU_STATE);
+ pm_state.sysram_base + EXYNOS5420_CPU_STATE);
pmu_raw_writel(EXYNOS5420_USE_STANDBY_WFI_ALL,
S5P_CENTRAL_SEQ_OPTION);
@@ -658,4 +659,13 @@ void __init exynos_pm_init(void)
register_syscore_ops(&exynos_pm_syscore_ops);
suspend_set_ops(&exynos_suspend_ops);
+
+ /*
+ * 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())
+ pm_state.sysram_base = sysram_ns_base_addr;
+ else
+ pm_state.sysram_base = sysram_base_addr;
}