diff options
author | Anson Huang <b20788@freescale.com> | 2011-07-18 12:54:13 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-07-20 13:14:47 +0800 |
commit | 683b3c5bbb377e08043c814da860677b03815452 (patch) | |
tree | 11f09f5b8c6dfe6a457ec6103b456ca2b6778ff6 /arch/arm/mach-mx6/system.c | |
parent | e1425efa1589cb97347f3195b018163665d2fc52 (diff) |
ENGR00139274-1 [MX6]Enable suspend/resume feature
Enable suspend/resume feature for MX6q
echo standby > /sys/power/state -> wait mode;
echo mem > /sys/power/state -> stop mode;
Currentlu only support debug uart as wakeup source;
Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch/arm/mach-mx6/system.c')
-rw-r--r-- | arch/arm/mach-mx6/system.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index ba4091e9d285..f18389bf26da 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -26,6 +26,86 @@ #include <mach/clock.h> #include <asm/proc-fns.h> #include <asm/system.h> +#include "crm_regs.h" + +#define SCU_CTRL 0x00 +#define SCU_CONFIG 0x04 +#define SCU_CPU_STATUS 0x08 +#define SCU_INVALIDATE 0x0c +#define SCU_FPGA_REVISION 0x10 + +void gpc_enable_wakeup(unsigned int irq) +{ + void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); + + if ((irq < 32) || (irq > 158)) + printk(KERN_ERR "Invalid irq number!\n"); + + /* Enable wake up source */ + __raw_writel(~(1 << (irq % 32)), + gpc_base + 0x8 + (irq / 32 - 1) * 4); + +} +/* set cpu low power mode before WFI instruction */ +void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode) +{ + void __iomem *scu_base = IO_ADDRESS(SCU_BASE_ADDR); + void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR); + u32 scu_cr, ccm_clpcr; + int stop_mode = 0; + + scu_cr = __raw_readl(scu_base + SCU_CTRL); + ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK); + + switch (mode) { + case WAIT_CLOCKED: + break; + case WAIT_UNCLOCKED: + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + case WAIT_UNCLOCKED_POWER_OFF: + case STOP_POWER_OFF: + if (mode == WAIT_UNCLOCKED_POWER_OFF) { + ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY; + ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS; + stop_mode = 0; + } else { + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET; + ccm_clpcr |= MXC_CCM_CLPCR_VSTBY; + ccm_clpcr |= MXC_CCM_CLPCR_SBYOS; + ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS; + stop_mode = 1; + } + /* scu standby enable, scu clk will be + * off after all cpu enter WFI */ + scu_cr |= 0x20; + break; + case STOP_POWER_ON: + ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET; + break; + default: + printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode); + return; + } + + if (stop_mode == 1) { + /* Mask all wake up source */ + __raw_writel(0xFFFFFFFF, gpc_base + 0x8); + __raw_writel(0xFFFFFFFF, gpc_base + 0xC); + __raw_writel(0xFFFFFFFF, gpc_base + 0x10); + __raw_writel(0xFFFFFFFF, gpc_base + 0x14); + /* Power down and power up sequence */ + __raw_writel(0xFFFFFFFF, gpc_base + 0x2a4); + __raw_writel(0xFFFFFFFF, gpc_base + 0x2a8); + + gpc_enable_wakeup(MXC_INT_UART4_ANDED); + } + + __raw_writel(scu_cr, scu_base + SCU_CTRL); + __raw_writel(ccm_clpcr, MXC_CCM_CLPCR); +} void arch_idle(void) { |