diff options
author | Anson Huang <b20788@freescale.com> | 2014-11-10 16:13:36 +0800 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2015-04-14 14:01:07 -0500 |
commit | fd4edc83cca0c9717f83e02172964cafc57ea7b5 (patch) | |
tree | 7ac9a0abad17e49ca5bab2069571456a9b25db28 /arch/arm/mach-imx/gpc.c | |
parent | c0e06d15872cc07b386881e1f80d4c65b0b47842 (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.c | 36 |
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; |