diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-imx/busfreq-imx.c | 18 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx6.c | 23 |
3 files changed, 42 insertions, 0 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c index 19246693f29e..d84e707e2228 100644 --- a/arch/arm/mach-imx/busfreq-imx.c +++ b/arch/arm/mach-imx/busfreq-imx.c @@ -107,6 +107,16 @@ static struct delayed_work bus_freq_daemon; static RAW_NOTIFIER_HEAD(busfreq_notifier_chain); +static bool check_m4_sleep(void) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(500); + + while (imx_gpc_is_m4_sleeping() == 0) + if (time_after(jiffies, timeout)) + return false; + return true; +} + static int busfreq_notify(enum busfreq_event event) { int ret; @@ -134,6 +144,10 @@ EXPORT_SYMBOL(unregister_busfreq_notifier); */ static void enter_lpm_imx6_up(void) { + if (cpu_is_imx6sx() && imx_src_is_m4_enabled()) + if (!check_m4_sleep()) + pr_err("M4 is NOT in sleep!!!\n"); + /* set periph_clk2 to source from OSC for periph */ clk_set_parent(periph_clk2_sel_clk, osc_clk); clk_set_parent(periph_clk, periph_clk2_clk); @@ -831,6 +845,10 @@ static int busfreq_probe(struct platform_device *pdev) err = init_mmdc_ddr3_settings_imx6_up(pdev); else if (ddr_type == IMX_DDR_TYPE_LPDDR2) err = init_mmdc_lpddr2_settings(pdev); + /* if M4 is enabled and rate > 24MHz, add high bus count */ + if (imx_src_is_m4_enabled() && + (clk_get_rate(m4_clk) > LPAPM_CLK)) + high_bus_count++; } if (err) { diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 23faad6a7bfb..d510cbf04cf9 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -74,6 +74,7 @@ void imx_gpc_release_m4_in_sleep(void); void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data); void mcc_send_via_mu_buffer(unsigned int index, unsigned int data); unsigned int imx_gpc_is_m4_sleeping(void); +bool imx_mu_is_m4_in_low_freq(void); enum mxc_cpu_pwr_mode { WAIT_CLOCKED, /* wfi only */ diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 8f4c57c306ed..07395d66b8b0 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -751,6 +751,24 @@ static int imx6q_pm_enter(suspend_state_t state) unsigned int console_saved_reg[11] = {0}; static unsigned int ccm_ccgr4, ccm_ccgr6; + if (imx_src_is_m4_enabled()) { + if (imx_gpc_is_m4_sleeping() && imx_mu_is_m4_in_low_freq()) { + imx_gpc_hold_m4_in_sleep(); + imx_mu_enable_m4_irqs_in_gic(true); + } else { + pr_info("M4 is busy, enter WAIT mode instead of STOP!\n"); + imx6_set_lpm(WAIT_UNCLOCKED); + imx6_set_int_mem_clk_lpm(true); + imx_gpc_pre_suspend(false); + /* Zzz ... */ + cpu_do_idle(); + imx_gpc_post_resume(); + imx6_set_lpm(WAIT_CLOCKED); + + return 0; + } + } + switch (state) { case PM_SUSPEND_STANDBY: imx6_set_lpm(STOP_POWER_ON); @@ -828,6 +846,11 @@ static int imx6q_pm_enter(suspend_state_t state) return -EINVAL; } + if (imx_src_is_m4_enabled()) { + imx_mu_enable_m4_irqs_in_gic(false); + imx_gpc_release_m4_in_sleep(); + } + return 0; } |