summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Zhao <richard.zhao@freescale.com>2011-11-24 11:34:28 +0800
committerJason Liu <r64343@freescale.com>2012-01-09 21:08:16 +0800
commit69ff52ba61fd3163f95b92297fa1ee110e6f2e8b (patch)
tree0b5e9bf3ce7c0022cefef1426bbcda8aeda0cc14
parent33024e254a8acdfb3c57eb4e81f59a6bcead9f77 (diff)
ENGR00163057 ARM: imx6q: add gpu suspend/resume support
GPU power down/up follow a restrict process. Signed-off-by: Richard Zhao <richard.zhao@freescale.com>
-rw-r--r--arch/arm/mach-mx6/pm.c65
-rw-r--r--arch/arm/mach-mx6/system.c4
2 files changed, 60 insertions, 9 deletions
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
index df0f06e76882..bdf337144554 100644
--- a/arch/arm/mach-mx6/pm.c
+++ b/arch/arm/mach-mx6/pm.c
@@ -11,6 +11,7 @@
* http://www.gnu.org/copyleft/gpl.html
*/
#include <linux/module.h>
+#include <linux/delay.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -46,6 +47,7 @@
#define GPC_ISR2_OFFSET 0x1c
#define GPC_ISR3_OFFSET 0x20
#define GPC_ISR4_OFFSET 0x24
+#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
@@ -87,8 +89,51 @@ static void (*suspend_in_iram)(suspend_state_t state,
static unsigned long iram_paddr, cpaddr;
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 u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn, gpc_cpu, gpc_ctr;
+static u32 anatop[2], ccgr1, ccgr6;
+
+static void gpu_power_down(void)
+{
+ int reg;
+
+ /* enable power down request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power down request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
+ /* disable clocks */
+ __raw_writel(ccgr1 & 0xf0ffffff, MXC_CCM_CCGR1);
+ __raw_writel(ccgr6 & 0x00003fff, MXC_CCM_CCGR6);
+ /* power off pu */
+ reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
+ reg &= ~0x0003fe00;
+ __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
+}
+
+static void gpu_power_up(void)
+{
+ int reg;
+ /* power on pu */
+ reg = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
+ reg &= ~0x0003fe00;
+ reg |= 0x10 << 9; /* 1.1v */
+ __raw_writel(reg, anatop_base + ANATOP_REG_CORE_OFFSET);
+ mdelay(10);
+
+ /* enable clocks */
+ __raw_writel(ccgr1 | 0x0f000000, MXC_CCM_CCGR1);
+ __raw_writel(ccgr6 | 0x0000c000, MXC_CCM_CCGR6);
+
+ /* enable power up request */
+ reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+ /* power up request */
+ reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+ __raw_writel(reg | 0x2, gpc_base + GPC_CNTR_OFFSET);
+ udelay(10);
+}
+
static void mx6_suspend_store(void)
@@ -96,6 +141,8 @@ 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);
+ ccgr1 = __raw_readl(MXC_CCM_CCGR1);
+ ccgr6 = __raw_readl(MXC_CCM_CCGR6);
scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET);
gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET);
gpc_imr[1] = __raw_readl(gpc_base + GPC_IMR2_OFFSET);
@@ -104,7 +151,7 @@ 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);
+ gpc_ctr = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
anatop[0] = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
anatop[1] = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
}
@@ -112,6 +159,9 @@ static void mx6_suspend_store(void)
static void mx6_suspend_restore(void)
{
/* restore settings after suspend */
+ __raw_writel(anatop[0], anatop_base + ANATOP_REG_2P5_OFFSET);
+ __raw_writel(anatop[1], anatop_base + ANATOP_REG_CORE_OFFSET);
+ udelay(50);
__raw_writel(ccm_ccr, MXC_CCM_CCR);
__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
__raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET);
@@ -122,9 +172,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);
+
+ __raw_writel(ccgr1, MXC_CCM_CCGR1);
+ __raw_writel(ccgr6, MXC_CCM_CCGR6);
}
static int mx6_suspend_enter(suspend_state_t state)
@@ -149,11 +199,11 @@ static int mx6_suspend_enter(suspend_state_t state)
wake_irq_isr[2], wake_irq_isr[3]);
return 0;
}
-
mx6_suspend_store();
switch (state) {
case PM_SUSPEND_MEM:
+ gpu_power_down();
mxc_cpu_lp_set(ARM_POWER_OFF);
break;
case PM_SUSPEND_STANDBY:
@@ -183,6 +233,7 @@ static int mx6_suspend_enter(suspend_state_t state)
/* restore gic registers */
restore_gic_dist_state(0, &gds);
restore_gic_cpu_state(0, &gcs);
+ gpu_power_up();
}
mx6_suspend_restore();
diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c
index 16a6531abf5f..69e761c00402 100644
--- a/arch/arm/mach-mx6/system.c
+++ b/arch/arm/mach-mx6/system.c
@@ -131,9 +131,9 @@ void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
anatop_val = __raw_readl(anatop_base + ANATOP_REG_2P5_OFFSET);
anatop_val |= 1 << 18;
__raw_writel(anatop_val, anatop_base + ANATOP_REG_2P5_OFFSET);
- /* Make sure ARM and SOC domain has same voltage and PU domain off */
+ /* Make sure ARM and SOC domain has same voltage */
anatop_val = __raw_readl(anatop_base + ANATOP_REG_CORE_OFFSET);
- anatop_val &= 0xff83001f;
+ anatop_val &= ~(0x1f << 18);
anatop_val |= (anatop_val & 0x1f) << 18;
__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);