pm: policy: move constraints to policy API

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>
This commit is contained in:
Gerard Marull-Paretas 2022-01-20 16:06:28 +01:00 committed by Carles Cufí
commit 5a71eeb35c
23 changed files with 191 additions and 195 deletions

View file

@ -216,9 +216,9 @@ disable sleep state 2 while polling:
.. code-block:: c .. code-block:: c
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
<code that calls uart_poll_in() and expects input at any point in time> <code that calls uart_poll_in() and expects input at any point in time>
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
References References

View file

@ -242,9 +242,9 @@ disable sleep state 2 while polling:
.. code-block:: c .. code-block:: c
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
<code that calls uart_poll_in() and expects input at any point in time> <code that calls uart_poll_in() and expects input at any point in time>
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
References References

View file

@ -222,9 +222,9 @@ disable sleep state 2 while polling:
.. code-block:: c .. code-block:: c
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
<code that calls uart_poll_in() and expects input at any point in time> <code that calls uart_poll_in() and expects input at any point in time>
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
References References

View file

@ -38,19 +38,6 @@ The list of available power states is defined by :c:enum:`pm_state`. In
general power states with higher indexes will offer greater power savings and general power states with higher indexes will offer greater power savings and
have higher wake latencies. have higher wake latencies.
.. _pm_constraints:
Power States Constraint
=======================
The power management subsystem allows different Zephyr components and
applications to set constraints on various power states preventing the
system from transitioning into these states. This can be used by devices when
executing tasks in background to prevent the system from going to a specific
state where it would lose context. Constraints can be set using the
:c:func:`pm_constraint_set`, released using :c:func:`pm_constraint_release` and
checked using the :c:func:`pm_constraint_get`.
Power Management Policies Power Management Policies
========================= =========================
@ -61,7 +48,7 @@ The power management subsystem supports the following power management policies:
The policy manager is responsible for informing the power subsystem which The policy manager is responsible for informing the power subsystem which
power state the system should transition to based on states defined by the power state the system should transition to based on states defined by the
platform and possible runtime :ref:`constraints<pm_constraints>` platform and other constraints such as a list of allowed states.
More details on the states definition can be found in the More details on the states definition can be found in the
:dtcompatible:`zephyr,power-state` binding documentation. :dtcompatible:`zephyr,power-state` binding documentation.
@ -94,3 +81,12 @@ remaining time for the next scheduled timeout.
An example of an application that defines its own policy can be found in An example of an application that defines its own policy can be found in
:zephyr_file:`tests/subsys/pm/power_mgmt/`. :zephyr_file:`tests/subsys/pm/power_mgmt/`.
Policy and Power States
------------------------
The power management subsystem allows different Zephyr components and
applications to configure the policy manager to block system from transitioning
into certain power states. This can be used by devices when executing tasks in
background to prevent the system from going to a specific state where it would
lose context.

View file

@ -13,10 +13,10 @@ States
.. doxygengroup:: subsys_pm_states .. doxygengroup:: subsys_pm_states
Constraints Policy
=========== ======
.. doxygengroup:: subsys_pm_sys_constraint .. doxygengroup:: subsys_pm_sys_policy
Hooks Hooks
===== =====

View file

