ARM: imx: support arm power off in cpuidle for i.mx6sx
Subsystems (3)
PATCH v2 1/1 ARM: imx: support arm power off in cpuidle for i.mx6sx
This patch introduces an independent cpuidle driver for i.MX6SX, and supports arm power off in idle, totally 3 levels of cpuidle are supported as below:
1. ARM WFI;
2. SOC in WAIT mode;
3. SOC in WAIT mode + ARM power off.
ARM power off can save at least 5mW power.
This patch also replaces imx6q_enable_rbc with imx6_enable_rbc.
---
changes since V1:
replace imx6q_enable_rbc with imx6_enable_rbc.
arch/arm/mach-imx/Makefile | 3 +- arch/arm/mach-imx/common.h | 4 ++ arch/arm/mach-imx/cpuidle-imx6sx.c | 107 +++++++++++++++++++++++++++++++++++++ arch/arm/mach-imx/cpuidle.h | 5 ++ arch/arm/mach-imx/gpc.c | 25 ++++++++- arch/arm/mach-imx/mach-imx6sx.c | 2 +- arch/arm/mach-imx/pm-imx6.c | 6 +-- 7 files changed, 144 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-imx/cpuidle-imx6sx.c
arch/arm/mach-imx/Makefile +1 -2
@@ -32,8 +32,7 @@ ifeq ($(CONFIG_CPU_IDLE),y) obj-$(CONFIG_SOC_IMX5) += cpuidle-imx5.o obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o -# i.MX6SX reuses i.MX6Q cpuidle driver -obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6q.o +obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o endif ifdef CONFIG_SND_IMX_SOC
arch/arm/mach-imx/common.h +4 -0
@@ -70,6 +70,10 @@ void imx_set_soc_revision(unsigned int rev);unsigned int imx_get_soc_revision (void );void imx_init_revision_from_anatop (void );struct device *imx_soc_device_init (void ); +void imx6_enable_rbc (bool enable); +void imx_gpc_set_arm_power_in_lpm (bool power_off); +void imx_gpc_set_arm_power_up_timing (u32 sw2iso,u32 sw); +void imx_gpc_set_arm_power_down_timing (u32 sw2iso,u32 sw);enum mxc_cpu_pwr_mode {WAIT_CLOCKED ,/* wfi only */
arch/arm/mach-imx/cpuidle-imx6sx.c new file +107 -0
107 lines not on this page · raw message
arch/arm/mach-imx/cpuidle.h +5 -0
@@ -14,6 +14,7 @@extern int imx5_cpuidle_init (void );extern int imx6q_cpuidle_init (void );extern int imx6sl_cpuidle_init (void ); +extern int imx6sx_cpuidle_init (void );#else static inline int imx5_cpuidle_init (void ) {
@@ -27,4 +28,8 @@ static inline int imx6sl_cpuidle_init(void) {return 0 ; } +static inline int imx6sx_cpuidle_init (void ) +{ +return 0 ; +}#endif
arch/arm/mach-imx/gpc.c +23 -2
@@ -20,6 +20,10 @@#define GPC_IMR1 0x008#define GPC_PGC_CPU_PDN 0x2a0 +#define GPC_PGC_CPU_PUPSCR 0x2a4 +#define GPC_PGC_CPU_PDNSCR 0x2a8 +#define GPC_PGC_SW2ISO_SHIFT 0x8 +#define GPC_PGC_SW_SHIFT 0x0#define IMR_NUM 4
@@ -27,6 +31,23 @@ static void __iomem *gpc_base;static u32 gpc_wake_irqs[IMR_NUM ];static u32 gpc_saved_imrs[IMR_NUM ]; +void imx_gpc_set_arm_power_up_timing (u32 sw2iso,u32 sw) +{ +writel_relaxed ((sw2iso <<GPC_PGC_SW2ISO_SHIFT ) | + (sw <<GPC_PGC_SW_SHIFT ), gpc_base +GPC_PGC_CPU_PUPSCR ); +} + +void imx_gpc_set_arm_power_down_timing (u32 sw2iso,u32 sw) +{ +writel_relaxed ((sw2iso <<GPC_PGC_SW2ISO_SHIFT ) | + (sw <<GPC_PGC_SW_SHIFT ), gpc_base +GPC_PGC_CPU_PDNSCR ); +} + +void imx_gpc_set_arm_power_in_lpm (bool power_off) +{ +writel_relaxed (power_off, gpc_base +GPC_PGC_CPU_PDN ); +} +void imx_gpc_pre_suspend (bool arm_power_off) {void __iomem *reg_imr1 = gpc_base +GPC_IMR1 ;
@@ -34,7 +55,7 @@ void imx_gpc_pre_suspend(bool arm_power_off)/* Tell GPC to power off ARM core when suspend */ if (arm_power_off) -writel_relaxed (0x1 , gpc_base +GPC_PGC_CPU_PDN ); +imx_gpc_set_arm_power_in_lpm (arm_power_off);for (i =0 ; i <IMR_NUM ; i++) { gpc_saved_imrs[i] =readl_relaxed (reg_imr1 + i *4 );
@@ -48,7 +69,7 @@ void imx_gpc_post_resume(void)int i;/* Keep ARM core powered on for other low-power modes */ -writel_relaxed (0x0 , gpc_base +GPC_PGC_CPU_PDN ); +imx_gpc_set_arm_power_in_lpm (false);for (i =0 ; i <IMR_NUM ; i++)writel_relaxed (gpc_saved_imrs[i], reg_imr1 + i *4 );
arch/arm/mach-imx/mach-imx6sx.c +1 -1
@@ -90,7 +90,7 @@ static void __init imx6sx_init_irq(void)static void __init imx6sx_init_late (void ) { -imx6q_cpuidle_init (); +imx6sx_cpuidle_init ();if (IS_ENABLED (CONFIG_ARM_IMX6Q_CPUFREQ ))platform_device_register_simple ("imx6q-cpufreq" ,-1 ,NULL ,0 );
arch/arm/mach-imx/pm-imx6.c +3 -3
@@ -205,7 +205,7 @@ void imx6q_set_int_mem_clk_lpm(bool enable)writel_relaxed (val, ccm_base +CGPR ); } -static void imx6q_enable_rbc (bool enable) +void imx6_enable_rbc (bool enable) {u32 val;
@@ -360,7 +360,7 @@ static int imx6q_pm_enter(suspend_state_t state)* RBC setting, so we do NOT need to do that here. */ if (!imx6_suspend_in_ocram_fn) -imx6q_enable_rbc (true); +imx6_enable_rbc (true);imx_gpc_pre_suspend (true);imx_anatop_pre_suspend ();/* Zzz ... */
@@ -369,7 +369,7 @@ static int imx6q_pm_enter(suspend_state_t state)imx_smp_prepare ();imx_anatop_post_resume ();imx_gpc_post_resume (); -imx6q_enable_rbc (false); +imx6_enable_rbc (false);imx6q_enable_wb (false);imx6q_set_int_mem_clk_lpm (true);imx6q_set_lpm (WAIT_CLOCKED );
Signature · 1 line
1.9.1
Shawn Guo
AppliedPATCH v2 1/1 ARM: imx: support arm power off in cpuidle for i.mx6sx
Quoted 8 lines · Anson Huang
This patch introduces an independent cpuidle driver for i.MX6SX, and supports arm power off in idle, totally 3 levels of cpuidle are supported as below:
1. ARM WFI;
2. SOC in WAIT mode;
3. SOC in WAIT mode + ARM power off.
Quoted 5 lines
ARM power off can save at least 5mW power.
This patch also replaces
imx6q_enable_rbcwithimx6_enable_rbc.Signed-off-by Anson Huang <[email protected]>
Applied, thanks.