summaryrefslogtreecommitdiff
path: root/arch/arm/mach-ux500/pm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-ux500/pm')
-rw-r--r--arch/arm/mach-ux500/pm/suspend.c4
-rw-r--r--arch/arm/mach-ux500/pm/suspend_dbg.c80
-rw-r--r--arch/arm/mach-ux500/pm/suspend_dbg.h13
3 files changed, 96 insertions, 1 deletions
diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c
index df527964182..9dd4d86a2f3 100644
--- a/arch/arm/mach-ux500/pm/suspend.c
+++ b/arch/arm/mach-ux500/pm/suspend.c
@@ -76,6 +76,8 @@ static int suspend(bool do_deepsleep)
prcmu_enable_wakeups(PRCMU_WAKEUP(ABB));
#endif
+ ux500_suspend_dbg_test_set_wakeup();
+
context_vape_save();
context_fsmc_save();
@@ -258,6 +260,8 @@ static void ux500_suspend_end(void)
(void) prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP,
"suspend", 25);
suspend_state = PM_SUSPEND_ON;
+
+ ux500_suspend_dbg_end();
}
static struct platform_suspend_ops ux500_suspend_ops = {
diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.c b/arch/arm/mach-ux500/pm/suspend_dbg.c
index 1b7d871ba52..68afa96e547 100644
--- a/arch/arm/mach-ux500/pm/suspend_dbg.c
+++ b/arch/arm/mach-ux500/pm/suspend_dbg.c
@@ -14,10 +14,16 @@
#include <linux/suspend.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/wakelock.h>
#include <mach/pm.h>
+#include <mach/pm-timer.h>
+
+/* To reach main_wake_lock */
+#include "../../../../kernel/power/power.h"
#ifdef CONFIG_UX500_SUSPEND_STANDBY
static u32 sleep_enabled = 1;
@@ -100,6 +106,79 @@ int ux500_suspend_dbg_begin(suspend_state_t state)
return 0;
}
+/* The number of failed suspend attempts in a row before giving up */
+#define TEST_FAILS 10
+
+static int suspend_test_count;
+static int suspend_test_current;
+static int suspend_test_fail_count;
+
+void ux500_suspend_dbg_test_set_wakeup(void)
+{
+ if (suspend_test_count == 0)
+ return;
+
+ ux500_rtcrtt_off();
+
+ /* Make sure the rtc writes have been accepted */
+ udelay(120);
+
+ if (cpu_is_u9500())
+ prcmu_enable_wakeups(PRCMU_WAKEUP(ABB) | PRCMU_WAKEUP(RTC) |
+ PRCMU_WAKEUP(HSI0));
+ else
+ prcmu_enable_wakeups(PRCMU_WAKEUP(ABB) | PRCMU_WAKEUP(RTC));
+
+ /* Program RTC to generate an interrupt 1s later */
+ ux500_rtcrtt_next(1000000);
+}
+
+void ux500_suspend_dbg_test_start(int num)
+{
+ suspend_test_count = num;
+ suspend_test_current = deepsleeps_done;
+ suspend_test_fail_count = 0;
+}
+
+bool ux500_suspend_test_success(bool *ongoing)
+{
+ (*ongoing) = ((suspend_test_fail_count < TEST_FAILS) &&
+ (suspend_test_count > 0));
+ return suspend_test_fail_count < TEST_FAILS;
+}
+
+void ux500_suspend_dbg_end(void)
+{
+ static int attempts;
+
+ if (suspend_test_count > 0) {
+ attempts++;
+ pr_info("Suspend test: %d done\n", attempts);
+ suspend_test_count--;
+ wake_lock(&main_wake_lock);
+
+ if (suspend_test_current < deepsleeps_done) {
+ suspend_test_current = deepsleeps_done;
+ suspend_test_fail_count = 0;
+ } else {
+ suspend_test_fail_count++;
+ }
+
+ if (suspend_test_fail_count > TEST_FAILS) {
+ suspend_test_count = 0;
+ pr_err("suspend: Aborting after %d "
+ "failed suspend in a row\n",
+ TEST_FAILS);
+ } else if (suspend_test_count > 0) {
+ msleep(100);
+ wake_unlock(&main_wake_lock);
+ }
+
+ if (suspend_test_count == 0)
+ attempts = 0;
+ }
+}
+
void ux500_suspend_dbg_init(void)
{
struct dentry *suspend_dir;
@@ -145,7 +224,6 @@ void ux500_suspend_dbg_init(void)
if (IS_ERR_OR_NULL(file))
goto error;
-
file = debugfs_create_u32("sleep_failed", S_IRUGO,
suspend_dir,
&sleeps_failed);
diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.h b/arch/arm/mach-ux500/pm/suspend_dbg.h
index 29bfec7e269..1e45fa05e5e 100644
--- a/arch/arm/mach-ux500/pm/suspend_dbg.h
+++ b/arch/arm/mach-ux500/pm/suspend_dbg.h
@@ -28,6 +28,10 @@ bool ux500_suspend_deepsleep_enabled(void);
void ux500_suspend_dbg_sleep_status(bool is_deepsleep);
void ux500_suspend_dbg_init(void);
int ux500_suspend_dbg_begin(suspend_state_t state);
+void ux500_suspend_dbg_end(void);
+void ux500_suspend_dbg_test_set_wakeup(void);
+void ux500_suspend_dbg_test_start(int num);
+bool ux500_suspend_test_success(bool *ongoing);
#else
static inline bool ux500_suspend_enabled(void)
@@ -57,6 +61,15 @@ static inline int ux500_suspend_dbg_begin(suspend_state_t state)
{
return 0;
}
+static inline void ux500_suspend_dbg_end(void) { }
+static inline void ux500_suspend_dbg_test_set_wakeup(void) { }
+static inline void ux500_suspend_dbg_test_start(int num)
+{ }
+static inline bool ux500_suspend_test_success(bool *ongoing)
+{
+ (*ongoing) = false;
+ return false;
+}
#endif