From 33803407a4e0b34bdfa5cf30db5c12d3b49475d1 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Thu, 24 Nov 2011 11:34:28 +0800 Subject: [PATCH] ENGR00163057 ARM: imx6q: add gpu suspend/resume support GPU power down/up follow a restrict process. Signed-off-by: Richard Zhao --- arch/arm/mach-mx6/pm.c | 65 ++++++++++++++++++++++++++++++++++---- arch/arm/mach-mx6/system.c | 4 +-- 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 +#include #include #include #include @@ -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); -- 2.39.5