[PATCH v1 08/30] soc/tegra: regulators: Support Tegra SoC device sync state API
From: Dmitry Osipenko <digetx@gmail.com>
Date: 2020-11-04 23:49:30
Also in:
dri-devel, linux-media, linux-mmc, linux-pwm, linux-samsung-soc, linux-tegra, linux-usb, lkml
Subsystem:
the rest · Maintainer:
Linus Torvalds
Downscale of the CORE voltage isn't allowed because some hardware units, which are supplied by the CORE regulator, usually left ON at a boot time. The new sync state API resolves this problem for us. All drivers of the devices that are known to be ON at a boot time now should sync theirs state. Once everything is synced, the voltage of the CORE domain could be scaled without any limitations. Make Tegra20/30 regulator couplers to use the new sync state API. Tested-by: Peter Geis <redacted> Tested-by: Nicolas Chauvet <redacted> Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- drivers/soc/tegra/regulators-tegra20.c | 19 ++++++++++++++++++- drivers/soc/tegra/regulators-tegra30.c | 22 +++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/tegra/regulators-tegra20.c b/drivers/soc/tegra/regulators-tegra20.c
index 367a71a3cd10..8782e399a58c 100644
--- a/drivers/soc/tegra/regulators-tegra20.c
+++ b/drivers/soc/tegra/regulators-tegra20.c@@ -16,6 +16,8 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <soc/tegra/common.h> + struct tegra_regulator_coupler { struct regulator_coupler coupler; struct regulator_dev *core_rdev;
@@ -38,6 +40,21 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra, int core_cur_uV; int err; + /* + * Tegra20 SoC has critical DVFS-capable devices that are + * permanently-active or active at a boot time, like EMC + * (DRAM controller) or Host1x bus for example. + * + * The voltage of a CORE SoC power domain shall not be dropped below + * a minimum level, which is determined by device's clock rate. + * This means that we can't fully allow CORE voltage scaling until + * the state of all DVFS-critical CORE devices is synced. + */ + if (tegra_soc_dvfs_state_synced()) { + pr_info_once("voltage state synced\n"); + return 0; + } + if (tegra->core_min_uV > 0) return tegra->core_min_uV;
@@ -58,7 +75,7 @@ static int tegra20_core_limit(struct tegra_regulator_coupler *tegra, */ tegra->core_min_uV = core_max_uV; - pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV); + pr_info("core voltage initialized to %duV\n", tegra->core_min_uV); return tegra->core_min_uV; }
diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c
index 7f21f31de09d..f7a5260edffe 100644
--- a/drivers/soc/tegra/regulators-tegra30.c
+++ b/drivers/soc/tegra/regulators-tegra30.c@@ -16,6 +16,7 @@ #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <soc/tegra/common.h> #include <soc/tegra/fuse.h> struct tegra_regulator_coupler {
@@ -39,6 +40,21 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra, int core_cur_uV; int err; + /* + * Tegra30 SoC has critical DVFS-capable devices that are + * permanently-active or active at a boot time, like EMC + * (DRAM controller) or Host1x bus for example. + * + * The voltage of a CORE SoC power domain shall not be dropped below + * a minimum level, which is determined by device's clock rate. + * This means that we can't fully allow CORE voltage scaling until + * the state of all DVFS-critical CORE devices is synced. + */ + if (tegra_soc_dvfs_state_synced()) { + pr_info_once("voltage state synced\n"); + return 0; + } + if (tegra->core_min_uV > 0) return tegra->core_min_uV;
@@ -59,7 +75,7 @@ static int tegra30_core_limit(struct tegra_regulator_coupler *tegra, */ tegra->core_min_uV = core_max_uV; - pr_info("core minimum voltage limited to %duV\n", tegra->core_min_uV); + pr_info("core voltage initialized to %duV\n", tegra->core_min_uV); return tegra->core_min_uV; }
@@ -143,6 +159,10 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, if (core_min_uV < 0) return core_min_uV; + err = regulator_check_voltage(core_rdev, &core_min_uV, &core_max_uV); + if (err) + return err; + err = regulator_check_consumers(core_rdev, &core_min_uV, &core_max_uV, PM_SUSPEND_ON); if (err)
--
2.27.0