summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6/system.c
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2011-07-18 12:54:13 +0800
committerJason Liu <r64343@freescale.com>2012-07-20 13:14:47 +0800
commit683b3c5bbb377e08043c814da860677b03815452 (patch)
tree11f09f5b8c6dfe6a457ec6103b456ca2b6778ff6 /arch/arm/mach-mx6/system.c
parente1425efa1589cb97347f3195b018163665d2fc52 (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.c80
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)
{