Implement constraint API as weak symbols so applications or platform
can override them. Constraints are a high-level abstraction to inhibit
the power subsystem of using certain power states. Some platforms can
have their own way to set/release constraints in their drivers that
are not part of Zephyr's code base.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
PM_DEVICE_STATE_RESUMING and PM_DEVICE_STATE_SUSPENDING
are transitional states and are only used in device runtime. Remove it
and use device flag to keep track of a transition.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The runtime API is referenced count and uses a uint32_t.
Avoid underflow when dealing with put requests.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Return 0 in cases where the request does not trigger a device state
change, only incremented or to decremented the reference count.
Fixes#37821
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Suspend devices when the system goes to STATE_SOFT_OFF.
This state was not triggering any device power management. This should
at least suspend devices as it is done for SUSPEND_TO_RAM and
SUSPEND_TO_DISK.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
_pm_devices, pm_suspend_devices, pm_low_power_devices and
pm_resume_devices are only used if CONFIG_PM_DEVICE is defined and not
CONFIG_PM.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Introduce a new API to allow devices capable of wake up the system
register themselves was wake up sources. This permits applications to
select the most appropriate way to wake up the system when it is
suspended.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Just using a simple atomic for flags instead of using an array.
While is neat using ATOMIC_DEFINE for future proof. The reality is
that it brings some problem for the wakeup source implementation
that needs to statically initialize it during the device definition.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Use the internal function z_device_get_all_static helper function
instead of using __device_start and __device_end directly. Some other
minor adjustments have been done (e.g. reduce *dev scope to the for
loop). An issue on the range of the for loop in _pm_devices has also
been fixed.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The shared _pm_devices function used should_suspend check function to
see if a device had to be suspended or not. Some of the logic inside
that function was redundant since the pm_device_state_set function
already performs similar checks, e.g. if the device is already at the
given state or the state transition is not supported it will return
error codes appropriately.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
A device that is turned off should not be suspended. A device that has
been turned off can only be resumed. This action is currently forbidden
by the "should_suspend" function in the device PM code.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Add support for FORCE_SUSPEND and LOW_POWER actions. Even though these
actions have no clear meaning, they are added for compatibility until
their associated states are discussed. Their usage in new code should be
discouraged until the associated states are clarified.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
If a device does not support, for example, the suspend action the
subsystem should just ignore the device.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Instead of passing target states, use actions for device PM control.
Actions represent better the meaning of the callback argument.
Furthermore, they are more future proof as they can be suitable for
other PM actions that have no direct mapping to a state. If we compare
with Linux, we could have a multi-stage suspend/resume. Such scenario
would not have a good mapping when using target states.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The verb tense for the suspended state was not consistent with other
states. The likely reason: state was being used as a command/action.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
If the device is already at the given state, do not call the device PM
control function. This makes sure that devices are only called to change
from one state to another.
Even though asynchronous device PM is completely broken, transitional
states are considered too.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Improve the docstrings of the pm_device_state_set function and change to
shorter argument variable names.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Since the state is no longer modified by the device PM callback, just
use the state value.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The device PM subsystem already holds the device state, so there is no
need to keep duplicates inside the device. The pm_device_state_get has
been refactored to just return the device state. Note that this is still
not safe, but the same applied to the previous implementation. This
problem will be addressed later.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Busy check APIs now return boolean type. Due to that change, the
function names have also been adjusted. The common name pattern for
boolean check type APIs is "PREFIX_is_CONDITION". For example,
"pm_device_is_busy". pm_device_busy_check has been renamed to
pm_device_is_busy and pm_device_any_busy_check to pm_device_is_any_busy.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
- Use an enum for the available flags
- Use ATOMIC_DEFINE macro to declare the flag bit field
- Improve naming
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The following device busy APIs:
- device_busy_set()
- device_busy_clear()
- device_busy_check()
- device_any_busy_check()
were used for device PM, so they have been moved to the pm subsystem.
This means they are now prefixed with `pm_` and are defined in
`pm/device.h`.
If device PM is not enabled dummy functions are now provided that do
nothing or return `-ENOSYS`, meaning that the functionality is not
available.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
SoC hooks are defined as weak functions for the case where they are
not implemented by a SoC. The problem that may happen is when an
application define it as weak as well. In this case, no compilation
error is issued but the version that will be used depends on the build
order. Just remove the weak placeholder implementation.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
cc13x2_cc26x2 had its own power policy that was implementing the same
logic available in the default residency policy. Also, this policy was
unnecessarily setting up a timeout to wakeup the system. This is not
necessary, the power subsystem takes care of this.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The callback is not used anymore, so just delete it from the pm_control
callback signature.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The callback used by the device runtime PM can be easily replaced by a
simple state set after calling the state set/get calls. Broadcast logic
is simplified too, leading to the same previous behavior.
Since this is the only place where this callback was used, it can now be
removed from all devices and so pm_control callback signature
simplified.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Move all PM_DEVICE_STATE_* definitions to an enum. The
PM_DEVICE_STATE_SET and PM_DEVICE_STATE_GET definitions have been kept
out of the enum since they do not represent any state. However, their
name has not been changed since they will be removed soon.
All drivers and tests have been adjusted accordingly.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Policy manager header has to be in the include for applications.
Also it had several function prototypes that are not part of the policy.
These functions were moved from the policy header to a dedicated private
header.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
When a device is defined a new pointer to a device will be created in
the "z_pm_device_slots" region, effectively creating a device array with
the same size as the number of system devices. This array is then used
by the device PM subsystem to keep track of suspended devices during
power transitions.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
It was just making the code hard to read. Also it was not following
the code guideline because the type was not telling us the sign
and size.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
z_pm_core_devices was hack to set some priority between devices. It
was doing it hardcoding some devices that were the first to bring up
and the last to power down. Remove it and use the same list used to
initialize devices.
Fixes#34214
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
pm_device_runtime_state_set takes care of the check the reference count
and take the right action. It is not necessary check it in
pm_device_request.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Assuming that pm_device_state_set is synchronous it is possible to
simplify the mutex usage. Now there are two places where the lock is
held, one in the worqueue handler and other in pm_device_request to
cover the synchronous path. It is no longer needed held the lock in the
pm_device_state_set callback and not needed to wait on the conditional
variable after set the state in the synchronous path.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Most APIs have the default synchronous and an asynchronous version
with the sufix _async because that is the most common use.
All devices in tree right now are using the synchronous version, so
just change it to be consistent with the rest of the system.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Since we are using mutex to protect critical sections and mutexes are
reentrant, it is possible to get rid of atomic for the state because
we can lock the mutex in device_pm_callback.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Protect critical sections using the mutex.
The mutex is required to use the conditional variable and since we
need to atomically check the pm state and the workqueue before wait
the condition, it is necessary to protect them using the same mutex.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Protect critical sessions using the spinlock available. The atomic
usage was not properly protecting the critical section and was
possible to have a race condition between the usage check and state
set.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Add a function that properly uses a mutex to check a condition before
wait on the conditional variable.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The time necessary to resume from a power state has to be added to the
minimal residency time to check if there is enough time to go to a
particular state.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Avoid confusion with device runtime idle pm states and just use device
pm states.
This simplify the code a little bit and prepare the ground for having
a better definition of device pm states. Right now this code needed to
hijack two transitional states to not break the current code logic but
the goal is avoid it and have everything in one single place.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Devices may be initialized but started powered down for this reason
is necessary to power a device on if requested even if in pre-kernel
state.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Device pm runtime was using semaphore to protect critical section but
enable / disable functions were waiting on the semaphore. So, just
replace it with a spin lock.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The sync API was using k_poll_signal and in certain conditions is
possible multiple threads waiting on a signal leading to an undefined
behavior.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The context parameter used across device power management is
actually the power state. Just use it and avoid a lot of
unnecessary casts.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Currently when the system goes to sleep it asks *all* devices that
support PM to suspend or go to a low power state, and the system wakes
up it put *all* suspended devices in active state, even if a device
was already suspended and not being used.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Use `pm_device_*` prefix for the device runtime PM API. This adds the
API to the `pm` namespace, making it clear part of the PM subsystem.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>