]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00160513 [MX6Q]Lower SOC power in dormant
authorAnson Huang <b20788@freescale.com>
Fri, 21 Oct 2011 02:48:56 +0000 (10:48 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:16 +0000 (08:33 +0200)
Add necessary implement to lower the SOC power
when dormant, on ddr3, ARM+SOC is ~3.8mA, and
on LPDDR2, it is ~2.3mA.

Signed-off-by: Anson Huang <b20788@freescale.com>
arch/arm/mach-mx6/crm_regs.h
arch/arm/mach-mx6/pm.c
arch/arm/mach-mx6/system.c

index 03ef76648453be0d89f9ef0f2a75bc1f07b0a877..273e8d238caab6b792c12b8db36a45f19cddce64 100644 (file)
 #define MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS              (1 << 21)
 #define MXC_CCM_CLPCR_BYP_MMDC_CH0_LPM_HS              (1 << 19)
 #define MXC_CCM_CLPCR_WB_CORE_AT_LPM                   (1 << 17)
-#define MXC_CCM_CLPCR_WB_PER_AT_LPM                    (1 << 17)
+#define MXC_CCM_CLPCR_WB_PER_AT_LPM                    (1 << 16)
 #define MXC_CCM_CLPCR_COSC_PWRDOWN                     (1 << 11)
 #define MXC_CCM_CLPCR_STBY_COUNT_MASK                  (0x3 << 9)
 #define MXC_CCM_CLPCR_STBY_COUNT_OFFSET                        (9)
index 2d36c4bffbb9ab8f4ff4874253b8ba065e968922..a93963b566d157b2d68470e53cffcd0fe3ae373f 100644 (file)
@@ -46,6 +46,7 @@
 #define GPC_ISR2_OFFSET                                0x1c
 #define GPC_ISR3_OFFSET                                0x20
 #define GPC_ISR4_OFFSET                                0x24
+#define GPC_PGC_GPU_PGCR_OFFSET                0x260
 #define GPC_PGC_CPU_PDN_OFFSET         0x2a0
 #define GPC_PGC_CPU_PUPSCR_OFFSET      0x2a4
 #define GPC_PGC_CPU_PDNSCR_OFFSET      0x2a8
@@ -57,6 +58,9 @@
 #define LOCAL_TWD_COUNT_OFFSET         0x4
 #define LOCAL_TWD_CONTROL_OFFSET       0x8
 #define LOCAL_TWD_INT_OFFSET           0xc
+#define ANATOP_REG_2P5_OFFSET          0x130
+#define ANATOP_REG_CORE_OFFSET         0x140
+
 static struct clk *cpu_clk;
 static struct pm_platform_data *pm_data;
 
@@ -75,18 +79,22 @@ static void __iomem *src_base;
 static void __iomem *local_twd_base;
 static void __iomem *gic_dist_base;
 static void __iomem *gic_cpu_base;
+static void __iomem *anatop_base;
 
 static void *suspend_iram_base;
 static void (*suspend_in_iram)(suspend_state_t state,
        unsigned long iram_paddr, unsigned long suspend_iram_base) = NULL;
 static unsigned long iram_paddr, cpaddr;
 
-static u32 ccm_clpcr, scu_ctrl;
-static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu;
+static u32 ccm_ccr, ccm_clpcr, scu_ctrl;
+static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu, gpc_gpu_pgcr;
+static u32 anatop[2];
+
 
 static void mx6_suspend_store(void)
 {
        /* save some settings before suspend */
+       ccm_ccr = __raw_readl(MXC_CCM_CCR);
        ccm_clpcr = __raw_readl(MXC_CCM_CLPCR);
        scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET);
        gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET);