@ -10,7 +10,7 @@
#include <device.h> #include <device.h>
#include <drivers/entropy.h> #include <drivers/entropy.h>
#include <irq.h> #include <irq.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <pm/device.h> #include <pm/device.h>
#include <sys/ring_buffer.h> #include <sys/ring_buffer.h>
@ -101,7 +101,7 @@ static int entropy_cc13xx_cc26xx_get_entropy(const struct device *dev,
unsigned int key = irq_lock(); unsigned int key = irq_lock();
if (!data->constrained) { if (!data->constrained) {
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
data->constrained = true; data->constrained = true;
} }
irq_unlock(key); irq_unlock(key);
@ -146,7 +146,7 @@ static void entropy_cc13xx_cc26xx_isr(const struct device *dev)
if (cnt != sizeof(num)) { if (cnt != sizeof(num)) {
#ifdef CONFIG_PM #ifdef CONFIG_PM
if (data->constrained) { if (data->constrained) {
pm_constraint_release( pm_policy_state_lock_put(
PM_STATE_STANDBY); PM_STATE_STANDBY);
data->constrained = false; data->constrained = false;
} }
@ -290,7 +290,7 @@ static int entropy_cc13xx_cc26xx_init(const struct device *dev)
#if defined(CONFIG_PM) #if defined(CONFIG_PM)
Power_setDependency(PowerCC26XX_PERIPH_TRNG); Power_setDependency(PowerCC26XX_PERIPH_TRNG);
/* Stay out of standby until buffer is filled with entropy */ /* Stay out of standby until buffer is filled with entropy */
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
data->constrained = true; data->constrained = true;
/* Register notification function */ /* Register notification function */
Power_registerNotify(&data->post_notify, Power_registerNotify(&data->post_notify,

View file

@ -18,7 +18,7 @@
#include <sys/util.h> #include <sys/util.h>
#include <errno.h> #include <errno.h>
#include <soc.h> #include <soc.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <stm32_ll_bus.h> #include <stm32_ll_bus.h>
#include <stm32_ll_rcc.h> #include <stm32_ll_rcc.h>
#include <stm32_ll_rng.h> #include <stm32_ll_rng.h>
@ -246,7 +246,7 @@ static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len)
available = available - len; available = available - len;
if ((available <= rngp->threshold) if ((available <= rngp->threshold)
&& !LL_RNG_IsEnabledIT(entropy_stm32_rng_data.rng)) { && !LL_RNG_IsEnabledIT(entropy_stm32_rng_data.rng)) {
pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE);
LL_RNG_EnableIT(entropy_stm32_rng_data.rng); LL_RNG_EnableIT(entropy_stm32_rng_data.rng);
} }
@ -300,7 +300,7 @@ static void stm32_rng_isr(const void *arg)
byte); byte);
if (ret < 0) { if (ret < 0) {
LL_RNG_DisableIT(entropy_stm32_rng_data.rng); LL_RNG_DisableIT(entropy_stm32_rng_data.rng);
pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE);
} }
k_sem_give(&entropy_stm32_rng_data.sem_sync); k_sem_give(&entropy_stm32_rng_data.sem_sync);
@ -512,7 +512,7 @@ static int entropy_stm32_rng_init(const struct device *dev)
* rng pool is being populated. The ISR will release the constraint again * rng pool is being populated. The ISR will release the constraint again
* when the rng pool is filled. * when the rng pool is filled.
*/ */
pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE);
LL_RNG_EnableIT(dev_data->rng); LL_RNG_EnableIT(dev_data->rng);

View file

@ -9,7 +9,7 @@
#include <kernel.h> #include <kernel.h>
#include <drivers/i2c.h> #include <drivers/i2c.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/pm.h> #include <pm/policy.h>
#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
#include <logging/log.h> #include <logging/log.h>
@ -198,7 +198,7 @@ static int i2c_cc13xx_cc26xx_transfer(const struct device *dev,
k_sem_take(&data->lock, K_FOREVER); k_sem_take(&data->lock, K_FOREVER);
#ifdef CONFIG_PM #ifdef CONFIG_PM
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
#endif #endif
for (int i = 0; i < num_msgs; i++) { for (int i = 0; i < num_msgs; i++) {
@ -222,7 +222,7 @@ static int i2c_cc13xx_cc26xx_transfer(const struct device *dev,
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
#endif #endif
k_sem_give(&data->lock); k_sem_give(&data->lock);

View file

@ -10,7 +10,7 @@
#include <errno.h> #include <errno.h>
#include <sys/__assert.h> #include <sys/__assert.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <drivers/uart.h> #include <drivers/uart.h>
#include <driverlib/ioc.h> #include <driverlib/ioc.h>
@ -254,7 +254,7 @@ static void uart_cc13xx_cc26xx_irq_tx_enable(const struct device *dev)
* standby mode instead, since it is the power state that * standby mode instead, since it is the power state that
* would interfere with a transfer. * would interfere with a transfer.
*/ */
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
data->tx_constrained = true; data->tx_constrained = true;
} }
#endif #endif
@ -272,7 +272,7 @@ static void uart_cc13xx_cc26xx_irq_tx_disable(const struct device *dev)
struct uart_cc13xx_cc26xx_data *data = dev->data; struct uart_cc13xx_cc26xx_data *data = dev->data;
if (data->tx_constrained) { if (data->tx_constrained) {
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
data->tx_constrained = false; data->tx_constrained = false;
} }
#endif #endif
@ -298,7 +298,7 @@ static void uart_cc13xx_cc26xx_irq_rx_enable(const struct device *dev)
* standby. * standby.
*/ */
if (!data->rx_constrained) { if (!data->rx_constrained) {
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
data->rx_constrained = true; data->rx_constrained = true;
} }
#endif #endif
@ -314,7 +314,7 @@ static void uart_cc13xx_cc26xx_irq_rx_disable(const struct device *dev)
struct uart_cc13xx_cc26xx_data *data = dev->data; struct uart_cc13xx_cc26xx_data *data = dev->data;
if (data->rx_constrained) { if (data->rx_constrained) {
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
data->rx_constrained = false; data->rx_constrained = false;
} }
#endif #endif

View file

@ -11,7 +11,6 @@
#include <drivers/uart.h> #include <drivers/uart.h>
#include <kernel.h> #include <kernel.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/pm.h>
#include <pm/policy.h> #include <pm/policy.h>
#include <soc.h> #include <soc.h>
@ -57,7 +56,7 @@ void uart1_wui_isr(const struct device *gpio, struct gpio_callback *cb,
* The pm state of it8xxx2 chip only supports standby, so here we * The pm state of it8xxx2 chip only supports standby, so here we
* can directly set the constraint for standby. * can directly set the constraint for standby.
*/ */
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
k_work_reschedule(&uart_console_data->rx_refresh_timeout_work, delay); k_work_reschedule(&uart_console_data->rx_refresh_timeout_work, delay);
#endif #endif
} }
@ -77,7 +76,7 @@ void uart2_wui_isr(const struct device *gpio, struct gpio_callback *cb,
* The pm state of it8xxx2 chip only supports standby, so here we * The pm state of it8xxx2 chip only supports standby, so here we
* can directly set the constraint for standby. * can directly set the constraint for standby.
*/ */
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
k_work_reschedule(&uart_console_data->rx_refresh_timeout_work, delay); k_work_reschedule(&uart_console_data->rx_refresh_timeout_work, delay);
#endif #endif
} }
@ -117,7 +116,7 @@ static void uart_it8xxx2_rx_refresh_timeout(struct k_work *work)
{ {
ARG_UNUSED(work); ARG_UNUSED(work);
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
} }
#endif #endif
#endif /* CONFIG_PM_DEVICE */ #endif /* CONFIG_PM_DEVICE */

