linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] add support for power off check in suspend
@ 2019-01-08  9:52 Claudiu.Beznea
  2019-01-08  9:52 ` [PATCH 1/3] PM / Suspend: Add support to check if platform's power is off " Claudiu.Beznea
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Claudiu.Beznea @ 2019-01-08  9:52 UTC (permalink / raw)
  To: Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches, linux,
	lgirdwood, broonie, rjw, pavel, len.brown
  Cc: linux-arm-kernel, linux-kernel, linux-pm, Claudiu.Beznea

From: Claudiu Beznea <claudiu.beznea@microchip.com>

Hi,

AT91 platforms support a power saving mode where SoC's power is cut off (we call
it backup mode). The resume is done with the help of bootloaders. To be able to
suspend/resume Linux to/from this mode all the drivers suspend/resume callbacks
should save/restore the content of all the active registers. We have 2 problems
we are trying to solve:
- some of these drivers are shared with other non Microchip SoCs (e.g. macb
  driver) and we don't want to disturbe other users of corresponding IPs with
  all the register save/restore operations;
- the suspend/resume time for the rest of the power saving mode we are using
  could be improved if we would know in drivers the suspend mode the platform
  is switched to.

A solution that would have been solve our problems was proposed in [1] but in
the end it wasn't accepted. It ended up with the introduction of
pm_suspend_target_state variable that could be used along with the changes in
this series.

While the discussion of [1] progressed it has been proposed (in [2]) to
implement a function that would tell if the platform's power would be cut off
at the end of the suspend procedure.

The patches in this series does as follows:
1/3 - add a new member to platform_suspend_ops that will tell if platform's
      power will be cut off at the end of the suspend procedure; drivers could
      use it via platform_off_in_suspend()
2/3 - add a new function to regulator's core that could be used to check if a
      proper regulator has been configured (via DT) to be powered off in
      suspend. This is used on this series to check the CPU's regulator is
      properly configured in DT to be turned off in suspend.
3/3 - fill .off_in_suspend member of at91_pm_ops; the functionality in patch 2/3
      is used to double check CPU's regulator would be turned off in suspend.

Thank you,
Claudiu Beznea

[1] https://lkml.org/lkml/2017/6/22/938
[2] https://lkml.org/lkml/2017/7/16/457

Claudiu Beznea (3):
  PM / Suspend: Add support to check if platform's power is off in
    suspend
  regulator: core: add helper to check if regulator is disabled in
    suspend
  ARM: at91: pm: add support for .off_in_suspend

 arch/arm/mach-at91/pm.c            | 61 +++++++++++++++++++++++++++++++++++---
 drivers/regulator/core.c           | 17 +++++++++++
 include/linux/regulator/consumer.h |  7 +++++
 include/linux/suspend.h            |  6 ++++
 kernel/power/suspend.c             | 13 ++++++++
 5 files changed, 100 insertions(+), 4 deletions(-)

-- 
2.7.4


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/3] PM / Suspend: Add support to check if platform's power is off in suspend
  2019-01-08  9:52 [PATCH 0/3] add support for power off check in suspend Claudiu.Beznea
@ 2019-01-08  9:52 ` Claudiu.Beznea
  2019-01-08  9:52 ` [PATCH 2/3] regulator: core: add helper to check if regulator is disabled " Claudiu.Beznea
  2019-01-08  9:53 ` [PATCH 3/3] ARM: at91: pm: add support for .off_in_suspend Claudiu.Beznea
  2 siblings, 0 replies; 4+ messages in thread
From: Claudiu.Beznea @ 2019-01-08  9:52 UTC (permalink / raw)
  To: Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches, linux,
	lgirdwood, broonie, rjw, pavel, len.brown
  Cc: linux-arm-kernel, linux-kernel, linux-pm, Claudiu.Beznea

From: Claudiu Beznea <claudiu.beznea@microchip.com>

Add support to check if platform's power will be cut off in suspend.
This will help drivers shared by multiple platforms to take only the
necessary actions while suspending/resuming (some platform may not need
to save/restore all the registers if platforms remains powered while
suspended). In this way suspend/resume time could be improved.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 include/linux/suspend.h |  6 ++++++
 kernel/power/suspend.c  | 13 +++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index 3f529ad9a9d2..21f19b167fe2 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -173,6 +173,9 @@ static inline void dpm_save_failed_step(enum suspend_stat_step step)
  *	Called by the PM core if the suspending of devices fails.
  *	This callback is optional and should only be implemented by platforms
  *	which require special recovery actions in that situation.
