diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2011-09-20 12:18:00 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 13:00:15 +0200 |
commit | 93fa516fe114ecd72d642dd7c9c6ce682627466c (patch) | |
tree | 8c813e3532d4ab1596864fa54da3fa84caf26827 /arch | |
parent | c15dbda50368798d6b84b912dab14044e4f4ae0f (diff) |
ARM: ux500: suspend_dbg: Add debug information
Change-Id: I48792f56b4edc3fb93897d89ad18402a27652a4b
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32081
Diffstat (limited to 'arch')
-rwxr-xr-x | arch/arm/configs/u8500_defconfig | 2 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/Kconfig | 15 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/suspend.c | 34 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/suspend_dbg.c | 117 | ||||
-rw-r--r-- | arch/arm/mach-ux500/pm/suspend_dbg.h | 36 |
5 files changed, 196 insertions, 8 deletions
diff --git a/arch/arm/configs/u8500_defconfig b/arch/arm/configs/u8500_defconfig index 703fd90c966..ee86a1c4a96 100755 --- a/arch/arm/configs/u8500_defconfig +++ b/arch/arm/configs/u8500_defconfig @@ -39,6 +39,8 @@ CONFIG_DBX500_PRCMU_DEBUG=y CONFIG_UX500_SUSPEND=y CONFIG_UX500_SUSPEND_DBG=y CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART=y +CONFIG_UX500_SUSPEND_STANDBY=y +CONFIG_UX500_SUSPEND_MEM=y CONFIG_UX500_CONTEXT=y CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_STAT_DETAILS=y diff --git a/arch/arm/mach-ux500/pm/Kconfig b/arch/arm/mach-ux500/pm/Kconfig index cc71c775f7c..9df7848caa0 100644 --- a/arch/arm/mach-ux500/pm/Kconfig +++ b/arch/arm/mach-ux500/pm/Kconfig @@ -26,9 +26,22 @@ config UX500_SUSPEND help Add support for suspend. +config UX500_SUSPEND_STANDBY + bool "Suspend Standby goes to ApSleep" + depends on UX500_SUSPEND + help + If yes, echo standby > /sys/power/state puts the system into ApSleep. + +config UX500_SUSPEND_MEM + bool "Suspend Mem goes to ApDeepSleep" + depends on UX500_SUSPEND + help + If yes, echo mem > /sys/power/state puts the system into ApDeepSleep else + it will do the same as echo standby > /sys/power/state. + config UX500_SUSPEND_DBG bool "Suspend debug" - depends on UX500_SUSPEND + depends on UX500_SUSPEND && DEBUG_FS help Add debug support for suspend. diff --git a/arch/arm/mach-ux500/pm/suspend.c b/arch/arm/mach-ux500/pm/suspend.c index f1b23529877..7189554eab8 100644 --- a/arch/arm/mach-ux500/pm/suspend.c +++ b/arch/arm/mach-ux500/pm/suspend.c @@ -125,12 +125,31 @@ exit: static int ux500_suspend_enter(suspend_state_t state) { - if (state == PM_SUSPEND_MEM) - return suspend(true); - else if (state == PM_SUSPEND_STANDBY) - return suspend(false); - else - return -EINVAL; + if (ux500_suspend_enabled()) { + if (ux500_suspend_deepsleep_enabled() && + state == PM_SUSPEND_MEM) + return suspend(true); + if (ux500_suspend_sleep_enabled()) + return suspend(false); + } + + ux500_suspend_dbg_add_wake_on_uart(); + /* + * Set IOFORCE in order to wake on GPIO the same way + * as in deeper sleep. + * (U5500 is not ready for IOFORCE) + */ + if (!cpu_is_u5500()) + ux500_pm_prcmu_set_ioforce(true); + + dsb(); + __asm__ __volatile__("wfi\n\t" : : : "memory"); + + if (!cpu_is_u5500()) + ux500_pm_prcmu_set_ioforce(false); + ux500_suspend_dbg_remove_wake_on_uart(); + + return 0; } static int ux500_suspend_valid(suspend_state_t state) @@ -154,7 +173,7 @@ static int ux500_suspend_begin(suspend_state_t state) { (void) prcmu_qos_update_requirement(PRCMU_QOS_ARM_OPP, "suspend", 100); - return 0; + return ux500_suspend_dbg_begin(state); } static void ux500_suspend_end(void) @@ -174,6 +193,7 @@ static struct platform_suspend_ops ux500_suspend_ops = { static __init int ux500_suspend_init(void) { + ux500_suspend_dbg_init(); prcmu_qos_add_requirement(PRCMU_QOS_ARM_OPP, "suspend", 25); suspend_set_ops(&ux500_suspend_ops); return 0; diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.c b/arch/arm/mach-ux500/pm/suspend_dbg.c index 301383a5ab9..cd058bad91e 100644 --- a/arch/arm/mach-ux500/pm/suspend_dbg.c +++ b/arch/arm/mach-ux500/pm/suspend_dbg.c @@ -11,9 +11,33 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/gpio.h> +#include <linux/suspend.h> +#include <linux/debugfs.h> +#include <linux/seq_file.h> +#include <linux/uaccess.h> #include <mach/pm.h> +#ifdef CONFIG_UX500_SUSPEND_STANDBY +static u32 sleep_enabled = 1; +#else +static u32 sleep_enabled; +#endif + +#ifdef CONFIG_UX500_SUSPEND_MEM +static u32 deepsleep_enabled = 1; +#else +static u32 deepsleep_enabled; +#endif + +static u32 suspend_enabled = 1; + +static u32 deepsleeps_done; +static u32 deepsleeps_failed; +static u32 sleeps_done; +static u32 sleeps_failed; +static u32 suspend_count; + #ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART void ux500_suspend_dbg_add_wake_on_uart(void) { @@ -28,6 +52,21 @@ void ux500_suspend_dbg_remove_wake_on_uart(void) } #endif +bool ux500_suspend_enabled(void) +{ + return suspend_enabled != 0; +} + +bool ux500_suspend_sleep_enabled(void) +{ + return sleep_enabled != 0; +} + +bool ux500_suspend_deepsleep_enabled(void) +{ + return deepsleep_enabled != 0; +} + void ux500_suspend_dbg_sleep_status(bool is_deepsleep) { enum prcmu_idle_stat prcmu_status; @@ -38,9 +77,87 @@ void ux500_suspend_dbg_sleep_status(bool is_deepsleep) pr_info("Returning from ApDeepSleep. PRCMU ret: 0x%x - %s\n", prcmu_status, prcmu_status == DEEP_SLEEP_OK ? "Success" : "Fail!"); + if (prcmu_status == DEEP_SLEEP_OK) + deepsleeps_done++; + else + deepsleeps_failed++; } else { pr_info("Returning from ApSleep. PRCMU ret: 0x%x - %s\n", prcmu_status, prcmu_status == SLEEP_OK ? "Success" : "Fail!"); + if (prcmu_status == SLEEP_OK) + sleeps_done++; + else + sleeps_failed++; } } + +int ux500_suspend_dbg_begin(suspend_state_t state) +{ + suspend_count++; + return 0; +} + +void ux500_suspend_dbg_init(void) +{ + struct dentry *suspend_dir; + struct dentry *file; + + suspend_dir = debugfs_create_dir("suspend", NULL); + if (IS_ERR_OR_NULL(suspend_dir)) + return; + + file = debugfs_create_bool("sleep", S_IWUGO | S_IRUGO, + suspend_dir, + &sleep_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_bool("deepsleep", S_IWUGO | S_IRUGO, + suspend_dir, + &deepsleep_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_bool("enable", S_IWUGO | S_IRUGO, + suspend_dir, + &suspend_enabled); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("count", S_IRUGO, + suspend_dir, + &suspend_count); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("sleep_count", S_IRUGO, + suspend_dir, + &sleeps_done); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("deepsleep_count", S_IRUGO, + suspend_dir, + &deepsleeps_done); + if (IS_ERR_OR_NULL(file)) + goto error; + + + file = debugfs_create_u32("sleep_failed", S_IRUGO, + suspend_dir, + &sleeps_failed); + if (IS_ERR_OR_NULL(file)) + goto error; + + file = debugfs_create_u32("deepsleep_failed", S_IRUGO, + suspend_dir, + &deepsleeps_failed); + if (IS_ERR_OR_NULL(file)) + goto error; + + return; +error: + if (!IS_ERR_OR_NULL(suspend_dir)) + debugfs_remove_recursive(suspend_dir); +} diff --git a/arch/arm/mach-ux500/pm/suspend_dbg.h b/arch/arm/mach-ux500/pm/suspend_dbg.h index dd0b27ff963..29bfec7e269 100644 --- a/arch/arm/mach-ux500/pm/suspend_dbg.h +++ b/arch/arm/mach-ux500/pm/suspend_dbg.h @@ -10,6 +10,9 @@ #ifndef UX500_SUSPEND_DBG_H #define UX500_SUSPEND_DBG_H +#include <linux/kernel.h> +#include <linux/suspend.h> + #ifdef CONFIG_UX500_SUSPEND_DBG_WAKE_ON_UART void ux500_suspend_dbg_add_wake_on_uart(void); void ux500_suspend_dbg_remove_wake_on_uart(void); @@ -19,9 +22,42 @@ static inline void ux500_suspend_dbg_remove_wake_on_uart(void) { } #endif #ifdef CONFIG_UX500_SUSPEND_DBG +bool ux500_suspend_enabled(void); +bool ux500_suspend_sleep_enabled(void); +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); + +#else +static inline bool ux500_suspend_enabled(void) +{ + return true; +} +static inline bool ux500_suspend_sleep_enabled(void) +{ +#ifdef CONFIG_UX500_SUSPEND_STANDBY + return true; +#else + return false; +#endif +} +static inline bool ux500_suspend_deepsleep_enabled(void) +{ +#ifdef CONFIG_UX500_SUSPEND_MEM + return true; #else + return false; +#endif +} static inline void ux500_suspend_dbg_sleep_status(bool is_deepsleep) { } +static inline void ux500_suspend_dbg_init(void) { } + +static inline int ux500_suspend_dbg_begin(suspend_state_t state) +{ + return 0; +} + #endif #endif |