View file

@ -13,7 +13,7 @@
#include <device.h> #include <device.h>
#include <drivers/uart.h> #include <drivers/uart.h>
#include <drivers/clock_control.h> #include <drivers/clock_control.h>
#include <pm/pm.h> #include <pm/policy.h>
#ifdef CONFIG_PINCTRL #ifdef CONFIG_PINCTRL
#include <drivers/pinctrl.h> #include <drivers/pinctrl.h>
#endif #endif
@ -38,7 +38,7 @@ struct mcux_lpuart_data {
void *cb_data; void *cb_data;
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
bool pm_constraint_on; bool pm_state_lock_on;
bool tx_poll_stream_on; bool tx_poll_stream_on;
bool tx_int_stream_on; bool tx_int_stream_on;
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -46,23 +46,23 @@ struct mcux_lpuart_data {
}; };
#ifdef CONFIG_PM #ifdef CONFIG_PM
static void mcux_lpuart_pm_constraint_set(const struct device *dev) static void mcux_lpuart_pm_policy_state_lock_get(const struct device *dev)
{ {
struct mcux_lpuart_data *data = dev->data; struct mcux_lpuart_data *data = dev->data;
if (!data->pm_constraint_on) { if (!data->pm_state_lock_on) {
data->pm_constraint_on = true; data->pm_state_lock_on = true;
pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
static void mcux_lpuart_pm_constraint_release(const struct device *dev) static void mcux_lpuart_pm_policy_state_lock_put(const struct device *dev)
{ {
struct mcux_lpuart_data *data = dev->data; struct mcux_lpuart_data *data = dev->data;
if (data->pm_constraint_on) { if (data->pm_state_lock_on) {
data->pm_constraint_on = false; data->pm_state_lock_on = false;
pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -103,7 +103,7 @@ static void mcux_lpuart_poll_out(const struct device *dev, unsigned char c)
*/ */
if (!data->tx_poll_stream_on && !data->tx_int_stream_on) { if (!data->tx_poll_stream_on && !data->tx_int_stream_on) {
data->tx_poll_stream_on = true; data->tx_poll_stream_on = true;
mcux_lpuart_pm_constraint_set(dev); mcux_lpuart_pm_policy_state_lock_get(dev);
/* Enable TC interrupt */ /* Enable TC interrupt */
LPUART_EnableInterrupts(config->base, LPUART_EnableInterrupts(config->base,
kLPUART_TransmissionCompleteInterruptEnable); kLPUART_TransmissionCompleteInterruptEnable);
@ -187,7 +187,7 @@ static void mcux_lpuart_irq_tx_enable(const struct device *dev)
data->tx_poll_stream_on = false; data->tx_poll_stream_on = false;
data->tx_int_stream_on = true; data->tx_int_stream_on = true;
/* Do not allow system to sleep while UART tx is ongoing */ /* Do not allow system to sleep while UART tx is ongoing */
mcux_lpuart_pm_constraint_set(dev); mcux_lpuart_pm_policy_state_lock_get(dev);
#endif #endif
LPUART_EnableInterrupts(config->base, mask); LPUART_EnableInterrupts(config->base, mask);
#ifdef CONFIG_PM #ifdef CONFIG_PM
@ -213,7 +213,7 @@ static void mcux_lpuart_irq_tx_disable(const struct device *dev)
* If transmission IRQ is no longer enabled, * If transmission IRQ is no longer enabled,
* transmission is complete. Release pm constraint. * transmission is complete. Release pm constraint.
*/ */
mcux_lpuart_pm_constraint_release(dev); mcux_lpuart_pm_policy_state_lock_put(dev);
irq_unlock(key); irq_unlock(key);
#endif #endif
} }
@ -329,7 +329,7 @@ static void mcux_lpuart_isr(const struct device *dev)
LPUART_DisableInterrupts(config->base, LPUART_DisableInterrupts(config->base,
kLPUART_TransmissionCompleteInterruptEnable); kLPUART_TransmissionCompleteInterruptEnable);
data->tx_poll_stream_on = false; data->tx_poll_stream_on = false;
mcux_lpuart_pm_constraint_release(dev); mcux_lpuart_pm_policy_state_lock_put(dev);
} }
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -484,7 +484,7 @@ static int mcux_lpuart_init(const struct device *dev)
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
data->pm_constraint_on = false; data->pm_state_lock_on = false;
data->tx_poll_stream_on = false; data->tx_poll_stream_on = false;
data->tx_int_stream_on = false; data->tx_int_stream_on = false;
#endif #endif

View file

@ -12,7 +12,7 @@
#include <drivers/clock_control.h> #include <drivers/clock_control.h>
#include <kernel.h> #include <kernel.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <soc.h> #include <soc.h>
#include "soc_miwu.h" #include "soc_miwu.h"
#include "soc_power.h" #include "soc_power.h"
@ -35,11 +35,11 @@ struct uart_npcx_config {
const struct npcx_alt *alts_list; const struct npcx_alt *alts_list;
}; };
enum uart_pm_constraint_flag { enum uart_pm_policy_state_flag {
UART_PM_CONSTRAINT_TX_FLAG, UART_PM_POLICY_STATE_TX_FLAG,
UART_PM_CONSTRAINT_RX_FLAG, UART_PM_POLICY_STATE_RX_FLAG,
UART_PM_CONSTRAINT_FLAG_COUNT, UART_PM_POLICY_STATE_FLAG_COUNT,
}; };
/* Driver data */ /* Driver data */
@ -52,7 +52,7 @@ struct uart_npcx_data {
void *user_data; void *user_data;
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
ATOMIC_DEFINE(pm_constraint_flag, UART_PM_CONSTRAINT_FLAG_COUNT); ATOMIC_DEFINE(pm_policy_state_flag, UART_PM_POLICY_STATE_FLAG_COUNT);
#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED #ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED
struct k_work_delayable rx_refresh_timeout_work; struct k_work_delayable rx_refresh_timeout_work;
#endif #endif
@ -60,19 +60,19 @@ struct uart_npcx_data {
}; };
#if defined(CONFIG_PM) && defined(CONFIG_UART_INTERRUPT_DRIVEN) #if defined(CONFIG_PM) && defined(CONFIG_UART_INTERRUPT_DRIVEN)
static void uart_npcx_pm_constraint_set(struct uart_npcx_data *data, static void uart_npcx_pm_policy_state_lock_get(struct uart_npcx_data *data,
enum uart_pm_constraint_flag flag) enum uart_pm_policy_state_flag flag)
{ {
if (atomic_test_and_set_bit(data->pm_constraint_flag, flag) == 0) { if (atomic_test_and_set_bit(data->pm_policy_state_flag, flag) == 0) {
pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
static void uart_npcx_pm_constraint_rel(struct uart_npcx_data *data, static void uart_npcx_pm_policy_state_lock_put(struct uart_npcx_data *data,
enum uart_pm_constraint_flag flag) enum uart_pm_policy_state_flag flag)
{ {
if (atomic_test_and_clear_bit(data->pm_constraint_flag, flag) == 1) { if (atomic_test_and_clear_bit(data->pm_policy_state_flag, flag) == 1) {
pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
#endif /* defined(CONFIG_PM) && defined(CONFIG_UART_INTERRUPT_DRIVEN) */ #endif /* defined(CONFIG_PM) && defined(CONFIG_UART_INTERRUPT_DRIVEN) */
@ -151,7 +151,7 @@ static int uart_npcx_fifo_fill(const struct device *dev, const uint8_t *tx_data,
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct uart_npcx_data *data = dev->data; struct uart_npcx_data *data = dev->data;
uart_npcx_pm_constraint_set(data, UART_PM_CONSTRAINT_TX_FLAG); uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_TX_FLAG);
inst->UTBUF = tx_data[tx_bytes++]; inst->UTBUF = tx_data[tx_bytes++];
inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN); inst->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN);
#else #else
@ -277,7 +277,7 @@ static void uart_npcx_isr(const struct device *dev)
if (uart_npcx_irq_rx_ready(dev)) { if (uart_npcx_irq_rx_ready(dev)) {
k_timeout_t delay = K_MSEC(CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT); k_timeout_t delay = K_MSEC(CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT);
uart_npcx_pm_constraint_set(data, UART_PM_CONSTRAINT_RX_FLAG); uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_RX_FLAG);
k_work_reschedule(&data->rx_refresh_timeout_work, delay); k_work_reschedule(&data->rx_refresh_timeout_work, delay);
} }
#endif #endif
@ -291,7 +291,7 @@ static void uart_npcx_isr(const struct device *dev)
if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) && if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) &&
IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) { IS_BIT_SET(inst->UFTSTS, NPCX_UFTSTS_NXMIP)) {
uart_npcx_pm_constraint_rel(data, UART_PM_CONSTRAINT_TX_FLAG); uart_npcx_pm_policy_state_lock_put(data, UART_PM_POLICY_STATE_TX_FLAG);
inst->UFTCTL &= ~BIT(NPCX_UFTCTL_NXMIP_EN); inst->UFTCTL &= ~BIT(NPCX_UFTCTL_NXMIP_EN);
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -381,7 +381,7 @@ static __unused void uart_npcx_rx_wk_isr(const struct device *dev, struct npcx_w
struct uart_npcx_data *data = dev->data; struct uart_npcx_data *data = dev->data;
k_timeout_t delay = K_MSEC(CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT); k_timeout_t delay = K_MSEC(CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT);
uart_npcx_pm_constraint_set(data, UART_PM_CONSTRAINT_RX_FLAG); uart_npcx_pm_policy_state_lock_get(data, UART_PM_POLICY_STATE_RX_FLAG);
k_work_reschedule(&data->rx_refresh_timeout_work, delay); k_work_reschedule(&data->rx_refresh_timeout_work, delay);
#endif #endif
@ -398,7 +398,7 @@ static void uart_npcx_rx_refresh_timeout(struct k_work *work)
struct uart_npcx_data *data = struct uart_npcx_data *data =
CONTAINER_OF(work, struct uart_npcx_data, rx_refresh_timeout_work); CONTAINER_OF(work, struct uart_npcx_data, rx_refresh_timeout_work);
uart_npcx_pm_constraint_rel(data, UART_PM_CONSTRAINT_RX_FLAG); uart_npcx_pm_policy_state_lock_put(data, UART_PM_POLICY_STATE_RX_FLAG);
} }
#endif #endif

View file

@ -33,7 +33,7 @@
#include <toolchain.h> #include <toolchain.h>
#include <linker/sections.h> #include <linker/sections.h>
#include <drivers/uart.h> #include <drivers/uart.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <sys/sys_io.h> #include <sys/sys_io.h>
#include <spinlock.h> #include <spinlock.h>
@ -681,7 +681,7 @@ static void uart_ns16550_irq_tx_enable(const struct device *dev)
* different states. * different states.
*/ */
for (uint8_t i = 0U; i < num_cpu_states; i++) { for (uint8_t i = 0U; i < num_cpu_states; i++) {
pm_constraint_set(cpu_states[i].state); pm_policy_state_lock_get(cpu_states[i].state);
} }
} }
#endif #endif
@ -718,7 +718,7 @@ static void uart_ns16550_irq_tx_disable(const struct device *dev)
* to different states. * to different states.
*/ */
for (uint8_t i = 0U; i < num_cpu_states; i++) { for (uint8_t i = 0U; i < num_cpu_states; i++) {
pm_constraint_release(cpu_states[i].state); pm_policy_state_lock_put(cpu_states[i].state);
} }
} }
#endif #endif

View file

@ -21,7 +21,7 @@
#include <init.h> #include <init.h>
#include <drivers/uart.h> #include <drivers/uart.h>
#include <drivers/clock_control.h> #include <drivers/clock_control.h>
#include <pm/pm.h> #include <pm/policy.h>
#ifdef CONFIG_UART_ASYNC_API #ifdef CONFIG_UART_ASYNC_API
#include <drivers/dma/dma_stm32.h> #include <drivers/dma/dma_stm32.h>
@ -72,23 +72,23 @@ uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint32_t baud_rate)
#define TIMEOUT 1000 #define TIMEOUT 1000
#ifdef CONFIG_PM #ifdef CONFIG_PM
static void uart_stm32_pm_constraint_set(const struct device *dev) static void uart_stm32_pm_policy_state_lock_get(const struct device *dev)
{ {
struct uart_stm32_data *data = dev->data; struct uart_stm32_data *data = dev->data;
if (!data->pm_constraint_on) { if (!data->pm_policy_state_on) {
data->pm_constraint_on = true; data->pm_policy_state_on = true;
pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
static void uart_stm32_pm_constraint_release(const struct device *dev) static void uart_stm32_pm_policy_state_lock_put(const struct device *dev)
{ {
struct uart_stm32_data *data = dev->data; struct uart_stm32_data *data = dev->data;
if (data->pm_constraint_on) { if (data->pm_policy_state_on) {
data->pm_constraint_on = false; data->pm_policy_state_on = false;
pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE);
} }
} }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -551,7 +551,7 @@ static void uart_stm32_poll_out(const struct device *dev,
/* Don't allow system to suspend until stream /* Don't allow system to suspend until stream
* transmission has completed * transmission has completed
*/ */
uart_stm32_pm_constraint_set(dev); uart_stm32_pm_policy_state_lock_get(dev);
/* Enable TC interrupt so we can release suspend /* Enable TC interrupt so we can release suspend
* constraint when done * constraint when done
@ -695,7 +695,7 @@ static void uart_stm32_irq_tx_enable(const struct device *dev)
key = irq_lock(); key = irq_lock();
data->tx_poll_stream_on = false; data->tx_poll_stream_on = false;
data->tx_int_stream_on = true; data->tx_int_stream_on = true;
uart_stm32_pm_constraint_set(dev); uart_stm32_pm_policy_state_lock_get(dev);
#endif #endif
LL_USART_EnableIT_TC(config->usart); LL_USART_EnableIT_TC(config->usart);
@ -718,7 +718,7 @@ static void uart_stm32_irq_tx_disable(const struct device *dev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
data->tx_int_stream_on = false; data->tx_int_stream_on = false;
uart_stm32_pm_constraint_release(dev); uart_stm32_pm_policy_state_lock_put(dev);
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
@ -972,7 +972,7 @@ static void uart_stm32_isr(const struct device *dev)
*/ */
LL_USART_DisableIT_TC(config->usart); LL_USART_DisableIT_TC(config->usart);
data->tx_poll_stream_on = false; data->tx_poll_stream_on = false;
uart_stm32_pm_constraint_release(dev); uart_stm32_pm_policy_state_lock_put(dev);
} }
/* Stream transmission was either async or IRQ based, /* Stream transmission was either async or IRQ based,
* constraint will be released at the same time TC IT * constraint will be released at the same time TC IT
@ -1011,7 +1011,7 @@ static void uart_stm32_isr(const struct device *dev)
async_evt_tx_done(data); async_evt_tx_done(data);
#ifdef CONFIG_PM #ifdef CONFIG_PM
uart_stm32_pm_constraint_release(dev); uart_stm32_pm_policy_state_lock_put(dev);
#endif #endif
} else if (LL_USART_IsEnabledIT_RXNE(config->usart) && } else if (LL_USART_IsEnabledIT_RXNE(config->usart) &&
LL_USART_IsActiveFlag_RXNE(config->usart)) { LL_USART_IsActiveFlag_RXNE(config->usart)) {
@ -1255,7 +1255,7 @@ static int uart_stm32_async_tx(const struct device *dev,
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* Do not allow system to suspend until transmission has completed */ /* Do not allow system to suspend until transmission has completed */
uart_stm32_pm_constraint_set(dev); uart_stm32_pm_policy_state_lock_get(dev);
#endif #endif
/* Enable TX DMA requests */ /* Enable TX DMA requests */

View file

@ -78,7 +78,7 @@ struct uart_stm32_data {
#ifdef CONFIG_PM #ifdef CONFIG_PM
bool tx_poll_stream_on; bool tx_poll_stream_on;
bool tx_int_stream_on; bool tx_int_stream_on;
bool pm_constraint_on; bool pm_policy_state_on;
#endif #endif
}; };

View file

@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(spi_cc13xx_cc26xx);
#include <drivers/spi.h> #include <drivers/spi.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/pm.h> #include <pm/policy.h>
#include <driverlib/prcm.h> #include <driverlib/prcm.h>
#include <driverlib/ssi.h> #include <driverlib/ssi.h>
@ -142,7 +142,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev,
spi_context_lock(ctx, false, NULL, config); spi_context_lock(ctx, false, NULL, config);
#ifdef CONFIG_PM #ifdef CONFIG_PM
pm_constraint_set(PM_STATE_STANDBY); pm_policy_state_lock_get(PM_STATE_STANDBY);
#endif #endif
err = spi_cc13xx_cc26xx_configure(dev, config); err = spi_cc13xx_cc26xx_configure(dev, config);
@ -178,7 +178,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev,
done: done:
#ifdef CONFIG_PM #ifdef CONFIG_PM
pm_constraint_release(PM_STATE_STANDBY); pm_policy_state_lock_put(PM_STATE_STANDBY);
#endif #endif
spi_context_release(ctx, err); spi_context_release(ctx, err);
return err; return err;

View file

@ -114,55 +114,6 @@ int pm_notifier_unregister(struct pm_notifier *notifier);
*/ */
const struct pm_state_info *pm_state_next_get(uint8_t cpu); const struct pm_state_info *pm_state_next_get(uint8_t cpu);
/**
* @}
*/
/**
* @brief System Power Management Constraints API
* @defgroup subsys_pm_sys_constraint Constraints
* @ingroup subsys_pm_sys
* @{
*/
/**
* @brief Set a constraint for a power state
*
* @details Disabled state cannot be selected by the Zephyr power
* management policies. Application defined policy should
* use the @ref pm_constraint_get function to
* check if given state is enabled and could be used.
*
* @note This API is refcount
*
* @param [in] state Power state to be disabled.
*/
void pm_constraint_set(enum pm_state state);
/**
* @brief Release a constraint for a power state
*
* @details Enabled state can be selected by the Zephyr power
* management policies. Application defined policy should
* use the @ref pm_constraint_get function to
* check if given state is enabled and could be used.
* By default all power states are enabled.
*
* @note This API is refcount
*
* @param [in] state Power state to be enabled.
*/
void pm_constraint_release(enum pm_state state);
/**
* @brief Check if particular power state is enabled
*
* This function returns true if given power state is enabled.
*
* @param [in] state Power state.
*/
bool pm_constraint_get(enum pm_state state);
/** /**
* @} * @}
*/ */
@ -216,23 +167,6 @@ static inline int pm_notifier_unregister(struct pm_notifier *notifier)
return -ENOSYS; return -ENOSYS;
} }
static inline void pm_constraint_set(enum pm_state state)
{
ARG_UNUSED(state);
}
static inline void pm_constraint_release(enum pm_state state)
{
ARG_UNUSED(state);
}
static inline bool pm_constraint_get(enum pm_state state)
{
ARG_UNUSED(state);
return true;
}
static inline void pm_state_set(enum pm_state state, uint8_t substate_id) static inline void pm_state_set(enum pm_state state, uint8_t substate_id)
{ {
ARG_UNUSED(state); ARG_UNUSED(state);

View file

@ -7,13 +7,22 @@
#ifndef ZEPHYR_INCLUDE_PM_POLICY_H_ #ifndef ZEPHYR_INCLUDE_PM_POLICY_H_
#define ZEPHYR_INCLUDE_PM_POLICY_H_ #define ZEPHYR_INCLUDE_PM_POLICY_H_
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <pm/state.h> #include <pm/state.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* @brief System Power Management Policy API
* @defgroup subsys_pm_sys_policy Policy
* @ingroup subsys_pm_sys
* @{
*/
/** @cond INTERNAL_HIDDEN */ /** @cond INTERNAL_HIDDEN */
/** /**
@ -33,6 +42,66 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks);
/** @endcond */ /** @endcond */
#if defined(CONFIG_PM) || defined(__DOXYGEN__)
/**
* @brief Increase a power state lock counter.
*
* A power state will not be allowed on the first call of
* pm_policy_state_lock_get(). Subsequent calls will just increase a reference
* count, thus meaning this API can be safely used concurrently. A state will
* be allowed again after pm_policy_state_lock_put() is called as many times as
* pm_policy_state_lock_get().
*
* Note that the PM_STATE_ACTIVE state is always allowed, so calling this API
* with PM_STATE_ACTIVE will have no effect.
*
* @param state Power state.
*
* @see pm_policy_state_lock_put()
*/
void pm_policy_state_lock_get(enum pm_state state);
/**
* @brief Decrease a power state lock counter.
*
* @param state Power state.
*
* @see pm_policy_state_lock_get()
*/
void pm_policy_state_lock_put(enum pm_state state);
/**
* @brief Check if a power state lock is active (not allowed).
*
* @param state Power state.
*
* @retval true if power state lock is active.
* @retval false if power state lock is not active.
*/
bool pm_policy_state_lock_is_active(enum pm_state state);
#else
static inline void pm_policy_state_lock_get(enum pm_state state)
{
ARG_UNUSED(state);
}
static inline void pm_policy_state_lock_put(enum pm_state state)
{
ARG_UNUSED(state);
}
static inline bool pm_policy_state_lock_is_active(enum pm_state state)
{
ARG_UNUSED(state);
return false;
}
#endif /* CONFIG_PM */
/**
* @}
*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -10,6 +10,7 @@
#include <init.h> #include <init.h>
#include <pm/pm.h> #include <pm/pm.h>
#include <pm/device.h> #include <pm/device.h>
#include <pm/policy.h>
#include <soc.h> #include <soc.h>
#include "retained.h" #include "retained.h"
#include <hal/nrf_gpio.h> #include <hal/nrf_gpio.h>
@ -30,7 +31,7 @@ static int disable_ds_1(const struct device *dev)
{ {
ARG_UNUSED(dev); ARG_UNUSED(dev);
pm_constraint_set(PM_STATE_SOFT_OFF); pm_policy_state_lock_get(PM_STATE_SOFT_OFF);
return 0; return 0;
} }

View file

@ -6,6 +6,7 @@
#include <zephyr.h> #include <zephyr.h>
#include <init.h> #include <init.h>
#include <pm/pm.h> #include <pm/pm.h>
#include <pm/policy.h>
#include <driverlib/pwr_ctrl.h> #include <driverlib/pwr_ctrl.h>
#include <driverlib/sys_ctrl.h> #include <driverlib/sys_ctrl.h>

View file

@ -1,9 +1,8 @@
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
if(CONFIG_PM) if(CONFIG_PM)
zephyr_sources(pm.c constraint.c state.c) zephyr_sources(pm.c policy.c state.c)
zephyr_sources_ifdef(CONFIG_PM_STATS pm_stats.c) zephyr_sources_ifdef(CONFIG_PM_STATS pm_stats.c)
zephyr_sources_ifdef(CONFIG_PM_POLICY_DEFAULT policy.c)
endif() endif()
zephyr_sources_ifdef(CONFIG_PM_DEVICE device.c) zephyr_sources_ifdef(CONFIG_PM_DEVICE device.c)

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2018 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/atomic.h>
#include <pm/state.h>
#include <toolchain.h>
static atomic_t power_state_disable_count[PM_STATE_COUNT];
void pm_constraint_set(enum pm_state state)
{
atomic_inc(&power_state_disable_count[state]);
}
void pm_constraint_release(enum pm_state state)
{
atomic_dec(&power_state_disable_count[state]);
}
bool pm_constraint_get(enum pm_state state)
{
return (atomic_get(&power_state_disable_count[state]) == 0);
}

View file

@ -1,5 +1,6 @@
/* /*
* Copyright (c) 2018 Intel Corporation. * Copyright (c) 2018 Intel Corporation.
* Copyright (c) 2022 Nordic Semiconductor ASA
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -8,7 +9,13 @@
#include <pm/policy.h> #include <pm/policy.h>
#include <sys_clock.h> #include <sys_clock.h>
#include <sys/time_units.h> #include <sys/time_units.h>
#include <sys/atomic.h>
#include <toolchain.h>
/** State lock reference counting */
static atomic_t state_lock_cnt[PM_STATE_COUNT];
#ifdef CONFIG_PM_POLICY_DEFAULT
const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
{ {
uint8_t num_cpu_states; uint8_t num_cpu_states;
@ -20,7 +27,7 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
const struct pm_state_info *state = &cpu_states[i]; const struct pm_state_info *state = &cpu_states[i];
uint32_t min_residency, exit_latency; uint32_t min_residency, exit_latency;
if (!pm_constraint_get(state->state)) { if (pm_policy_state_lock_is_active(state->state)) {
continue; continue;
} }
@ -35,3 +42,19 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks)
return NULL; return NULL;
} }
#endif
void pm_policy_state_lock_get(enum pm_state state)
{
atomic_inc(&state_lock_cnt[state]);
}
void pm_policy_state_lock_put(enum pm_state state)
{
atomic_dec(&state_lock_cnt[state]);
}
bool pm_policy_state_lock_is_active(enum pm_state state)
{
return (atomic_get(&state_lock_cnt[state]) != 0);
}