diff options
author | Olof Johansson <olof@lixom.net> | 2019-12-06 19:28:11 +0300 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2019-12-06 19:28:13 +0300 |
commit | c25f318b1ff7f27ef25def34f3a8834ec6de5972 (patch) | |
tree | eeff3073cfae2971b94bbdb60573a58f8d8712c4 /drivers/cpufreq | |
parent | f7a1a1db9877799e15aba047acd799c2df811f88 (diff) | |
parent | 0fb438eed10ca13d212a5675363beb5a5cd721f2 (diff) | |
download | linux-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.c | 59 |
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, }; |