From: Dmitry Osipenko <digetx@gmail.com> To: "Thierry Reding" <thierry.reding@gmail.com>, "Jonathan Hunter" <jonathanh@nvidia.com>, "Ulf Hansson" <ulf.hansson@linaro.org>, "Viresh Kumar" <vireshk@kernel.org>, "Stephen Boyd" <sboyd@kernel.org>, "Peter De Schrijver" <pdeschrijver@nvidia.com>, "Mikko Perttunen" <mperttunen@nvidia.com>, "Peter Chen" <peter.chen@kernel.org>, "Mark Brown" <broonie@kernel.org>, "Lee Jones" <lee.jones@linaro.org>, "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Nishanth Menon" <nm@ti.com>, "Vignesh Raghavendra" <vigneshr@ti.com>, "Richard Weinberger" <richard@nod.at>, "Miquel Raynal" <miquel.raynal@bootlin.com>, "Lucas Stach" <dev@lynxeye.de>, "Stefan Agner" <stefan@agner.ch>, "Adrian Hunter" <adrian.hunter@intel.com>, "Mauro Carvalho Chehab" <mchehab@kernel.org>, "Rob Herring" <robh+dt@kernel.org>, "Michael Turquette" <mturquette@baylibre.com> Cc: linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-staging@lists.linux.dev, linux-spi@vger.kernel.org, linux-pwm@vger.kernel.org, linux-mtd@lists.infradead.org, linux-mmc@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v8 28/34] soc/tegra: regulators: Prepare for suspend Date: Tue, 17 Aug 2021 04:27:48 +0300 [thread overview] Message-ID: <20210817012754.8710-29-digetx@gmail.com> (raw) In-Reply-To: <20210817012754.8710-1-digetx@gmail.com> Depending on hardware version, Tegra SoC may require a higher voltages during resume from system suspend, otherwise hardware will crash. Set SoC voltages to a nominal levels during suspend. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- drivers/soc/tegra/regulators-tegra20.c | 99 ++++++++++++++++++++ drivers/soc/tegra/regulators-tegra30.c | 122 +++++++++++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/drivers/soc/tegra/regulators-tegra20.c b/drivers/soc/tegra/regulators-tegra20.c index b8ce9fd0650d..6a2f90ab9d3e 100644 --- a/drivers/soc/tegra/regulators-tegra20.c +++ b/drivers/soc/tegra/regulators-tegra20.c @@ -16,7 +16,9 @@ #include <linux/regulator/coupler.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/suspend.h> +#include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> struct tegra_regulator_coupler { @@ -25,9 +27,12 @@ struct tegra_regulator_coupler { struct regulator_dev *cpu_rdev; struct regulator_dev *rtc_rdev; struct notifier_block reboot_notifier; + struct notifier_block suspend_notifier; int core_min_uV, cpu_min_uV; bool sys_reboot_mode_req; bool sys_reboot_mode; + bool sys_suspend_mode_req; + bool sys_suspend_mode; }; static inline struct tegra_regulator_coupler * @@ -105,6 +110,28 @@ static int tegra20_core_rtc_max_spread(struct regulator_dev *core_rdev, return 150000; } +static int tegra20_cpu_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + case 0: + return 1100000; + case 1: + return 1025000; + default: + return 1125000; + } +} + +static int tegra20_core_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + default: + return 1225000; + case 2: + return 1300000; + } +} + static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra, struct regulator_dev *core_rdev, struct regulator_dev *rtc_rdev, @@ -144,6 +171,11 @@ static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra, if (err) return err; + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + core_min_uV = clamp(tegra20_core_nominal_uV(), + core_min_uV, core_max_uV); + core_uV = regulator_get_voltage_rdev(core_rdev); if (core_uV < 0) return core_uV; @@ -279,6 +311,11 @@ static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra, if (tegra->sys_reboot_mode) cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV); + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + cpu_min_uV = clamp(tegra20_cpu_nominal_uV(), + cpu_min_uV, cpu_max_uV); + if (cpu_min_uV > cpu_uV) { err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev, cpu_uV, cpu_min_uV); @@ -320,6 +357,7 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler, } tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req); + tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req); if (rdev == cpu_rdev) return tegra20_cpu_voltage_update(tegra, cpu_rdev, @@ -334,6 +372,63 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler, return -EPERM; } +static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra, + bool sys_suspend_mode) +{ + int err; + + if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev) + return 0; + + /* + * All power domains are enabled early during resume from suspend + * by GENPD core. Domains like VENC may require a higher voltage + * when enabled during resume from suspend. This also prepares + * hardware for resuming from LP0. + */ + + WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode); + + err = regulator_sync_voltage_rdev(tegra->cpu_rdev); + if (err) + return err; + + err = regulator_sync_voltage_rdev(tegra->core_rdev); + if (err) + return err; + + return 0; +} + +static int tegra20_regulator_suspend(struct notifier_block *notifier, + unsigned long mode, void *arg) +{ + struct tegra_regulator_coupler *tegra; + int ret = 0; + + tegra = container_of(notifier, struct tegra_regulator_coupler, + suspend_notifier); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + ret = tegra20_regulator_prepare_suspend(tegra, true); + break; + + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + case PM_POST_SUSPEND: + ret = tegra20_regulator_prepare_suspend(tegra, false); + break; + } + + if (ret) + pr_err("failed to prepare regulators: %d\n", ret); + + return notifier_from_errno(ret); +} + static int tegra20_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra, bool sys_reboot_mode) { @@ -444,6 +539,7 @@ static struct tegra_regulator_coupler tegra20_coupler = { .balance_voltage = tegra20_regulator_balance_voltage, }, .reboot_notifier.notifier_call = tegra20_regulator_reboot, + .suspend_notifier.notifier_call = tegra20_regulator_suspend, }; static int __init tegra_regulator_coupler_init(void) @@ -456,6 +552,9 @@ static int __init tegra_regulator_coupler_init(void) err = register_reboot_notifier(&tegra20_coupler.reboot_notifier); WARN_ON(err); + err = register_pm_notifier(&tegra20_coupler.suspend_notifier); + WARN_ON(err); + return regulator_coupler_register(&tegra20_coupler.coupler); } arch_initcall(tegra_regulator_coupler_init); diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c index e74bbc9c7859..8fd43c689134 100644 --- a/drivers/soc/tegra/regulators-tegra30.c +++ b/drivers/soc/tegra/regulators-tegra30.c @@ -16,6 +16,7 @@ #include <linux/regulator/coupler.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/suspend.h> #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> @@ -25,9 +26,12 @@ struct tegra_regulator_coupler { struct regulator_dev *core_rdev; struct regulator_dev *cpu_rdev; struct notifier_block reboot_notifier; + struct notifier_block suspend_notifier; int core_min_uV, cpu_min_uV; bool sys_reboot_mode_req; bool sys_reboot_mode; + bool sys_suspend_mode_req; + bool sys_suspend_mode; }; static inline struct tegra_regulator_coupler * @@ -113,6 +117,52 @@ static int tegra30_core_cpu_limit(int cpu_uV) return -EINVAL; } +static int tegra30_cpu_nominal_uV(void) +{ + switch (tegra_sku_info.cpu_speedo_id) { + case 10 ... 11: + return 850000; + + case 9: + return 912000; + + case 1 ... 3: + case 7 ... 8: + return 1050000; + + default: + return 1125000; + + case 4 ... 6: + case 12 ... 13: + return 1237000; + } +} + +static int tegra30_core_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + case 0: + return 1200000; + + case 1: + if (tegra_sku_info.cpu_speedo_id != 7 && + tegra_sku_info.cpu_speedo_id != 8) + return 1200000; + + fallthrough; + + case 2: + if (tegra_sku_info.cpu_speedo_id != 13) + return 1300000; + + return 1350000; + + default: + return 1250000; + } +} + static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, struct regulator_dev *cpu_rdev, struct regulator_dev *core_rdev) @@ -168,6 +218,11 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, if (err) return err; + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + core_min_uV = clamp(tegra30_core_nominal_uV(), + core_min_uV, core_max_uV); + core_uV = regulator_get_voltage_rdev(core_rdev); if (core_uV < 0) return core_uV; @@ -223,6 +278,11 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, if (tegra->sys_reboot_mode) cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV); + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + cpu_min_uV = clamp(tegra30_cpu_nominal_uV(), + cpu_min_uV, cpu_max_uV); + if (core_min_limited_uV > core_uV) { pr_err("core voltage constraint violated: %d %d %d\n", core_uV, core_min_limited_uV, cpu_uV); @@ -292,10 +352,68 @@ static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler, } tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req); + tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req); return tegra30_voltage_update(tegra, cpu_rdev, core_rdev); } +static int tegra30_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra, + bool sys_suspend_mode) +{ + int err; + + if (!tegra->core_rdev || !tegra->cpu_rdev) + return 0; + + /* + * All power domains are enabled early during resume from suspend + * by GENPD core. Domains like VENC may require a higher voltage + * when enabled during resume from suspend. This also prepares + * hardware for resuming from LP0. + */ + + WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode); + + err = regulator_sync_voltage_rdev(tegra->cpu_rdev); + if (err) + return err; + + err = regulator_sync_voltage_rdev(tegra->core_rdev); + if (err) + return err; + + return 0; +} + +static int tegra30_regulator_suspend(struct notifier_block *notifier, + unsigned long mode, void *arg) +{ + struct tegra_regulator_coupler *tegra; + int ret = 0; + + tegra = container_of(notifier, struct tegra_regulator_coupler, + suspend_notifier); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + ret = tegra30_regulator_prepare_suspend(tegra, true); + break; + + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + case PM_POST_SUSPEND: + ret = tegra30_regulator_prepare_suspend(tegra, false); + break; + } + + if (ret) + pr_err("failed to prepare regulators: %d\n", ret); + + return notifier_from_errno(ret); +} + static int tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra, bool sys_reboot_mode) { @@ -395,6 +513,7 @@ static struct tegra_regulator_coupler tegra30_coupler = { .balance_voltage = tegra30_regulator_balance_voltage, }, .reboot_notifier.notifier_call = tegra30_regulator_reboot, + .suspend_notifier.notifier_call = tegra30_regulator_suspend, }; static int __init tegra_regulator_coupler_init(void) @@ -407,6 +526,9 @@ static int __init tegra_regulator_coupler_init(void) err = register_reboot_notifier(&tegra30_coupler.reboot_notifier); WARN_ON(err); + err = register_pm_notifier(&tegra30_coupler.suspend_notifier); + WARN_ON(err); + return regulator_coupler_register(&tegra30_coupler.coupler); } arch_initcall(tegra_regulator_coupler_init); -- 2.32.0
WARNING: multiple messages have this Message-ID (diff)
From: Dmitry Osipenko <digetx@gmail.com> To: "Thierry Reding" <thierry.reding@gmail.com>, "Jonathan Hunter" <jonathanh@nvidia.com>, "Ulf Hansson" <ulf.hansson@linaro.org>, "Viresh Kumar" <vireshk@kernel.org>, "Stephen Boyd" <sboyd@kernel.org>, "Peter De Schrijver" <pdeschrijver@nvidia.com>, "Mikko Perttunen" <mperttunen@nvidia.com>, "Peter Chen" <peter.chen@kernel.org>, "Mark Brown" <broonie@kernel.org>, "Lee Jones" <lee.jones@linaro.org>, "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>, "Nishanth Menon" <nm@ti.com>, "Vignesh Raghavendra" <vigneshr@ti.com>, "Richard Weinberger" <richard@nod.at>, "Miquel Raynal" <miquel.raynal@bootlin.com>, "Lucas Stach" <dev@lynxeye.de>, "Stefan Agner" <stefan@agner.ch>, "Adrian Hunter" <adrian.hunter@intel.com>, "Mauro Carvalho Chehab" <mchehab@kernel.org>, "Rob Herring" <robh+dt@kernel.org>, "Michael Turquette" <mturquette@baylibre.com> Cc: linux-kernel@vger.kernel.org, linux-tegra@vger.kernel.org, linux-pm@vger.kernel.org, linux-usb@vger.kernel.org, linux-staging@lists.linux.dev, linux-spi@vger.kernel.org, linux-pwm@vger.kernel.org, linux-mtd@lists.infradead.org, linux-mmc@vger.kernel.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org Subject: [PATCH v8 28/34] soc/tegra: regulators: Prepare for suspend Date: Tue, 17 Aug 2021 04:27:48 +0300 [thread overview] Message-ID: <20210817012754.8710-29-digetx@gmail.com> (raw) In-Reply-To: <20210817012754.8710-1-digetx@gmail.com> Depending on hardware version, Tegra SoC may require a higher voltages during resume from system suspend, otherwise hardware will crash. Set SoC voltages to a nominal levels during suspend. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> --- drivers/soc/tegra/regulators-tegra20.c | 99 ++++++++++++++++++++ drivers/soc/tegra/regulators-tegra30.c | 122 +++++++++++++++++++++++++ 2 files changed, 221 insertions(+) diff --git a/drivers/soc/tegra/regulators-tegra20.c b/drivers/soc/tegra/regulators-tegra20.c index b8ce9fd0650d..6a2f90ab9d3e 100644 --- a/drivers/soc/tegra/regulators-tegra20.c +++ b/drivers/soc/tegra/regulators-tegra20.c @@ -16,7 +16,9 @@ #include <linux/regulator/coupler.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/suspend.h> +#include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> struct tegra_regulator_coupler { @@ -25,9 +27,12 @@ struct tegra_regulator_coupler { struct regulator_dev *cpu_rdev; struct regulator_dev *rtc_rdev; struct notifier_block reboot_notifier; + struct notifier_block suspend_notifier; int core_min_uV, cpu_min_uV; bool sys_reboot_mode_req; bool sys_reboot_mode; + bool sys_suspend_mode_req; + bool sys_suspend_mode; }; static inline struct tegra_regulator_coupler * @@ -105,6 +110,28 @@ static int tegra20_core_rtc_max_spread(struct regulator_dev *core_rdev, return 150000; } +static int tegra20_cpu_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + case 0: + return 1100000; + case 1: + return 1025000; + default: + return 1125000; + } +} + +static int tegra20_core_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + default: + return 1225000; + case 2: + return 1300000; + } +} + static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra, struct regulator_dev *core_rdev, struct regulator_dev *rtc_rdev, @@ -144,6 +171,11 @@ static int tegra20_core_rtc_update(struct tegra_regulator_coupler *tegra, if (err) return err; + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + core_min_uV = clamp(tegra20_core_nominal_uV(), + core_min_uV, core_max_uV); + core_uV = regulator_get_voltage_rdev(core_rdev); if (core_uV < 0) return core_uV; @@ -279,6 +311,11 @@ static int tegra20_cpu_voltage_update(struct tegra_regulator_coupler *tegra, if (tegra->sys_reboot_mode) cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV); + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + cpu_min_uV = clamp(tegra20_cpu_nominal_uV(), + cpu_min_uV, cpu_max_uV); + if (cpu_min_uV > cpu_uV) { err = tegra20_core_rtc_update(tegra, core_rdev, rtc_rdev, cpu_uV, cpu_min_uV); @@ -320,6 +357,7 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler, } tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req); + tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req); if (rdev == cpu_rdev) return tegra20_cpu_voltage_update(tegra, cpu_rdev, @@ -334,6 +372,63 @@ static int tegra20_regulator_balance_voltage(struct regulator_coupler *coupler, return -EPERM; } +static int tegra20_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra, + bool sys_suspend_mode) +{ + int err; + + if (!tegra->core_rdev || !tegra->rtc_rdev || !tegra->cpu_rdev) + return 0; + + /* + * All power domains are enabled early during resume from suspend + * by GENPD core. Domains like VENC may require a higher voltage + * when enabled during resume from suspend. This also prepares + * hardware for resuming from LP0. + */ + + WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode); + + err = regulator_sync_voltage_rdev(tegra->cpu_rdev); + if (err) + return err; + + err = regulator_sync_voltage_rdev(tegra->core_rdev); + if (err) + return err; + + return 0; +} + +static int tegra20_regulator_suspend(struct notifier_block *notifier, + unsigned long mode, void *arg) +{ + struct tegra_regulator_coupler *tegra; + int ret = 0; + + tegra = container_of(notifier, struct tegra_regulator_coupler, + suspend_notifier); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + ret = tegra20_regulator_prepare_suspend(tegra, true); + break; + + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + case PM_POST_SUSPEND: + ret = tegra20_regulator_prepare_suspend(tegra, false); + break; + } + + if (ret) + pr_err("failed to prepare regulators: %d\n", ret); + + return notifier_from_errno(ret); +} + static int tegra20_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra, bool sys_reboot_mode) { @@ -444,6 +539,7 @@ static struct tegra_regulator_coupler tegra20_coupler = { .balance_voltage = tegra20_regulator_balance_voltage, }, .reboot_notifier.notifier_call = tegra20_regulator_reboot, + .suspend_notifier.notifier_call = tegra20_regulator_suspend, }; static int __init tegra_regulator_coupler_init(void) @@ -456,6 +552,9 @@ static int __init tegra_regulator_coupler_init(void) err = register_reboot_notifier(&tegra20_coupler.reboot_notifier); WARN_ON(err); + err = register_pm_notifier(&tegra20_coupler.suspend_notifier); + WARN_ON(err); + return regulator_coupler_register(&tegra20_coupler.coupler); } arch_initcall(tegra_regulator_coupler_init); diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c index e74bbc9c7859..8fd43c689134 100644 --- a/drivers/soc/tegra/regulators-tegra30.c +++ b/drivers/soc/tegra/regulators-tegra30.c @@ -16,6 +16,7 @@ #include <linux/regulator/coupler.h> #include <linux/regulator/driver.h> #include <linux/regulator/machine.h> +#include <linux/suspend.h> #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> @@ -25,9 +26,12 @@ struct tegra_regulator_coupler { struct regulator_dev *core_rdev; struct regulator_dev *cpu_rdev; struct notifier_block reboot_notifier; + struct notifier_block suspend_notifier; int core_min_uV, cpu_min_uV; bool sys_reboot_mode_req; bool sys_reboot_mode; + bool sys_suspend_mode_req; + bool sys_suspend_mode; }; static inline struct tegra_regulator_coupler * @@ -113,6 +117,52 @@ static int tegra30_core_cpu_limit(int cpu_uV) return -EINVAL; } +static int tegra30_cpu_nominal_uV(void) +{ + switch (tegra_sku_info.cpu_speedo_id) { + case 10 ... 11: + return 850000; + + case 9: + return 912000; + + case 1 ... 3: + case 7 ... 8: + return 1050000; + + default: + return 1125000; + + case 4 ... 6: + case 12 ... 13: + return 1237000; + } +} + +static int tegra30_core_nominal_uV(void) +{ + switch (tegra_sku_info.soc_speedo_id) { + case 0: + return 1200000; + + case 1: + if (tegra_sku_info.cpu_speedo_id != 7 && + tegra_sku_info.cpu_speedo_id != 8) + return 1200000; + + fallthrough; + + case 2: + if (tegra_sku_info.cpu_speedo_id != 13) + return 1300000; + + return 1350000; + + default: + return 1250000; + } +} + static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, struct regulator_dev *cpu_rdev, struct regulator_dev *core_rdev) @@ -168,6 +218,11 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, if (err) return err; + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + core_min_uV = clamp(tegra30_core_nominal_uV(), + core_min_uV, core_max_uV); + core_uV = regulator_get_voltage_rdev(core_rdev); if (core_uV < 0) return core_uV; @@ -223,6 +278,11 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, if (tegra->sys_reboot_mode) cpu_min_uV = max(cpu_min_uV, tegra->cpu_min_uV); + /* prepare voltage level for suspend */ + if (tegra->sys_suspend_mode) + cpu_min_uV = clamp(tegra30_cpu_nominal_uV(), + cpu_min_uV, cpu_max_uV); + if (core_min_limited_uV > core_uV) { pr_err("core voltage constraint violated: %d %d %d\n", core_uV, core_min_limited_uV, cpu_uV); @@ -292,10 +352,68 @@ static int tegra30_regulator_balance_voltage(struct regulator_coupler *coupler, } tegra->sys_reboot_mode = READ_ONCE(tegra->sys_reboot_mode_req); + tegra->sys_suspend_mode = READ_ONCE(tegra->sys_suspend_mode_req); return tegra30_voltage_update(tegra, cpu_rdev, core_rdev); } +static int tegra30_regulator_prepare_suspend(struct tegra_regulator_coupler *tegra, + bool sys_suspend_mode) +{ + int err; + + if (!tegra->core_rdev || !tegra->cpu_rdev) + return 0; + + /* + * All power domains are enabled early during resume from suspend + * by GENPD core. Domains like VENC may require a higher voltage + * when enabled during resume from suspend. This also prepares + * hardware for resuming from LP0. + */ + + WRITE_ONCE(tegra->sys_suspend_mode_req, sys_suspend_mode); + + err = regulator_sync_voltage_rdev(tegra->cpu_rdev); + if (err) + return err; + + err = regulator_sync_voltage_rdev(tegra->core_rdev); + if (err) + return err; + + return 0; +} + +static int tegra30_regulator_suspend(struct notifier_block *notifier, + unsigned long mode, void *arg) +{ + struct tegra_regulator_coupler *tegra; + int ret = 0; + + tegra = container_of(notifier, struct tegra_regulator_coupler, + suspend_notifier); + + switch (mode) { + case PM_HIBERNATION_PREPARE: + case PM_RESTORE_PREPARE: + case PM_SUSPEND_PREPARE: + ret = tegra30_regulator_prepare_suspend(tegra, true); + break; + + case PM_POST_HIBERNATION: + case PM_POST_RESTORE: + case PM_POST_SUSPEND: + ret = tegra30_regulator_prepare_suspend(tegra, false); + break; + } + + if (ret) + pr_err("failed to prepare regulators: %d\n", ret); + + return notifier_from_errno(ret); +} + static int tegra30_regulator_prepare_reboot(struct tegra_regulator_coupler *tegra, bool sys_reboot_mode) { @@ -395,6 +513,7 @@ static struct tegra_regulator_coupler tegra30_coupler = { .balance_voltage = tegra30_regulator_balance_voltage, }, .reboot_notifier.notifier_call = tegra30_regulator_reboot, + .suspend_notifier.notifier_call = tegra30_regulator_suspend, }; static int __init tegra_regulator_coupler_init(void) @@ -407,6 +526,9 @@ static int __init tegra_regulator_coupler_init(void) err = register_reboot_notifier(&tegra30_coupler.reboot_notifier); WARN_ON(err); + err = register_pm_notifier(&tegra30_coupler.suspend_notifier); + WARN_ON(err); + return regulator_coupler_register(&tegra30_coupler.coupler); } arch_initcall(tegra_regulator_coupler_init); -- 2.32.0 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2021-08-17 1:30 UTC|newest] Thread overview: 238+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-08-17 1:27 [PATCH v8 00/34] NVIDIA Tegra power management patches for 5.16 Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 01/34] opp: Add dev_pm_opp_sync() helper Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 7:55 ` Viresh Kumar 2021-08-17 7:55 ` Viresh Kumar 2021-08-17 15:49 ` Dmitry Osipenko 2021-08-17 15:49 ` Dmitry Osipenko 2021-08-18 3:55 ` Viresh Kumar 2021-08-18 3:55 ` Viresh Kumar 2021-08-18 4:12 ` Dmitry Osipenko 2021-08-18 4:12 ` Dmitry Osipenko 2021-08-18 4:29 ` Dmitry Osipenko 2021-08-18 4:29 ` Dmitry Osipenko 2021-08-18 4:30 ` Dmitry Osipenko 2021-08-18 4:30 ` Dmitry Osipenko 2021-08-18 4:34 ` Viresh Kumar 2021-08-18 4:34 ` Viresh Kumar 2021-08-18 4:31 ` Viresh Kumar 2021-08-18 4:31 ` Viresh Kumar 2021-08-18 4:37 ` Dmitry Osipenko 2021-08-18 4:37 ` Dmitry Osipenko 2021-08-18 4:53 ` Viresh Kumar 2021-08-18 4:53 ` Viresh Kumar 2021-08-18 5:21 ` Dmitry Osipenko 2021-08-18 5:21 ` Dmitry Osipenko 2021-08-18 5:58 ` Viresh Kumar 2021-08-18 5:58 ` Viresh Kumar 2021-08-18 6:00 ` Viresh Kumar 2021-08-18 6:00 ` Viresh Kumar 2021-08-18 6:22 ` Dmitry Osipenko 2021-08-18 6:22 ` Dmitry Osipenko 2021-08-18 6:27 ` Viresh Kumar 2021-08-18 6:27 ` Viresh Kumar 2021-08-18 8:29 ` Ulf Hansson 2021-08-18 8:29 ` Ulf Hansson 2021-08-18 9:14 ` Viresh Kumar 2021-08-18 9:14 ` Viresh Kumar 2021-08-18 9:41 ` Ulf Hansson 2021-08-18 9:41 ` Ulf Hansson 2021-08-18 9:42 ` Ulf Hansson 2021-08-18 9:42 ` Ulf Hansson 2021-08-18 9:50 ` Viresh Kumar 2021-08-18 9:50 ` Viresh Kumar 2021-08-18 10:08 ` Ulf Hansson 2021-08-18 10:08 ` Ulf Hansson 2021-08-18 15:43 ` Dmitry Osipenko 2021-08-18 15:43 ` Dmitry Osipenko 2021-08-18 15:46 ` Dmitry Osipenko 2021-08-18 15:46 ` Dmitry Osipenko 2021-08-19 13:07 ` Ulf Hansson 2021-08-19 13:07 ` Ulf Hansson 2021-08-19 19:35 ` Dmitry Osipenko 2021-08-19 19:35 ` Dmitry Osipenko 2021-08-20 5:07 ` Viresh Kumar 2021-08-20 5:07 ` Viresh Kumar 2021-08-20 12:42 ` Ulf Hansson 2021-08-20 12:42 ` Ulf Hansson 2021-08-21 17:34 ` Dmitry Osipenko 2021-08-21 17:34 ` Dmitry Osipenko 2021-08-23 10:46 ` Ulf Hansson 2021-08-23 10:46 ` Ulf Hansson 2021-08-23 15:54 ` Dmitry Osipenko 2021-08-23 15:54 ` Dmitry Osipenko 2021-08-18 15:55 ` Dmitry Osipenko 2021-08-18 15:55 ` Dmitry Osipenko 2021-08-19 6:16 ` Viresh Kumar 2021-08-19 6:16 ` Viresh Kumar 2021-08-19 14:55 ` Ulf Hansson 2021-08-19 14:55 ` Ulf Hansson 2021-08-20 5:18 ` Viresh Kumar 2021-08-20 5:18 ` Viresh Kumar 2021-08-20 12:57 ` Ulf Hansson 2021-08-20 12:57 ` Ulf Hansson 2021-08-23 20:24 ` Dmitry Osipenko 2021-08-23 20:24 ` Dmitry Osipenko 2021-08-24 3:04 ` Viresh Kumar 2021-08-24 3:04 ` Viresh Kumar 2021-08-22 18:35 ` Dmitry Osipenko 2021-08-22 18:35 ` Dmitry Osipenko 2021-08-25 15:41 ` Dmitry Osipenko 2021-08-25 15:41 ` Dmitry Osipenko 2021-08-26 2:54 ` Viresh Kumar 2021-08-26 2:54 ` Viresh Kumar 2021-08-26 2:55 ` Viresh Kumar 2021-08-26 2:55 ` Viresh Kumar 2021-08-17 1:27 ` [PATCH v8 02/34] soc/tegra: pmc: Disable PMC state syncing Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 03/34] soc/tegra: Don't print error message when OPPs not available Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 04/34] soc/tegra: Add devm_tegra_core_dev_init_opp_table_simple() Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 05/34] soc/tegra: Use dev_pm_opp_sync() Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 06/34] dt-bindings: clock: tegra-car: Document new tegra-clocks sub-node Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-18 1:15 ` Rob Herring 2021-08-18 1:15 ` Rob Herring 2021-08-18 1:44 ` Dmitry Osipenko 2021-08-18 1:44 ` Dmitry Osipenko 2021-08-18 13:52 ` Thierry Reding 2021-08-18 13:52 ` Thierry Reding 2021-08-18 15:04 ` Dmitry Osipenko 2021-08-18 15:04 ` Dmitry Osipenko 2021-08-18 13:59 ` Thierry Reding 2021-08-18 13:59 ` Thierry Reding 2021-08-18 15:05 ` Dmitry Osipenko 2021-08-18 15:05 ` Dmitry Osipenko 2021-08-18 16:39 ` Thierry Reding 2021-08-18 16:39 ` Thierry Reding 2021-08-18 16:57 ` Dmitry Osipenko 2021-08-18 16:57 ` Dmitry Osipenko 2021-08-18 17:16 ` Dmitry Osipenko 2021-08-18 17:16 ` Dmitry Osipenko 2021-08-19 16:31 ` Thierry Reding 2021-08-19 16:31 ` Thierry Reding 2021-08-19 22:20 ` Dmitry Osipenko 2021-08-19 22:20 ` Dmitry Osipenko 2021-08-20 2:51 ` Dmitry Osipenko 2021-08-20 2:51 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 07/34] clk: tegra: Support runtime PM and power domain Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-18 14:07 ` Thierry Reding 2021-08-18 14:07 ` Thierry Reding 2021-08-18 15:05 ` Dmitry Osipenko 2021-08-18 15:05 ` Dmitry Osipenko 2021-08-18 16:42 ` Thierry Reding 2021-08-18 16:42 ` Thierry Reding 2021-08-18 17:11 ` Dmitry Osipenko 2021-08-18 17:11 ` Dmitry Osipenko 2021-08-19 16:54 ` Thierry Reding 2021-08-19 16:54 ` Thierry Reding 2021-08-19 22:09 ` Dmitry Osipenko 2021-08-19 22:09 ` Dmitry Osipenko 2021-08-20 11:42 ` Thierry Reding 2021-08-20 11:42 ` Thierry Reding 2021-08-20 13:08 ` Ulf Hansson 2021-08-20 13:08 ` Ulf Hansson 2021-08-21 17:45 ` Dmitry Osipenko 2021-08-21 17:45 ` Dmitry Osipenko 2021-08-23 14:33 ` Thierry Reding 2021-08-23 14:33 ` Thierry Reding 2021-08-23 18:54 ` Dmitry Osipenko 2021-08-23 18:54 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 08/34] dt-bindings: host1x: Document OPP and power domain properties Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 09/34] dt-bindings: host1x: Document Memory Client resets of Host1x, GR2D and GR3D Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-18 1:16 ` Rob Herring 2021-08-18 1:16 ` Rob Herring 2021-08-18 1:37 ` Dmitry Osipenko 2021-08-18 1:37 ` Dmitry Osipenko 2021-08-18 2:04 ` Dmitry Osipenko 2021-08-18 2:04 ` Dmitry Osipenko 2021-08-18 2:07 ` Dmitry Osipenko 2021-08-18 2:07 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 10/34] gpu: host1x: Add host1x_channel_stop() Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 11/34] gpu: host1x: Add runtime PM and OPP support Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 12:04 ` Ulf Hansson 2021-08-17 12:04 ` Ulf Hansson 2021-08-17 14:02 ` Thierry Reding 2021-08-17 14:02 ` Thierry Reding 2021-08-18 8:35 ` Ulf Hansson 2021-08-18 8:35 ` Ulf Hansson 2021-08-18 17:24 ` Dmitry Osipenko 2021-08-18 17:24 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 12/34] drm/tegra: dc: Support OPP and SoC core voltage scaling Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 13/34] drm/tegra: hdmi: Add OPP support Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 14/34] drm/tegra: gr2d: Support power management Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 15/34] drm/tegra: gr3d: " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 16/34] drm/tegra: vic: Support system suspend Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 17/34] usb: chipidea: tegra: Add runtime PM and OPP support Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 18/34] bus: tegra-gmi: " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 19/34] pwm: tegra: " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-19 13:21 ` Thierry Reding 2021-08-19 13:21 ` Thierry Reding 2021-08-19 14:04 ` Ulf Hansson 2021-08-19 14:04 ` Ulf Hansson 2021-08-19 16:17 ` Thierry Reding 2021-08-19 16:17 ` Thierry Reding 2021-08-17 1:27 ` [PATCH v8 20/34] mmc: sdhci-tegra: " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-19 17:03 ` Thierry Reding 2021-08-19 17:03 ` Thierry Reding 2021-08-19 22:37 ` Dmitry Osipenko 2021-08-19 22:37 ` Dmitry Osipenko 2021-08-20 11:35 ` Thierry Reding 2021-08-20 11:35 ` Thierry Reding 2021-08-25 9:45 ` Dmitry Osipenko 2021-08-25 9:45 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 21/34] mtd: rawnand: tegra: " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 8:41 ` Miquel Raynal 2021-08-17 8:41 ` Miquel Raynal 2021-08-17 1:27 ` [PATCH v8 22/34] spi: tegra20-slink: Add " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 12:22 ` Mark Brown 2021-08-17 12:22 ` Mark Brown 2021-08-17 15:53 ` Dmitry Osipenko 2021-08-17 15:53 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 23/34] media: dt: bindings: tegra-vde: Convert to schema Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-18 1:17 ` Rob Herring 2021-08-18 1:17 ` Rob Herring 2021-08-17 1:27 ` [PATCH v8 24/34] media: dt: bindings: tegra-vde: Document OPP and power domain Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-18 1:17 ` Rob Herring 2021-08-18 1:17 ` Rob Herring 2021-08-17 1:27 ` [PATCH v8 25/34] media: staging: tegra-vde: Support generic power domain and OPP Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 26/34] soc/tegra: fuse: Add OPP support Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 27/34] soc/tegra: fuse: Reset hardware Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko [this message] 2021-08-17 1:27 ` [PATCH v8 28/34] soc/tegra: regulators: Prepare for suspend Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 29/34] soc/tegra: pmc: Enable core domain support for Tegra20 and Tegra30 Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 30/34] ARM: tegra: Add OPP tables and power domains to Tegra20 device-trees Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 31/34] ARM: tegra: Add OPP tables and power domains to Tegra30 device-trees Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 32/34] ARM: tegra: Add Memory Client resets to Tegra20 GR2D, GR3D and Host1x Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 33/34] ARM: tegra: Add Memory Client resets to Tegra30 " Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko 2021-08-17 1:27 ` [PATCH v8 34/34] ARM: tegra20/30: Disable unused host1x hardware Dmitry Osipenko 2021-08-17 1:27 ` Dmitry Osipenko
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210817012754.8710-29-digetx@gmail.com \ --to=digetx@gmail.com \ --cc=adrian.hunter@intel.com \ --cc=broonie@kernel.org \ --cc=dev@lynxeye.de \ --cc=devicetree@vger.kernel.org \ --cc=dri-devel@lists.freedesktop.org \ --cc=jonathanh@nvidia.com \ --cc=lee.jones@linaro.org \ --cc=linux-clk@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-media@vger.kernel.org \ --cc=linux-mmc@vger.kernel.org \ --cc=linux-mtd@lists.infradead.org \ --cc=linux-pm@vger.kernel.org \ --cc=linux-pwm@vger.kernel.org \ --cc=linux-spi@vger.kernel.org \ --cc=linux-staging@lists.linux.dev \ --cc=linux-tegra@vger.kernel.org \ --cc=linux-usb@vger.kernel.org \ --cc=mchehab@kernel.org \ --cc=miquel.raynal@bootlin.com \ --cc=mperttunen@nvidia.com \ --cc=mturquette@baylibre.com \ --cc=nm@ti.com \ --cc=pdeschrijver@nvidia.com \ --cc=peter.chen@kernel.org \ --cc=richard@nod.at \ --cc=robh+dt@kernel.org \ --cc=sboyd@kernel.org \ --cc=stefan@agner.ch \ --cc=thierry.reding@gmail.com \ --cc=u.kleine-koenig@pengutronix.de \ --cc=ulf.hansson@linaro.org \ --cc=vigneshr@ti.com \ --cc=vireshk@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.