summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2017-03-03 19:25:22 -0800
committerMarcel Ziswiler <marcel.ziswiler@toradex.com>2017-12-21 14:27:41 +0100
commitc9ba45bf40ea6584124ebb74bfc6ac66bddb7b16 (patch)
tree10727b548c0c718c9bc91be2fe3db886ecb757f8 /arch
parent144d67fec5e59f72caec04153e15d937ec42f276 (diff)
ARM: imx: busfreq: do not force high frequency during suspend
If the M4 core is running and in a low frequency mode, the A7 core should make sure that the AXI bus is left in a low frequency mode when entering suspend. So far the code unconditionally increased the high frequency variable which essentially forced the AXI bus to run in high frequency mode when entering suspend. With this change we leave the system in the state it was last in and also make sure that the last state change is actually applied before going to sleep. Typically high_bus_count ends up to be 0 because all devices requiring a high bus frequency release the bus during suspend, allowing the AXI bus to switch to 24MHz only. If the M4 is not running we don't want to artificially slow down the suspend process, hence let the bus run at full speed (it will get disabled anyway by hardware mechanism). Similar, when the M4 is running at high speed we likely need the bus capacity. Signed-off-by: Stefan Agner <stefan.agner@toradex.com> Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com> (cherry picked from commit 9e05354060550645ad21a0455468e142c7fdb201)
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/busfreq-imx.c31
-rw-r--r--arch/arm/mach-imx/common.h3
2 files changed, 29 insertions, 5 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx.c b/arch/arm/mach-imx/busfreq-imx.c
index 1b0df6b3e392..c9cc1ef516fd 100644
--- a/arch/arm/mach-imx/busfreq-imx.c
+++ b/arch/arm/mach-imx/busfreq-imx.c
@@ -1029,19 +1029,30 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev,
static int bus_freq_pm_notify(struct notifier_block *nb, unsigned long event,
void *dummy)
{
+ if (cpu_is_imx7d() && imx_src_is_m4_enabled()) {
+ if (event == PM_SUSPEND_PREPARE)
+ imx_mu_lpm_ready(false);
+ else if (event == PM_POST_SUSPEND)
+ imx_mu_lpm_ready(true);
+
+ /*
+ * If M4 is in low frequency mode, we should not force the
+ * system AXI bus to high frequency but let it switch to low
+ * frequency mode when entering suspend...
+ */
+ if (imx_mu_is_m4_in_low_freq())
+ return NOTIFY_OK;
+ }
+
mutex_lock(&bus_freq_mutex);
if (event == PM_SUSPEND_PREPARE) {
- if (cpu_is_imx7d() && imx_src_is_m4_enabled())
- imx_mu_lpm_ready(false);
high_bus_count++;
set_high_bus_freq(1);
busfreq_suspended = 1;
} else if (event == PM_POST_SUSPEND) {
busfreq_suspended = 0;
high_bus_count--;
- if (cpu_is_imx7d() && imx_src_is_m4_enabled())
- imx_mu_lpm_ready(true);
schedule_delayed_work(&bus_freq_daemon,
usecs_to_jiffies(5000000));
}
@@ -1325,11 +1336,23 @@ static const struct of_device_id imx_busfreq_ids[] = {
{ /* sentinel */ }
};
+static int busfreq_suspend(struct device *pdev)
+{
+ flush_delayed_work(&low_bus_freq_handler);
+
+ return 0;
+}
+
+static const struct dev_pm_ops busfreq_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(busfreq_suspend, NULL)
+};
+
static struct platform_driver busfreq_driver = {
.driver = {
.name = "imx_busfreq",
.owner = THIS_MODULE,
.of_match_table = imx_busfreq_ids,
+ .pm = &busfreq_pm_ops,
},
.probe = busfreq_probe,
};
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index e8fd22bc2b15..c5a724e9988b 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -80,14 +80,15 @@ void imx_gpc_hold_m4_in_sleep(void);
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);
-bool imx_mu_is_m4_in_low_freq(void);
bool imx_mu_is_m4_in_stop(void);
void imx_mu_set_m4_run_mode(void);
#ifdef CONFIG_HAVE_IMX_MU
int imx_mu_lpm_ready(bool ready);
+bool imx_mu_is_m4_in_low_freq(void);
void imx_mu_set_m4_low_freq(void);
#else
static inline int imx_mu_lpm_ready(bool ready) { return 0; }
+static inline bool imx_mu_is_m4_in_low_freq(void) { return false; }
static inline void imx_mu_set_m4_low_freq(void) { }
#endif