summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-06-23 16:42:44 +0800
committerShawn Guo <shawn.guo@freescale.com>2014-07-18 16:11:30 +0800
commit80c0ecdce802bd642dc7127cc77cea04e0a71bf5 (patch)
treed132b17db6e55bbf0539aa78ce137bbc44890273 /arch
parentdfea953ae221111c14d2fcfebad7b1973a0f49bd (diff)
downloadtalos-obmc-linux-80c0ecdce802bd642dc7127cc77cea04e0a71bf5.tar.gz
talos-obmc-linux-80c0ecdce802bd642dc7127cc77cea04e0a71bf5.zip
ARM: imx: add standby mode support for suspend
Add standby mode support for suspend, to enter standby mode: echo standby > /sys/power/state; Use UART or RTC alarm to wake up system, when system enters standby mode, SOC will enter STOP mode with ARM core kept power on and 24M XTAL on. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/common.h2
-rw-r--r--arch/arm/mach-imx/gpc.c5
-rw-r--r--arch/arm/mach-imx/pm-imx6.c30
3 files changed, 32 insertions, 5 deletions
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 13a6e1f8e11e..d205f362cf29 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -106,7 +106,7 @@ static inline void imx_scu_standby_enable(void) {}
#endif
void imx_src_init(void);
void imx_gpc_init(void);
-void imx_gpc_pre_suspend(void);
+void imx_gpc_pre_suspend(bool arm_power_off);
void imx_gpc_post_resume(void);
void imx_gpc_mask_all(void);
void imx_gpc_restore_all(void);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 586e0171a652..82ea74e68482 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -27,13 +27,14 @@ static void __iomem *gpc_base;
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
-void imx_gpc_pre_suspend(void)
+void imx_gpc_pre_suspend(bool arm_power_off)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Tell GPC to power off ARM core when suspend */
- writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
+ if (arm_power_off)
+ writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
for (i = 0; i < IMR_NUM; i++) {
gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index b3c770d0cc3f..5c3af8f993d0 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -274,6 +274,14 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
break;
case STOP_POWER_ON:
val |= 0x2 << BP_CLPCR_LPM;
+ val &= ~BM_CLPCR_VSTBY;
+ val &= ~BM_CLPCR_SBYOS;
+ if (cpu_is_imx6sl())
+ val |= BM_CLPCR_BYPASS_PMIC_READY;
+ if (cpu_is_imx6sl() || cpu_is_imx6sx())
+ val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+ else
+ val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
break;
case WAIT_UNCLOCKED_POWER_OFF:
val |= 0x1 << BP_CLPCR_LPM;
@@ -334,6 +342,19 @@ static int imx6q_suspend_finish(unsigned long val)
static int imx6q_pm_enter(suspend_state_t state)
{
switch (state) {
+ case PM_SUSPEND_STANDBY:
+ imx6q_set_lpm(STOP_POWER_ON);
+ imx6q_set_int_mem_clk_lpm(true);
+ imx_gpc_pre_suspend(false);
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(true);
+ /* Zzz ... */
+ cpu_do_idle();
+ if (cpu_is_imx6sl())
+ imx6sl_set_wait_clk(false);
+ imx_gpc_post_resume();
+ imx6q_set_lpm(WAIT_CLOCKED);
+ break;
case PM_SUSPEND_MEM:
imx6q_set_lpm(STOP_POWER_OFF);
imx6q_set_int_mem_clk_lpm(false);
@@ -344,7 +365,7 @@ static int imx6q_pm_enter(suspend_state_t state)
*/
if (!imx6_suspend_in_ocram_fn)
imx6q_enable_rbc(true);
- imx_gpc_pre_suspend();
+ imx_gpc_pre_suspend(true);
imx_anatop_pre_suspend();
imx_set_cpu_jump(0, v7_cpu_resume);
/* Zzz ... */
@@ -365,9 +386,14 @@ static int imx6q_pm_enter(suspend_state_t state)
return 0;
}
+static int imx6q_pm_valid(suspend_state_t state)
+{
+ return (state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM);
+}
+
static const struct platform_suspend_ops imx6q_pm_ops = {
.enter = imx6q_pm_enter,
- .valid = suspend_valid_only_mem,
+ .valid = imx6q_pm_valid,
};
void __init imx6q_pm_set_ccm_base(void __iomem *base)
OpenPOWER on IntegriCloud