summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c18
-rw-r--r--arch/arm/mach-imx/common.h1
-rw-r--r--arch/arm/mach-imx/pm-imx6.c23
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;
}