MLK-11071 cpufreq: imx7: add cpufreq pm_notifier on imx7d
authorBai Ping <b51503@freescale.com>
Tue, 9 Jun 2015 15:42:50 +0000 (23:42 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 19:46:56 +0000 (14:46 -0500)
Add pm_notifier for cpufreq on i.MX7D to make sure when
system do suspend/resume no cpu frequency change.
cpu frequency change may use the I2C/SPI interface to
control the external PMIC chip, if the I2C/SPI are not
active in this procedure, frequency change will fail.

Signed-off-by: Bai Ping <b51503@freescale.com>
(cherry picked from commit b993956109856d3b86df501271b5a55620781c1a)

drivers/cpufreq/imx7-cpufreq.c

index 7aafed7..617a64f 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-
+#include <linux/suspend.h>
 static struct clk *arm_clk;
 static struct clk *pll_arm;
 static struct clk *arm_src;
@@ -125,6 +125,40 @@ static struct cpufreq_driver imx7d_cpufreq_driver = {
        .attr = cpufreq_generic_attr,
 };
 
+static int imx7_cpufreq_pm_notify(struct notifier_block *nb,
+       unsigned long event, void *dummy)
+{
+       struct cpufreq_policy *data = cpufreq_cpu_get(0);
+       static u32 cpufreq_policy_min_pre_suspend;
+
+       /*
+        * During suspend/resume, when cpufreq driver try to increase
+        * voltage/freq, it needs to control I2C/SPI to communicate
+        * with external PMIC to adjust voltage, but these I2C/SPI
+        * devices may be already suspended, to avoid such scenario,
+        * we just increase cpufreq to highest setpoint before suspend.
+        */
+       switch (event) {
+       case PM_SUSPEND_PREPARE:
+               cpufreq_policy_min_pre_suspend = data->user_policy.min;
+               data->user_policy.min = data->user_policy.max;
+               break;
+       case PM_POST_SUSPEND:
+               data->user_policy.min = cpufreq_policy_min_pre_suspend;
+               break;
+       default:
+               break;
+       }
+
+       cpufreq_update_policy(0);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block imx7_cpufreq_pm_notifier = {
+       .notifier_call = imx7_cpufreq_pm_notify,
+};
+
 static int imx7d_cpufreq_probe(struct platform_device *pdev)
 {
        struct device_node *np;
@@ -217,6 +251,7 @@ static int imx7d_cpufreq_probe(struct platform_device *pdev)
 
        register_pm_notifier(&imx7_cpufreq_pm_notifier);
 
+       register_pm_notifier(&imx7_cpufreq_pm_notifier);
        of_node_put(np);
        return 0;