Commit c25f318b authored by Olof Johansson's avatar Olof Johansson
Browse files

Merge tag 'tegra-for-5.5-cpufreq' of...

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: default avatarOlof Johansson <olof@lixom.net>
parents f7a1a1db 0fb438ee
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -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 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev)
	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,
};