Skip to content

Commit 34106e6

Browse files
Declan Snydernordic-krch
authored andcommitted
[nrf fromtree] pm: Add constraint lists and APIs
Some pieces of the system may have custom types of constraints that they define based on different effects and reasons than just the standard "zephyr,disabling-states". To avoid every single one of these component reinventing the wheel, make some common APIs to handle these type of custom constraint lists. Signed-off-by: Declan Snyder <[email protected]> (cherry picked from commit a4225b1)
1 parent b4f39bc commit 34106e6

File tree

5 files changed

+143
-11
lines changed

5 files changed

+143
-11
lines changed

include/zephyr/pm/policy.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,36 @@ void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id);
125125
*/
126126
void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id);
127127

128+
/**
129+
* @brief Apply power state constraints by locking the specified states.
130+
*
131+
* This function locks all power states specified in the union of all constraints
132+
* in the provided constraint list. Each constraint in the set contributes to
133+
* determining which power states should be locked (not allowed), by increasing
134+
* a reference count just as if pm_policy_state_lock_get was called on each constraints'
135+
* states individually.
136+
*
137+
* @param constraints Pointer to the power state constraints set to apply.
138+
*
139+
* @see pm_policy_state_constraints_put()
140+
*/
141+
void pm_policy_state_constraints_get(struct pm_state_constraints *constraints);
142+
143+
/**
144+
* @brief Remove power state constraints by unlocking the specified states.
145+
*
146+
* This function unlocks all power states that were previously locked by a
147+
* corresponding call to pm_policy_state_constraints_get() with the same
148+
* constraint set. The function decreases the lock counter for each affected
149+
* power state specified in the union of all constraints in the list, just as
150+
* if pm_policy_state_put was called on all the constraints' states individually.
151+
*
152+
* @param constraints Pointer to the power state constraints set to remove.
153+
*
154+
* @see pm_policy_state_constraints_get()
155+
*/
156+
void pm_policy_state_constraints_put(struct pm_state_constraints *constraints);
157+
128158
/**
129159
* @brief Check if a power state lock is active (not allowed).
130160
*

include/zephyr/pm/state.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ struct pm_state_info {
168168
};
169169

170170
/**
171-
* Power state information needed to lock a power state.
171+
* Information needed to be able to reference a power state as a constraint
172+
* on some device or system functions.
172173
*/
173174
struct pm_state_constraint {
174175
/**
@@ -185,6 +186,16 @@ struct pm_state_constraint {
185186
uint8_t substate_id;
186187
};
187188

189+
/**
190+
* Collection of multiple power state constraints.
191+
*/
192+
struct pm_state_constraints {
193+
/** Array of power state constraints */
194+
struct pm_state_constraint *list;
195+
/** Number of constraints in the list */
196+
size_t count;
197+
};
198+
188199
/** @cond INTERNAL_HIDDEN */
189200

190201
/**
@@ -359,6 +370,54 @@ struct pm_state_constraint {
359370
Z_PM_STATE_FROM_DT_CPU, (), node_id) \
360371
}
361372

373+
/**
374+
* @brief initialize a device pm constraint with information from devicetree.
375+
*
376+
* @param node_id Node identifier.
377+
*/
378+
#define PM_STATE_CONSTRAINT_INIT(node_id) \
379+
{ \
380+
.state = PM_STATE_DT_INIT(node_id), \
381+
.substate_id = DT_PROP_OR(node_id, substate_id, 0), \
382+
}
383+
384+
#define Z_PM_STATE_CONSTRAINT_REF(node_id, phandle, idx) \
385+
PM_STATE_CONSTRAINT_INIT(DT_PHANDLE_BY_IDX(node_id, phandle, idx))
386+
387+
#define Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, phandles) \
388+
_CONCAT_4(node_id, _, phandles, _constraints)
389+
390+
/**
391+
* @brief Define a list of power state constraints from devicetree.
392+
*
393+
* This macro creates an array of pm_state_constraint structures initialized
394+
* with power state information from the specified devicetree property.
395+
*
396+
* @param node_id Devicetree node identifier.
397+
* @param prop Property name containing the list of power state phandles.
398+
*/
399+
#define PM_STATE_CONSTRAINTS_LIST_DEFINE(node_id, prop) \
400+
struct pm_state_constraint Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, prop)[] = \
401+
{ \
402+
DT_FOREACH_PROP_ELEM_SEP(node_id, prop, Z_PM_STATE_CONSTRAINT_REF, (,)) \
403+
}
404+
405+
/**
406+
* @brief Get power state constraints structure from devicetree.
407+
*
408+
* This macro creates a structure containing a pointer to the constraints list
409+
* and the count of constraints, suitable for initializing a pm_state_constraints
410+
* structure. Must be used after the PM_STATE_CONSTRAINTS_LIST_DEFINE call for the same
411+
* @param prop to refer to the array of constraints.
412+
*
413+
* @param node_id Devicetree node identifier.
414+
* @param prop Property name containing the list of power state phandles.
415+
*/
416+
#define PM_STATE_CONSTRAINTS_GET(node_id, prop) \
417+
{ \
418+
.list = Z_PM_STATE_CONSTRAINTS_LIST_NAME(node_id, prop), \
419+
.count = DT_PROP_LEN(node_id, prop), \
420+
}
362421