@@ -96,11 +104,15 @@ static void mx6_suspend_store(void)
        gpc_cpu_pup = __raw_readl(gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
        gpc_cpu_pdn = __raw_readl(gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
        gpc_cpu = __raw_readl(gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+       gpc_gpu_pgcr = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+       anatop[0] = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
+       anatop[1] = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
 }
 
 static void mx6_suspend_restore(void)
 {
        /* restore settings after suspend */
+       __raw_writel(ccm_ccr, MXC_CCM_CCR);
        __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
        __raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET);
        __raw_writel(gpc_imr[0], gpc_base + GPC_IMR1_OFFSET);
@@ -110,6 +122,9 @@ static void mx6_suspend_restore(void)
        __raw_writel(gpc_cpu_pup, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
        __raw_writel(gpc_cpu_pdn, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
        __raw_writel(gpc_cpu, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+       __raw_writel(gpc_gpu_pgcr, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+       __raw_writel(anatop[0], anatop_base + ANATOP_REG_2P5_OFFSET);
+       __raw_writel(anatop[1], anatop_base + ANATOP_REG_CORE_OFFSET);
 }
 
 static int mx6_suspend_enter(suspend_state_t state)
@@ -239,6 +254,7 @@ static int __init pm_init(void)
        gic_dist_base = IO_ADDRESS(IC_DISTRIBUTOR_BASE_ADDR);
        gic_cpu_base = IO_ADDRESS(IC_INTERFACES_BASE_ADDR);
        local_twd_base = IO_ADDRESS(LOCAL_TWD_ADDR);
+       anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR);
 
        pr_info("Static Power Management for Freescale i.MX6\n");
 
index 243152e81695aca0c8487241799d2769a4ccbaf3..db1dea5b74d1ee5c02ad948acf0df623b677f799 100644 (file)
 #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
-#define GPC_PGC_CPU_PDN_OFFSET 0x2a0
+#define SCU_CTRL                                       0x00
+#define SCU_CONFIG                                     0x04
+#define SCU_CPU_STATUS                         0x08
+#define SCU_INVALIDATE                         0x0c
+#define SCU_FPGA_REVISION                      0x10
+#define GPC_CNTR_OFFSET                                0x0
+#define GPC_PGC_GPU_PGCR_OFFSET                0x260
+#define GPC_PGC_CPU_PDN_OFFSET         0x2a0
 #define GPC_PGC_CPU_PUPSCR_OFFSET      0x2a4
 #define GPC_PGC_CPU_PDNSCR_OFFSET      0x2a8
+#define ANATOP_REG_2P5_OFFSET          0x130
+#define ANATOP_REG_CORE_OFFSET         0x140
 
 #define MODULE_CLKGATE         (1 << 30)
 #define MODULE_SFTRST          (1 << 31)
-static DEFINE_SPINLOCK(wfi_lock);
+/* static DEFINE_SPINLOCK(wfi_lock); */
 
 extern unsigned int gpc_wake_irq[4];
 
-static unsigned int cpu_idle_mask;
+/* static unsigned int cpu_idle_mask; */
 
 static void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
 
@@ -64,8 +68,10 @@ void gpc_set_wakeup(unsigned int irq[4])
 /* set cpu low power mode before WFI instruction */
 void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 {
-       u32 ccm_clpcr;
+
        int stop_mode = 0;
+       void __iomem *anatop_base = IO_ADDRESS(ANATOP_BASE_ADDR);
+       u32 ccm_clpcr, anatop_val;
 
        ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
 
@@ -116,8 +122,22 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
                __raw_writel(0xFFFFFFFF, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
 
                /* dormant mode, need to power off the arm core */
-               if (stop_mode == 2)
-                       __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+               if (stop_mode == 2) {
+                        __raw_writel(0x1, gpc_base + GPC_PGC_CPU_PDN_OFFSET);
+                       __raw_writel(0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+                       __raw_writel(0x1, gpc_base + GPC_CNTR_OFFSET);
+                       /* Enable weak 2P5 linear regulator */
+                       anatop_val = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
+                       anatop_val |= 1 << 18;
+                       __raw_writel(anatop_val, anatop_base + ANATOP_REG_2P5_OFFSET);
+                       /* Set ARM core power domain to 1V and PU domain set to off */
+                       anatop_val = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
+                       anatop_val &= 0xfffc0000;
+                       anatop_val |= 0xc;
+                       __raw_writel(anatop_val, anatop_base + ANATOP_REG_CORE_OFFSET);
+                       __raw_writel(__raw_readl(MXC_CCM_CCR) | MXC_CCM_CCR_RBC_EN, MXC_CCM_CCR);
+                       ccm_clpcr |= MXC_CCM_CLPCR_WB_PER_AT_LPM;
+               }
        }
        __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
 }