diff options
author | Stefan Agner <stefan.agner@toradex.com> | 2017-03-03 19:25:22 -0800 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2017-04-03 15:36:21 +0200 |
commit | 9e05354060550645ad21a0455468e142c7fdb201 (patch) | |
tree | cd5d2de43bf4aff4aa88bdc7155963c71f3de3a0 | |
parent | 70f901b01c4ac4dfe741f91b76967a433674a37d (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>
-rw-r--r-- | arch/arm/mach-imx/busfreq-imx.c | 31 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 3 |
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 38540487429a..676ad4587a49 100644 --- a/arch/arm/mach-imx/busfreq-imx.c +++ b/arch/arm/mach-imx/busfreq-imx.c @@ -962,19 +962,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)); } @@ -1249,11 +1260,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 d933ddf34300..208b9d63b26b 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -88,14 +88,15 @@ int imx_update_shared_mem(struct clk_hw *hw, bool enable); bool imx_src_is_m4_enabled(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 |