+ *
+ * @off_in_suspend: Returns wheather the platform's power will be cut off at
+ *	the end of suspend procedure or not.
  */
 struct platform_suspend_ops {
 	int (*valid)(suspend_state_t state);
@@ -185,6 +188,7 @@ struct platform_suspend_ops {
 	bool (*suspend_again)(void);
 	void (*end)(void);
 	void (*recover)(void);
+	bool (*off_in_suspend)(suspend_state_t state);
 };
 
 struct platform_s2idle_ops {
@@ -275,6 +279,7 @@ extern void arch_suspend_disable_irqs(void);
 extern void arch_suspend_enable_irqs(void);
 
 extern int pm_suspend(suspend_state_t state);
+extern bool platform_off_in_suspend(suspend_state_t state);
 #else /* !CONFIG_SUSPEND */
 #define suspend_valid_only_mem	NULL
 
@@ -287,6 +292,7 @@ static inline bool pm_suspend_via_s2idle(void) { return false; }
 
 static inline void suspend_set_ops(const struct platform_suspend_ops *ops) {}
 static inline int pm_suspend(suspend_state_t state) { return -ENOSYS; }
+static inline bool platform_off_in_suspend(suspend_state_t state) { return false; }
 static inline bool idle_should_enter_s2idle(void) { return false; }
 static inline void __init pm_states_init(void) {}
 static inline void s2idle_set_ops(const struct platform_s2idle_ops *ops) {}
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 0bd595a0b610..e1f60c8a17b9 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -319,6 +319,19 @@ static bool platform_suspend_again(suspend_state_t state)
 		suspend_ops->suspend_again() : false;
 }
 
+/**
+ * platform_off_in_suspend() - specifies if SoC's power will pe cut off at the
+ * end of suspend procedure.
+ */
+bool platform_off_in_suspend(suspend_state_t state)
+{
+	if (!suspend_ops || !suspend_ops->off_in_suspend)
+		return false;
+
+	return suspend_ops->off_in_suspend(state);
+}
+EXPORT_SYMBOL_GPL(platform_off_in_suspend);
+
 #ifdef CONFIG_PM_DEBUG
 static unsigned int pm_test_delay = 5;
 module_param(pm_test_delay, uint, 0644);
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] regulator: core: add helper to check if regulator is disabled in suspend
  2019-01-08  9:52 [PATCH 0/3] add support for power off check in suspend Claudiu.Beznea
  2019-01-08  9:52 ` [PATCH 1/3] PM / Suspend: Add support to check if platform's power is off " Claudiu.Beznea
@ 2019-01-08  9:52 ` Claudiu.Beznea
  2019-01-08  9:53 ` [PATCH 3/3] ARM: at91: pm: add support for .off_in_suspend Claudiu.Beznea
  2 siblings, 0 replies; 4+ messages in thread
From: Claudiu.Beznea @ 2019-01-08  9:52 UTC (permalink / raw)
  To: Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches, linux,
	lgirdwood, broonie, rjw, pavel, len.brown
  Cc: linux-arm-kernel, linux-kernel, linux-pm, Claudiu.Beznea

From: Claudiu Beznea <claudiu.beznea@microchip.com>

Add helper to check if regulator will be disabled in suspend.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 drivers/regulator/core.c           | 17 +++++++++++++++++
 include/linux/regulator/consumer.h |  7 +++++++
 2 files changed, 24 insertions(+)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index b9d7b45c7295..a876ec369450 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3786,6 +3786,23 @@ int regulator_suspend_disable(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_suspend_disable);
 
+bool regulator_is_disabled_in_suspend(struct regulator *regulator,
+				      suspend_state_t state)
+{
+	struct regulator_state *rstate;
+
+	if (!regulator->rdev->constraints)
+		return false;
+
+	rstate = regulator_get_suspend_state(regulator->rdev, state);
+	if (!rstate)
+		return false;
+
+	return !!(regulator->rdev->desc->ops->set_suspend_disable &&
+		  rstate->enabled == DISABLE_IN_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(regulator_is_disabled_in_suspend);
+
 static int _regulator_set_suspend_voltage(struct regulator *regulator,
 					  int min_uV, int max_uV,
 					  suspend_state_t state)
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index f3f76051e8b0..cf5e71dc63ce 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -36,6 +36,7 @@
 #define __LINUX_REGULATOR_CONSUMER_H_
 
 #include <linux/err.h>
+#include <linux/suspend.h>
 
 struct device;
 struct notifier_block;
@@ -285,6 +286,9 @@ void devm_regulator_unregister_notifier(struct regulator *regulator,
 void *regulator_get_drvdata(struct regulator *regulator);
 void regulator_set_drvdata(struct regulator *regulator, void *data);
 
+/* regulator suspend/resume state */
+bool regulator_is_disabled_in_suspend(struct regulator *regulator,
+				      suspend_state_t state);
 #else
 
 /*
@@ -579,6 +583,9 @@ static inline int regulator_list_voltage(struct regulator *regulator, unsigned s
 	return -EINVAL;
 }
 
+bool regulator_is_disabled_in_suspend(struct regulator *regulator,
+				      suspend_state_t state);
+
 #endif
 
 static inline int regulator_set_voltage_triplet(struct regulator *regulator,
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] ARM: at91: pm: add support for .off_in_suspend
  2019-01-08  9:52 [PATCH 0/3] add support for power off check in suspend Claudiu.Beznea
  2019-01-08  9:52 ` [PATCH 1/3] PM / Suspend: Add support to check if platform's power is off " Claudiu.Beznea
  2019-01-08  9:52 ` [PATCH 2/3] regulator: core: add helper to check if regulator is disabled " Claudiu.Beznea
@ 2019-01-08  9:53 ` Claudiu.Beznea
  2 siblings, 0 replies; 4+ messages in thread
