1 /*
2  * Copyright (c) 2012-2014 Wind River Systems, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_PM_PM_H_
8 #define ZEPHYR_INCLUDE_PM_PM_H_
9 
10 #include <zephyr/types.h>
11 #include <zephyr/sys/slist.h>
12 #include <zephyr/pm/state.h>
13 #include <zephyr/toolchain.h>
14 #include <errno.h>
15 #include <stdbool.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /**
22  * @brief System and device power management
23  * @defgroup subsys_pm Power Management (PM)
24  * @since 1.2
25  * @ingroup os_services
26  * @{
27  * @}
28  */
29 
30 /**
31  * @brief System Power Management API
32  * @defgroup subsys_pm_sys System
33  * @since 1.2
34  * @ingroup subsys_pm
35  * @{
36  */
37 
38 /**
39  * Power management notifier struct
40  *
41  * This struct contains callbacks that are called when the target enters and
42  * exits power states.
43  *
44  * As currently implemented the entry callback is invoked when
45  * transitioning from PM_STATE_ACTIVE to another state, and the exit
46  * callback is invoked when transitioning from a non-active state to
47  * PM_STATE_ACTIVE. This behavior may change in the future.
48  *
49  * @note These callbacks can be called from the ISR of the event
50  *       that caused the kernel exit from idling.
51  *
52  * @note It is not allowed to call @ref pm_notifier_unregister or
53  *       @ref pm_notifier_register from these callbacks because they are called
54  *       with the spin locked in those functions.
55  */
56 struct pm_notifier {
57 	sys_snode_t _node;
58 	/**
59 	 * Application defined function for doing any target specific operations
60 	 * for power state entry.
61 	 */
62 	void (*state_entry)(enum pm_state state);
63 	/**
64 	 * Application defined function for doing any target specific operations
65 	 * for power state exit.
66 	 */
67 	void (*state_exit)(enum pm_state state);
68 };
69 
70 #if defined(CONFIG_PM) || defined(__DOXYGEN__)
71 /**
72  * @brief Force usage of given power state.
73  *
74  * This function overrides decision made by PM policy forcing
75  * usage of given power state upon next entry of the idle thread.
76  *
77  * @note This function can only run in thread context
78  *
79  * @param cpu CPU index.
80  * @param info Power state which should be used in the ongoing
81  *	suspend operation.
82  */
83 bool pm_state_force(uint8_t cpu, const struct pm_state_info *info);
84 
85 /**
86  * @brief Register a power management notifier
87  *
88  * Register the given notifier from the power management notification
89  * list.
90  *
91  * @param notifier pm_notifier object to be registered.
92  */
93 void pm_notifier_register(struct pm_notifier *notifier);
94 
95 /**
96  * @brief Unregister a power management notifier
97  *
98  * Remove the given notifier from the power management notification
99  * list. After that this object callbacks will not be called.
100  *
101  * @param notifier pm_notifier object to be unregistered.
102  *
103  * @return 0 if the notifier was successfully removed, a negative value
104  * otherwise.
105  */
106 int pm_notifier_unregister(struct pm_notifier *notifier);
107 
108 /**
109  * @brief Gets the next power state that will be used.
110  *
111  * This function returns the next power state that will be used by the
112  * SoC.
113  *
114  * @param cpu CPU index.
115  * @return next pm_state_info that will be used
116  */
117 const struct pm_state_info *pm_state_next_get(uint8_t cpu);
118 
119 /**
120  * @brief Notify exit from kernel sleep.
121  *
122  * This function would notify exit from kernel idling if a corresponding
123  * pm_system_suspend() notification was handled and did not return
124  * PM_STATE_ACTIVE.
125  *
126  * This function should be called from the ISR context of the event
127  * that caused the exit from kernel idling.
128  *
129  * This is required for cpu power states that would require
130  * interrupts to be enabled while entering low power states. e.g. C1 in x86. In
131  * those cases, the ISR would be invoked immediately after the event wakes up
132  * the CPU, before code following the CPU wait, gets a chance to execute. This
133  * can be ignored if no operation needs to be done at the wake event
134  * notification.
135  */
136 void pm_system_resume(void);
137 
138 
139 /** @cond INTERNAL_HIDDEN */
140 __deprecated void z_pm_save_idle_exit(void);
141 /** @endcond */
142 
143 /**
144  * @}
145  */
146 
147 /**
148  * @brief System Power Management Hooks
149  * @defgroup subsys_pm_sys_hooks Hooks
150  * @ingroup subsys_pm_sys
151  * @{
152  */
153 
154 /**
155  * @brief Put processor into a power state.
156  *
157  * This function implements the SoC specific details necessary
158  * to put the processor into available power states.
159  *
160  * @param state Power state.
161  * @param substate_id Power substate id.
162  */
163 void pm_state_set(enum pm_state state, uint8_t substate_id);
164 
165 /**
166  * @brief Do any SoC or architecture specific post ops after sleep state exits.
167  *
168  * This function is a place holder to do any operations that may
169  * be needed to be done after sleep state exits. Currently it enables
170  * interrupts after resuming from sleep state. In future, the enabling
171  * of interrupts may be moved into the kernel.
172  *
173  * @param state Power state.
174  * @param substate_id Power substate id.
175  */
176 void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id);
177 
178 /**
179  * @}
180  */
181 
182 #else  /* CONFIG_PM */
183 
pm_notifier_register(struct pm_notifier * notifier)184 static inline void pm_notifier_register(struct pm_notifier *notifier)
185 {
186 	ARG_UNUSED(notifier);
187 }
188 
pm_notifier_unregister(struct pm_notifier * notifier)189 static inline int pm_notifier_unregister(struct pm_notifier *notifier)
190 {
191 	ARG_UNUSED(notifier);
192 
193 	return -ENOSYS;
194 }
195 
pm_state_next_get(uint8_t cpu)196 static inline const struct pm_state_info *pm_state_next_get(uint8_t cpu)
197 {
198 	ARG_UNUSED(cpu);
199 
200 	return NULL;
201 }
z_pm_save_idle_exit(void)202 static inline void z_pm_save_idle_exit(void)
203 {
204 }
205 
pm_system_resume(void)206 static inline void pm_system_resume(void)
207 {
208 }
209 
210 #endif /* CONFIG_PM */
211 
212 #ifdef __cplusplus
213 }
214 #endif
215 
216 #endif /* ZEPHYR_INCLUDE_PM_PM_H_ */
217