summaryrefslogtreecommitdiff
path: root/drivers/cpufreq
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2019-12-06 19:28:11 +0300
committerOlof Johansson <olof@lixom.net>2019-12-06 19:28:13 +0300
commitc25f318b1ff7f27ef25def34f3a8834ec6de5972 (patch)
treeeeff3073cfae2971b94bbdb60573a58f8d8712c4 /drivers/cpufreq
parentf7a1a1db9877799e15aba047acd799c2df811f88 (diff)
parent0fb438eed10ca13d212a5675363beb5a5cd721f2 (diff)
downloadlinux-c25f318b1ff7f27ef25def34f3a8834ec6de5972.tar.xz
Merge tag 'tegra-for-5.5-cpufreq' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux into arm/fixes
cpufreq: tegra: Changes for v5.5-rc1 Implements support for suspend/resume on Tegra124. * tag 'tegra-for-5.5-cpufreq' of git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux: cpufreq: tegra124: Add suspend and resume support Link: https://lore.kernel.org/r/20191204130753.3614278-3-thierry.reding@gmail.com Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/cpufreq')
-rw-r--r--drivers/cpufreq/tegra124-cpufreq.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
index 4f0c637b3b49..7a1ea6fdcab6 100644
--- a/drivers/cpufreq/tegra124-cpufreq.c
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -6,6 +6,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/clk.h>
+#include <linux/cpufreq.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -128,8 +129,66 @@ out_put_np:
return ret;
}
+static int __maybe_unused tegra124_cpufreq_suspend(struct device *dev)
+{
+ struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
+ int err;
+
+ /*
+ * PLLP rate 408Mhz is below the CPU Fmax at Vmin and is safe to
+ * use during suspend and resume. So, switch the CPU clock source
+ * to PLLP and disable DFLL.
+ */
+ err = clk_set_parent(priv->cpu_clk, priv->pllp_clk);
+ if (err < 0) {
+ dev_err(dev, "failed to reparent to PLLP: %d\n", err);
+ return err;
+ }
+
+ clk_disable_unprepare(priv->dfll_clk);
+
+ return 0;
+}
+
+static int __maybe_unused tegra124_cpufreq_resume(struct device *dev)
+{
+ struct tegra124_cpufreq_priv *priv = dev_get_drvdata(dev);
+ int err;
+
+ /*
+ * Warmboot code powers up the CPU with PLLP clock source.
+ * Enable DFLL clock and switch CPU clock source back to DFLL.
+ */
+ err = clk_prepare_enable(priv->dfll_clk);
+ if (err < 0) {
+ dev_err(dev, "failed to enable DFLL clock for CPU: %d\n", err);
+ goto disable_cpufreq;
+ }
+
+ err = clk_set_parent(priv->cpu_clk, priv->dfll_clk);
+ if (err < 0) {
+ dev_err(dev, "failed to reparent to DFLL clock: %d\n", err);
+ goto disable_dfll;
+ }
+
+ return 0;
+
+disable_dfll:
+ clk_disable_unprepare(priv->dfll_clk);
+disable_cpufreq:
+ disable_cpufreq();
+
+ return err;
+}
+
+static const struct dev_pm_ops tegra124_cpufreq_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(tegra124_cpufreq_suspend,
+ tegra124_cpufreq_resume)
+};
+
static struct platform_driver tegra124_cpufreq_platdrv = {
.driver.name = "cpufreq-tegra124",
+ .driver.pm = &tegra124_cpufreq_pm_ops,
.probe = tegra124_cpufreq_probe,
};