[v2,1/3] PM / Suspend: Add support to check if platform's power is off in suspend
diff mbox series

Message ID 1546944944-13911-2-git-send-email-claudiu.beznea@microchip.com
State New
Headers show
Series
  • add support for power off check in suspend
Related show

Commit Message

Claudiu Beznea Jan. 8, 2019, 10:56 a.m. UTC
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(+)

Comments

Pavel Machek Jan. 9, 2019, 2:14 p.m. UTC | #1
Hi!

> 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 wether the platform's power will be cut off at

wether -- spelling?

> @@ -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);
>  };

Dunno, should it be per-regulator? SoCs commonly have more than one
power supply, with some of them off during suspend...
									Pavel
Claudiu Beznea Jan. 10, 2019, 10:24 a.m. UTC | #2
On 09.01.2019 16:14, Pavel Machek wrote:
> Hi!
> 
>> 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 wether the platform's power will be cut off at
> 
> wether -- spelling?

Yep, I did it again :), sorry

> 
>> @@ -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);
>>  };
> 
> Dunno, should it be per-regulator? SoCs commonly have more than one
> power supply, with some of them off during suspend...

Every regulator has a suspend state which could be described via device
tree. In our case, besides other regulators, we have core regulator, which
is turned off in suspend at the end of the suspend procedure, when PMIC
detects a level transition on one of its pins, transition which is
triggered the moment the CPU is shut down (we are doing this from software
at the end of suspend procedure).

One aspect is that we map our proprietary power saving modes to Linux power
saving modes (suspend-to-ram and standby) at the system initialization. So,
we could have our backup mode mapped to any of suspend-to-ram or standby so
that when:
echo mem > /sys/power/state or
echo standby > /sys/power/state
the final power saving mode could be or not this backup mode (depending on
the mapping - which is done at system initialization based on kernel
parameters).

And so, depending on the mapped mode (which we currently know only from
arch/arm/mach-at91/) the real core's regulator could be on or off. We need
both these information to know if core's regulator would be off in suspend.

I chose to have it here, in platform_suspend_ops thinking that it is more
related to suspend procedure and that every platform could take use of it
to do whatever the platform specific things are done in suspend.
Also, I had in mind that regulator framework doesn't care (as far as I
know) what every regulator feeds.
It looked to me more proper to have it per platform since in our case we
have the mapping b/w Linux power saving modes (suspend-to-ram, standby) and
SoC specific power saving modes done only in arch/arm/mach-at91/.

I also though that doing so, and having the platform_off_in_suspend()
wrapper, in drivers we could only include linux/suspend.h and make use of
this wrapper and in case we would have had it per regulator we should have
been taken care in drivers or regulator framework which regulator deals
with feeding the core.

Thank you,
Claudiu Beznea

> 									Pavel
>

Patch
diff mbox series

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 wether 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);