363422
#if defined(CONFIG_PM) || defined(__DOXYGEN__)
364423
/**
@@ -403,6 +462,18 @@ const char *pm_state_to_str(enum pm_state state);
403462
* @return 0 on success, -EINVAL if the string is invalid or NULL.
404463
*/
405464
int pm_state_from_str(const char *name, enum pm_state *out);
465+
466+
/**
467+
* @brief Check if a power management constraint matches any in a set of constraints.
468+
*
469+
* @param constraints Pointer to the power state constraints structure.
470+
* @param match The constraint to match against.
471+
*
472+
* @return true if the constraint matches, false otherwise.
473+
*/
474+
bool pm_state_in_constraints(const struct pm_state_constraints *constraints,
475+
const struct pm_state_constraint match);
476+
406477
/**
407478
* @}
408479
*/
@@ -428,6 +499,14 @@ static inline const struct pm_state_info *pm_state_get(uint8_t cpu,
428499
return NULL;
429500
}
430501

502+
static inline bool pm_state_in_constraints(struct pm_state_constraints *constraints,
503+
struct pm_state_constraint match)
504+
{
505+
ARG_UNUSED(constraints);
506+
ARG_UNUSED(match);
507+
508+
return false;
509+
}
431510
#endif /* CONFIG_PM */
432511

433512
#ifdef __cplusplus

subsys/pm/policy/policy_device_lock.c

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,6 @@ struct pm_state_device_constraint {
2424
*/
2525
#define PM_CONSTRAINTS_NAME(node_id) _CONCAT(__devicepmconstraints_, node_id)
2626

27-
/**
28-
* @brief initialize a device pm constraint with information from devicetree.
29-
*
30-
* @param node_id Node identifier.
31-
*/
32-
#define PM_STATE_CONSTRAINT_INIT(node_id) \
33-
{ \
34-
.state = PM_STATE_DT_INIT(node_id), \
35-
.substate_id = DT_PROP_OR(node_id, substate_id, 0), \
36-
}
3727

3828
/**
3929
* @brief Helper macro to define a device pm constraints.

subsys/pm/policy/policy_state_lock.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id)
6565
#endif
6666
}
6767

68+
void pm_policy_state_constraints_get(struct pm_state_constraints *constraints)
69+
{
70+
for (int i = 0; i < constraints->count; i++) {
71+
pm_policy_state_lock_get(constraints->list[i].state,
72+
constraints->list[i].substate_id);
73+
}
74+
}
75+
6876
void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id)
6977
{
7078
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state)
@@ -84,6 +92,14 @@ void pm_policy_state_lock_put(enum pm_state state, uint8_t substate_id)
8492
#endif
8593
}
8694

95+
void pm_policy_state_constraints_put(struct pm_state_constraints *constraints)
96+
{
97+
for (int i = 0; i < constraints->count; i++) {
98+
pm_policy_state_lock_put(constraints->list[i].state,
99+
constraints->list[i].substate_id);
100+
}
101+
}
102+
87103
bool pm_policy_state_lock_is_active(enum pm_state state, uint8_t substate_id)
88104
{
89105
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_power_state)

subsys/pm/state.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,20 @@ int pm_state_from_str(const char *name, enum pm_state *out)
152152

153153
return 0;
154154
}
155+
156+
bool pm_state_in_constraints(const struct pm_state_constraints *constraints,
157+
const struct pm_state_constraint match)
158+
{
159+
struct pm_state_constraint *constraints_list = constraints->list;
160+
size_t num_constraints = constraints->count;
161+
bool match_found = false;
162+
163+
for (int i = 0; i < num_constraints; i++) {
164+
enum pm_state state = constraints_list[i].state;
165+
uint8_t substate = constraints_list[i].substate_id;
166+
167+
match_found |= ((state == match.state) && (substate == match.substate_id));
168+
}
169+
170+
return match_found;
171+
}

0 commit comments

Comments
 (0)