From: Claudiu.Beznea @ 2019-01-08  9:53 UTC (permalink / raw)
  To: Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches, linux,
	lgirdwood, broonie, rjw, pavel, len.brown
  Cc: linux-arm-kernel, linux-kernel, linux-pm, Claudiu.Beznea

From: Claudiu Beznea <claudiu.beznea@microchip.com>

Add support to check if platform is off in suspend. The check is based on
pm_data.mode and CPU's regulator which will be turn off in suspend.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 51e808adb00c..c404d92aa297 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -16,6 +16,7 @@
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/parser.h>
+#include <linux/regulator/consumer.h>
 #include <linux/suspend.h>
 
 #include <linux/clk/at91_pmc.h>
@@ -164,6 +165,47 @@ static int at91_pm_config_ws(unsigned int pm_mode, bool set)
 	return mode ? 0 : -EPERM;
 }
 
+static const struct of_device_id sama5d2_cpu_reg_ids[] = {
+	{ .compatible = "active-semi,act8945a",		.data = "VDD_1V2" },
+	{ /* sentinel */ }
+};
+
+static struct regulator *at91_pm_cpu_regulator_get(void)
+{
+	struct device *cpu_dev = get_cpu_device(0);
+	static struct regulator *cpu_reg;
+	const struct of_device_id *match;
+	struct platform_device *pdev;
+	struct device_node *np;
+
+	if (!cpu_dev)
+		return cpu_reg;
+
+	if (!cpu_reg) {
+		for_each_matching_node_and_match(np, sama5d2_cpu_reg_ids,
+						 &match) {
+			pdev = of_find_device_by_node(np);
+			if (!pdev)
+				continue;
+
+			cpu_reg = regulator_get(cpu_dev, match->data);
+			put_device(&pdev->dev);
+			break;
+		}
+	}
+
+	return cpu_reg;
+}
+
+static bool at91_pm_state_allowed(suspend_state_t state)
+{
+	struct regulator *reg;
+
+	reg = at91_pm_cpu_regulator_get();
+
+	return !!(reg && regulator_is_disabled_in_suspend(reg, state));
+}
+
 /*
  * Called after processes are frozen, but before we shutdown devices.
  */
@@ -182,6 +224,9 @@ static int at91_pm_begin(suspend_state_t state)
 		pm_data.mode = -1;
 	}
 
+	if (pm_data.mode == AT91_PM_BACKUP && !at91_pm_state_allowed(state))
+		return -EPERM;
+
 	return at91_pm_config_ws(pm_data.mode, true);
 }
 
@@ -321,12 +366,20 @@ static void at91_pm_end(void)
 	at91_pm_config_ws(pm_data.mode, false);
 }
 
+static bool at91_pm_off_in_suspend(suspend_state_t state)
+{
+	if (pm_data.mode != AT91_PM_BACKUP)
+		return false;
+
+	return at91_pm_state_allowed(state);
+}
 
 static const struct platform_suspend_ops at91_pm_ops = {
-	.valid	= at91_pm_valid_state,
-	.begin	= at91_pm_begin,
-	.enter	= at91_pm_enter,
-	.end	= at91_pm_end,
+	.valid		= at91_pm_valid_state,
+	.begin		= at91_pm_begin,
+	.enter		= at91_pm_enter,
+	.end		= at91_pm_end,
+	.off_in_suspend	= at91_pm_off_in_suspend,
 };
 
 static struct platform_device at91_cpuidle_device = {
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-01-08  9:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-08  9:52 [PATCH 0/3] add support for power off check in suspend Claudiu.Beznea
2019-01-08  9:52 ` [PATCH 1/3] PM / Suspend: Add support to check if platform's power is off " Claudiu.Beznea
2019-01-08  9:52 ` [PATCH 2/3] regulator: core: add helper to check if regulator is disabled " Claudiu.Beznea
2019-01-08  9:53 ` [PATCH 3/3] ARM: at91: pm: add support for .off_in_suspend Claudiu.Beznea

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).