Only set a cpu as active (on pm subsystem) when the cpu is effectively
initialized. We cannot assume on pm subsystem that all cpus were
initialized since when the option CONFIG_SMP_BOOT_DELAY is used cpus are
initialized on demand by the application.
Note that once cpus are properly initialized the subystem is able to track
their status.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Events in the power-management policy context are defined as any source
that will wake up the system at a known time in the future. By
registering such event, the policy manager will be able to decide wether
certain power states are worth entering or not.
Events will bypass the ticks argument received by the policy manager if
they occur earlier.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Latency is always specified in microseconds, so apend `us` to the
relevant variables. Also, make it clear that latency request structures
are private (they are just exposed publicly to allow static allocation).
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Until now iterable sections APIs have been part of the toolchain
(common) headers. They are not strictly related to a toolchain, they
just rely on linker providing support for sections. Most files relied on
indirect includes to access the API, now, it is included as needed.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Use iterable sections to handle devices list. This simplifies devices
implementation by using standard APIs.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The init infrastructure, found in `init.h`, is currently used by:
- `SYS_INIT`: to call functions before `main`
- `DEVICE_*`: to initialize devices
They are all sorted according to an initialization level + a priority.
`SYS_INIT` calls are really orthogonal to devices, however, the required
function signature requires a `const struct device *dev` as a first
argument. The only reason for that is because the same init machinery is
used by devices, so we have something like:
```c
struct init_entry {
int (*init)(const struct device *dev);
/* only set by DEVICE_*, otherwise NULL */
const struct device *dev;
}
```
As a result, we end up with such weird/ugly pattern:
```c
static int my_init(const struct device *dev)
{
/* always NULL! add ARG_UNUSED to avoid compiler warning */
ARG_UNUSED(dev);
...
}
```
This is really a result of poor internals isolation. This patch proposes
a to make init entries more flexible so that they can accept sytem
initialization calls like this:
```c
static int my_init(void)
{
...
}
```
This is achieved using a union:
```c
union init_function {
/* for SYS_INIT, used when init_entry.dev == NULL */
int (*sys)(void);
/* for DEVICE*, used when init_entry.dev != NULL */
int (*dev)(const struct device *dev);
};
struct init_entry {
/* stores init function (either for SYS_INIT or DEVICE*)
union init_function init_fn;
/* stores device pointer for DEVICE*, NULL for SYS_INIT. Allows
* to know which union entry to call.
*/
const struct device *dev;
}
```
This solution **does not increase ROM usage**, and allows to offer clean
public APIs for both SYS_INIT and DEVICE*. Note that however, init
machinery keeps a coupling with devices.
**NOTE**: This is a breaking change! All `SYS_INIT` functions will need
to be converted to the new signature. See the script offered in the
following commit.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
init: convert SYS_INIT functions to the new signature
Conversion scripted using scripts/utils/migrate_sys_init.py.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
manifest: update projects for SYS_INIT changes
Update modules with updated SYS_INIT calls:
- hal_ti
- lvgl
- sof
- TraceRecorderSource
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: devicetree: devices: adjust test
Adjust test according to the recently introduced SYS_INIT
infrastructure.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
tests: kernel: threads: adjust SYS_INIT call
Adjust to the new signature: int (*init_fn)(void);
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
When demand paging is enabled, only a minimal set of functions
are available at boot. Anything not marked as boot functions
would not be loading in memory at boot which would result in
page faults when jumping to those functions. However, at early
boot, demand paging has not been enabled yet. So we need to
mark necessary functions as boot functions so they are placed
in the correct linker section where they are loaded at boot.
Fixes#56414
Signed-off-by: Daniel Leung <daniel.leung@intel.com>
Add the `zephyr,pm-device-runtime-auto` flag to `pm.yaml` and
`struct pm_device`.
This flag is intended to signify to the boot system that device runtime
PM should be automatically enabled on the device after the init function
has run.
Only run `pm_device_runtime_auto_enable` function on a device if
initialisation succeeded. This prevents actions being run on devices
that are not ready.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Returning an error code when PM is not supported for a device only makes
writing drivers harder, as instead of checking for failures with `< 0`,
they also need to check for `-ENOTSUP`.
From the point of view of a driver, an `-ENOTSUP` return value is
equivalent to success, as if the device it is trying to turn on doesn't
support PM, by definition it is already enabled. This is equivalent to
the API behaviour when `CONFIG_PM_DEVICE_RUNTIME=n`.
Whether a device supports PM or not can still be determined at runtime
by inspecting the return code of `pm_device_runtime_enable` if
necessary.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Only run `pm_device_runtime_put` on the dependent domain if the original
claim operation succeeded. This fixes unbalanced operations when running
```
pm_device_runtime_get(dev);
pm_device_runtime_put(dev);
```
On a device that does not have PM enabled but does have a power domain.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
The z_set_timeout_expiry() function is a wrapper provided in the
timeout subsystem that has some corrections for timelicing. But the
suspend code doesn't care; by definition there are no active threads
that might be timeslicing at the point where the OS is suspending.
Use the lower-level timer driver API instead.
(z_set_timeout_expiry() is also about to disappear)
Signed-off-by: Andy Ross <andyross@google.com>
Check if device runtime is enabled in the beginning of
runtime_suspend to avoid unnecessary checks.
This does not change the current behavior.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Check if device runtime is enabled in the beginning of
pm_device_runtime_get to avoid unnecessary checks.
This does not change the current behavior.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Rework the implementation of `pm_device_children_action_run` to use the
common `device_supported_foreach` iterator.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
z_cpus_active count becomes incorrect when the state is
PM_STATE_RUNTIME_IDLE and CONFIG_PM_DEVICE is enabled.
Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
The PM subsystem should not call the PM control callbacks on
uninitialized devices when entering low-power states.
Signed-off-by: Corey Wharton <xodus7@cwharton.com>
To be able to call pm_device_runtime_put() from an IRQ context, move
from mutexes to semaphores and force the async path when the put
operation is called from an ISR.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
For the async operation move from condition variables to events to
reduce the dependency on the mutexes that cannot be used in IRQ
context.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Replace usage of CONFIG_MP_NUM_CPUS with CONFIG_MP_MAX_NUM_CPUS for
init and declaration as we phase out CONFIG_MP_NUM_CPUS usage.
Signed-off-by: Kumar Gala <kumar.gala@intel.com>
Change for loops of the form:
for (i = 0; i < CONFIG_MP_NUM_CPUS; i++)
...
to
unsigned int num_cpus = arch_num_cpus();
for (i = 0; i < num_cpus; i++)
...
We do the call outside of the for loop so that it only happens once,
rather than on every iteration.
Signed-off-by: Kumar Gala <kumar.gala@intel.com>
There is a typo in argument for the STATS_NAME_INIT_PARMS macro.
This causes an error during build.
The correct reference should be "pm_stats".
Signed-off-by: Steven Slupsky <sslupsky@gmail.com>
Current API allowed to get notified when the maximum system latency
changes, however, a single callback was allowed. The design was intended
for SoC specific actions when latency changes. However, in some cases
drivers may also want to know the current maximum latency to perform
local actions if other parts of the system modify it.
This patch updates the API with a pair of subscribe/unsubscribe calls to
achieve such goal. Tests have been updated to show how the API can be
used.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
When new latency requirements are introduced/updated, the microseconds
value gets converted down to ticks. Ticks usually have a coarse
resolution compared to the microseconds scale. This is fine for making
PM state change decisions, however, when getting notified about latency
changes, we may want to know the real value in microseconds, even if the
system rounds to ticks internally. This patch stores the value in both
us and ticks (in ticks to cache the conversion, really), so that the
user will get notified with precise latency values.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Check that the device we are trying to use has successfully powered up
when it is on a power domain. If it has not, release the request for the
power domain to be powered to ensure we do not have dangling requests.
As a result of this, `PM_DEVICE_ACTION_RESUME` will not be run on a
device if `PM_DEVICE_ACTION_TURN_ON` has already failed.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Store errors powering up devices in a flag in the PM struct. This is
required as the `pm->state` variable always transitions to
`PM_DEVICE_STATE_SUSPENDED`, even when `PM_DEVICE_ACTION_TURN_ON`
returns an error. Marking the transition as failed will allow the
transition logic in `pm_device_runtime_get` to detect the problem.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Add a new API used by arch to implement suspend-to-RAM (S2RAM).
The API is composed by a single function to save the CPU context on
suspend.
A CPU context is the arch-specific set of registers that must be
preserved on power-off (in retained RAM) to be able to resume the
execution from the point it was suspended without going through the
whole kernel startup stage.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
Update the internal power state tracking for `PM_DEVICE_ACTION_TURN_ON`
and `PM_DEVICE_ACTION_TURN_OFF` even when the transition function fails.
Just because the driver couldn't perform some action does not mean the
device is still powered/unpowered.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Add state checking to every transition to ensure that the device is in
the state we think it is before running the action.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
PM_DEVICE_ACTION_FORCE_SUSPEND has been equivalent to
PM_DEVICE_ACTION_SUSPEND for a while. Release notes for Zephyr 2.7
mentioned its removal (see 76702e8ff3) but
for some reason it was kept.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Sometimes we want to entirely decouple the system PM from the device PM,
leaving the devices to manage its own power states using the runtime PM.
This is currently not possible because the suspend / resume code path is
triggering the device PM hooks even when the runtime PM is enabled.
Introduce a new PM_DEVICE_RUNTIME_EXCLUSIVE symbol to allow the platform
to skip the device PM triggers on suspend / resume.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
_current_cpu is a macro that expands to an assert that checks if the
current context can be migrated to a another cpu. Since this
pm_system_suspend() is called from the idle thread (each cpu has its
own) and with locked this check is redundant. Just use
arch_curr_cpu() to avoid it.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
pm_system_resume() can be called from the idle thread with
interruptions unmasked. In this situation, _current_cpu will call
z_smp_cpu_mobile() that will return true and cause an assert.
In this function we don't need to check if the current context can be
preempted, we just need the information about which cpu is executing
it.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Files including <zephyr/kernel.h> do not have to include
<zephyr/zephyr.h>, a shim to <zephyr/kernel.h>.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Adds a helper function to query whether a device is currently powered.
This can be used to determine if the chip can be initialised now, or if
it needs to be deferred.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
Return `-ENOTSUP` on calls to device_runtime functions if the underlying
device does not support power management.
Fixes#45648.
Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
There is a race condition in a multicore system that happens when the
idle thread in a CPU checks if the state was forced, if not it will
call the policy manager. If a secondary core forces a state after that
this point the value returned by the policy will be rewritten.
Another case is, if a state is forced while a CPU is sleeping,
when this CPU resumes, the forced bit is cleared and the forced state
is never be used.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
In pm_system_suspend there is a goto label that is supposed to be used
to do cleanup before exit the function but it is not doing anything
right now. Just remove it.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
In order to bring consistency in-tree, migrate all subsystems code to
the new prefix <zephyr/...>. Note that the conversion has been scripted,
refer to zephyrproject-rtos#45388 for more details.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Add API to add devices to a power domain in runtime. The number of
devices that can be added is defined in build time.
The script gen_handles.py will check the number defined in
`CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC` to resize the handles vector,
adding empty slots in the supported sector to be used later.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
The autoconf.h header is not required because the definitions present in
the file are exposed using the compiler `-imacros` flag.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Add a new API that allows to register a callback that is called when the
maximum latency value changes. This can be used by SoC code to perform
actions based on certain latency values.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
Add a new API that allows to configure maximum latency requirements.
When the policy manager computes the next state, it will check if the
state brings too much latency based on requirements. This can be useful,
for example, if a certain driver or the application want a system to
respond fast, since any low power state that brings too much latency
will not be used.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The state lock get/put calls should always be balanced: first call get
and then put. Add an assertion in case lock counter is about to go
negative, indicating a programming error.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
The pm_constraint_* APIs were effectively used by the policy manager
only. This patch renames the API to the policy namespace and makes its
naming more explicit:
- pm_constraint_set -> pm_policy_state_lock_get()
- pm_constraint_release -> pm_policy_state_lock_put()
- pm_constraint_get -> pm_policy_state_lock_is_active()
The reason for these changes is that constraints can be of many types:
allow/disallow states, impose latency requirements, etc. The new naming
also makes explicit that the API calls will influence the PM policy
behavior.
All drivers and documentation have been updated accordingly.
Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>