summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx/gpc.c
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-11-10 16:13:36 +0800
committerNitin Garg <nitin.garg@freescale.com>2015-04-14 14:01:07 -0500
commitfd4edc83cca0c9717f83e02172964cafc57ea7b5 (patch)
tree7ac9a0abad17e49ca5bab2069571456a9b25db28 /arch/arm/mach-imx/gpc.c
parentc0e06d15872cc07b386881e1f80d4c65b0b47842 (diff)
MLK-9825 arm: imx: add mega/fast mix power off feature in DSM
This patch adds mega fast domain power off feature in DSM, it can save about 0.72mW power; If there is any module in Mega/Fast domain enabled as wakeup source, then Mega/Fast domain's power will be kept on in DSM. Signed-off-by: Anson Huang <b20788@freescale.com>
Diffstat (limited to 'arch/arm/mach-imx/gpc.c')
-rw-r--r--arch/arm/mach-imx/gpc.c36
1 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 7fa7ba01a3d8..1936aa52348a 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -26,6 +26,7 @@
#define GPC_CNTR 0x000
#define GPC_IMR1 0x008
+#define GPC_PGC_MF_PDN 0x220
#define GPC_PGC_GPU_PDN 0x260
#define GPC_PGC_GPU_PUPSCR 0x264
#define GPC_PGC_GPU_PDNSCR 0x268
@@ -46,16 +47,33 @@ struct pu_domain {
};
static void __iomem *gpc_base;
+static u32 gpc_mf_irqs[IMR_NUM];
static u32 gpc_wake_irqs[IMR_NUM];
static u32 gpc_saved_imrs[IMR_NUM];
static u32 bypass;
+static void imx_gpc_mf_mix_off(void)
+{
+ int i;
+
+ for (i = 0; i < IMR_NUM; i++)
+ if ((gpc_wake_irqs[i] & gpc_mf_irqs[i]) != 0)
+ return;
+
+ pr_info("Turn off M/F mix!\n");
+ /* turn off mega/fast mix */
+ writel_relaxed(0x1, gpc_base + GPC_PGC_MF_PDN);
+}
+
void imx_gpc_pre_suspend(bool arm_power_off)
{
void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
int i;
/* Tell GPC to power off ARM core when suspend */
+ if (cpu_is_imx6sx() && arm_power_off)
+ imx_gpc_mf_mix_off();
+
if (arm_power_off)
writel_relaxed(0x1, gpc_base + GPC_PGC_CPU_PDN);
@@ -72,6 +90,9 @@ void imx_gpc_post_resume(void)
/* Keep ARM core powered on for other low-power modes */
writel_relaxed(0x0, gpc_base + GPC_PGC_CPU_PDN);
+ /* Keep M/F mix powered on for other low-power modes */
+ if (cpu_is_imx6sx())
+ writel_relaxed(0x0, gpc_base + GPC_PGC_MF_PDN);
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
@@ -157,6 +178,21 @@ void __init imx_gpc_init(void)
for (i = 0; i < IMR_NUM; i++)
writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+ /* Read supported wakeup source in M/F domain */
+ if (cpu_is_imx6sx()) {
+ of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 0,
+ &gpc_mf_irqs[0]);
+ of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 1,
+ &gpc_mf_irqs[1]);
+ of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 2,
+ &gpc_mf_irqs[2]);
+ of_property_read_u32_index(np, "fsl,mf-mix-wakeup-irq", 3,
+ &gpc_mf_irqs[3]);
+ if (!(gpc_mf_irqs[0] | gpc_mf_irqs[1] |
+ gpc_mf_irqs[2] | gpc_mf_irqs[3]))
+ pr_info("No wakeup source in Mega/Fast domain found!\n");
+ }
+
/* Register GPC as the secondary interrupt controller behind GIC */
gic_arch_extn.irq_mask = imx_gpc_irq_mask;
gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;