1919#include <linux/of_device.h>
2020#include <linux/platform_device.h>
2121#include <linux/psci.h>
22+ #include <linux/pm_domain.h>
2223#include <linux/pm_runtime.h>
2324#include <linux/slab.h>
2425#include <linux/string.h>
@@ -52,8 +53,9 @@ static inline int psci_enter_state(int idx, u32 state)
5253 return CPU_PM_CPU_IDLE_ENTER_PARAM (psci_cpu_suspend_enter , idx , state );
5354}
5455
55- static int psci_enter_domain_idle_state (struct cpuidle_device * dev ,
56- struct cpuidle_driver * drv , int idx )
56+ static int __psci_enter_domain_idle_state (struct cpuidle_device * dev ,
57+ struct cpuidle_driver * drv , int idx ,
58+ bool s2idle )
5759{
5860 struct psci_cpuidle_data * data = this_cpu_ptr (& psci_cpuidle_data );
5961 u32 * states = data -> psci_states ;
@@ -66,15 +68,25 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
6668 return -1 ;
6769
6870 /* Do runtime PM to manage a hierarchical CPU toplogy. */
69- RCU_NONIDLE (pm_runtime_put_sync_suspend (pd_dev ));
71+ rcu_irq_enter_irqson ();
72+ if (s2idle )
73+ dev_pm_genpd_suspend (pd_dev );
74+ else
75+ pm_runtime_put_sync_suspend (pd_dev );
76+ rcu_irq_exit_irqson ();
7077
7178 state = psci_get_domain_state ();
7279 if (!state )
7380 state = states [idx ];
7481
7582 ret = psci_cpu_suspend_enter (state ) ? -1 : idx ;
7683
77- RCU_NONIDLE (pm_runtime_get_sync (pd_dev ));
84+ rcu_irq_enter_irqson ();
85+ if (s2idle )
86+ dev_pm_genpd_resume (pd_dev );
87+ else
88+ pm_runtime_get_sync (pd_dev );
89+ rcu_irq_exit_irqson ();
7890
7991 cpu_pm_exit ();
8092
@@ -83,6 +95,19 @@ static int psci_enter_domain_idle_state(struct cpuidle_device *dev,
8395 return ret ;
8496}
8597
98+ static int psci_enter_domain_idle_state (struct cpuidle_device * dev ,
99+ struct cpuidle_driver * drv , int idx )
100+ {
101+ return __psci_enter_domain_idle_state (dev , drv , idx , false);
102+ }
103+
104+ static int psci_enter_s2idle_domain_idle_state (struct cpuidle_device * dev ,
105+ struct cpuidle_driver * drv ,
106+ int idx )
107+ {
108+ return __psci_enter_domain_idle_state (dev , drv , idx , true);
109+ }
110+
86111static int psci_idle_cpuhp_up (unsigned int cpu )
87112{
88113 struct device * pd_dev = __this_cpu_read (psci_cpuidle_data .dev );
@@ -170,6 +195,7 @@ static int psci_dt_cpu_init_topology(struct cpuidle_driver *drv,
170195 * deeper states.
171196 */
172197 drv -> states [state_count - 1 ].enter = psci_enter_domain_idle_state ;
198+ drv -> states [state_count - 1 ].enter_s2idle = psci_enter_s2idle_domain_idle_state ;
173199 psci_cpuidle_use_cpuhp = true;
174200
175201 return 0 ;
0 commit comments