summaryrefslogtreecommitdiff
path: root/arch/arm/mach-exynos/pm.c
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2014-03-18 07:28:27 +0900
committerKukjin Kim <kgene.kim@samsung.com>2014-03-21 04:09:28 +0900
commitd710aa31874e2ff6e656dbd4807f4bd8d659eb93 (patch)
treeb897e022fd8d9579acaabc318a2bffd0c55c1f2e /arch/arm/mach-exynos/pm.c
parent559ba237999d723ccba5b4a75cf6b280bac1ab21 (diff)
ARM: EXYNOS: Stop using legacy Samsung PM code
Since Exynos SoCs does not follow most of the semantics of older SoCs when configuring the system to enter sleep, there is no reason to rely on the legacy Samsung PM core anymore. This patch adds local Exynos suspend ops and removes all the code left unnecessary. As a side effect, suspend support on Exynos becomes multiplatform-friendly. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos/pm.c')
-rw-r--r--arch/arm/mach-exynos/pm.c79
1 files changed, 71 insertions, 8 deletions
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index 596ed13c4166..ada1c8374b77 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -23,14 +23,14 @@
#include <asm/cacheflush.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/smp_scu.h>
+#include <asm/suspend.h>
#include <plat/cpu.h>
-#include <plat/pm.h>
+#include <plat/pm-common.h>
#include <plat/pll.h>
#include <plat/regs-srom.h>
#include <mach/map.h>
-#include <mach/pm-core.h>
#include "common.h"
#include "regs-pmu.h"
@@ -48,6 +48,7 @@ static struct sleep_save exynos_core_save[] = {
SAVE_ITEM(S5P_SROM_BC3),
};
+static u32 exynos_irqwake_intmask = 0xffffffff;
/* For Cortex-A9 Diagnostic and Power control register */
static unsigned int save_arm_register[2];
@@ -72,6 +73,10 @@ static void exynos_pm_prepare(void)
{
unsigned int tmp;
+ /* Set wake-up mask registers */
+ __raw_writel(exynos_get_eint_wake_mask(), S5P_EINT_WAKEUP_MASK);
+ __raw_writel(exynos_irqwake_intmask & ~(1 << 31), S5P_WAKEUP_MASK);
+
s3c_pm_do_save(exynos_core_save, ARRAY_SIZE(exynos_core_save));
if (soc_is_exynos5250()) {
@@ -89,7 +94,7 @@ static void exynos_pm_prepare(void)
/* ensure at least INFORM0 has the resume address */
- __raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+ __raw_writel(virt_to_phys(exynos_cpu_resume), S5P_INFORM0);
}
static int exynos_pm_suspend(void)
@@ -187,14 +192,71 @@ static struct syscore_ops exynos_pm_syscore_ops = {
.resume = exynos_pm_resume,
};
-void __init exynos_pm_init(void)
+/*
+ * Suspend Ops
+ */
+
+static int exynos_suspend_enter(suspend_state_t state)
{
- u32 tmp;
+ int ret;
+
+ s3c_pm_debug_init();
+
+ S3C_PMDBG("%s: suspending the system...\n", __func__);
+
+ S3C_PMDBG("%s: wakeup masks: %08x,%08x\n", __func__,
+ exynos_irqwake_intmask, exynos_get_eint_wake_mask());
- pm_cpu_prep = exynos_pm_prepare;
- pm_cpu_sleep = exynos_cpu_suspend;
+ if (exynos_irqwake_intmask == -1U
+ && exynos_get_eint_wake_mask() == -1U) {
+ pr_err("%s: No wake-up sources!\n", __func__);
+ pr_err("%s: Aborting sleep\n", __func__);
+ return -EINVAL;
+ }
+
+ s3c_pm_save_uarts();
+ exynos_pm_prepare();
+ flush_cache_all();
+ s3c_pm_check_store();
+
+ ret = cpu_suspend(0, exynos_cpu_suspend);
+ if (ret)
+ return ret;
+
+ s3c_pm_restore_uarts();
- s3c_pm_init();
+ S3C_PMDBG("%s: wakeup stat: %08x\n", __func__,
+ __raw_readl(S5P_WAKEUP_STAT));
+
+ s3c_pm_check_restore();
+
+ S3C_PMDBG("%s: resuming the system...\n", __func__);
+
+ return 0;
+}
+
+static int exynos_suspend_prepare(void)
+{
+ s3c_pm_check_prepare();
+
+ return 0;
+}
+
+static void exynos_suspend_finish(void)
+{
+ s3c_pm_check_cleanup();
+}
+
+static const struct platform_suspend_ops exynos_suspend_ops = {
+ .enter = exynos_suspend_enter,
+ .prepare = exynos_suspend_prepare,
+ .finish = exynos_suspend_finish,
+ .valid = suspend_valid_only_mem,
+};
+
+void __init exynos_pm_init(void)
+{
+ u32 tmp;
/* All wakeup disable */
tmp = __raw_readl(S5P_WAKEUP_MASK);
@@ -202,4 +264,5 @@ void __init exynos_pm_init(void)
__raw_writel(tmp, S5P_WAKEUP_MASK);
register_syscore_ops(&exynos_pm_syscore_ops);
+ suspend_set_ops(&exynos_suspend_ops);
}