diff --git a/boards/arm/cc1352r1_launchxl/doc/index.rst b/boards/arm/cc1352r1_launchxl/doc/index.rst index 7a2546e83bc..02a7ed76eea 100644 --- a/boards/arm/cc1352r1_launchxl/doc/index.rst +++ b/boards/arm/cc1352r1_launchxl/doc/index.rst @@ -216,9 +216,9 @@ disable sleep state 2 while polling: .. code-block:: c - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); References diff --git a/boards/arm/cc1352r_sensortag/doc/index.rst b/boards/arm/cc1352r_sensortag/doc/index.rst index ed3e4aa902c..2c2e8f86487 100644 --- a/boards/arm/cc1352r_sensortag/doc/index.rst +++ b/boards/arm/cc1352r_sensortag/doc/index.rst @@ -242,9 +242,9 @@ disable sleep state 2 while polling: .. code-block:: c - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); References diff --git a/boards/arm/cc26x2r1_launchxl/doc/index.rst b/boards/arm/cc26x2r1_launchxl/doc/index.rst index 4a7843b15bd..6afd2c2441c 100644 --- a/boards/arm/cc26x2r1_launchxl/doc/index.rst +++ b/boards/arm/cc26x2r1_launchxl/doc/index.rst @@ -222,9 +222,9 @@ disable sleep state 2 while polling: .. code-block:: c - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); References diff --git a/doc/guides/pm/system.rst b/doc/guides/pm/system.rst index d298dbb5e6c..b788711f0d6 100644 --- a/doc/guides/pm/system.rst +++ b/doc/guides/pm/system.rst @@ -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 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 ========================= @@ -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 power state the system should transition to based on states defined by the -platform and possible runtime :ref:`constraints` +platform and other constraints such as a list of allowed states. More details on the states definition can be found in the :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 :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. diff --git a/doc/reference/pm/index.rst b/doc/reference/pm/index.rst index 76750668abc..05c01103202 100644 --- a/doc/reference/pm/index.rst +++ b/doc/reference/pm/index.rst @@ -13,10 +13,10 @@ States .. doxygengroup:: subsys_pm_states -Constraints -=========== +Policy +====== -.. doxygengroup:: subsys_pm_sys_constraint +.. doxygengroup:: subsys_pm_sys_policy Hooks ===== diff --git a/drivers/entropy/entropy_cc13xx_cc26xx.c b/drivers/entropy/entropy_cc13xx_cc26xx.c index 2703dbbb522..2a68f9de54b 100644 --- a/drivers/entropy/entropy_cc13xx_cc26xx.c +++ b/drivers/entropy/entropy_cc13xx_cc26xx.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -101,7 +101,7 @@ static int entropy_cc13xx_cc26xx_get_entropy(const struct device *dev, unsigned int key = irq_lock(); if (!data->constrained) { - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); data->constrained = true; } irq_unlock(key); @@ -146,7 +146,7 @@ static void entropy_cc13xx_cc26xx_isr(const struct device *dev) if (cnt != sizeof(num)) { #ifdef CONFIG_PM if (data->constrained) { - pm_constraint_release( + pm_policy_state_lock_put( PM_STATE_STANDBY); data->constrained = false; } @@ -290,7 +290,7 @@ static int entropy_cc13xx_cc26xx_init(const struct device *dev) #if defined(CONFIG_PM) Power_setDependency(PowerCC26XX_PERIPH_TRNG); /* 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; /* Register notification function */ Power_registerNotify(&data->post_notify, diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index 0a03178fdce..f5a041b2cce 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -246,7 +246,7 @@ static uint16_t rng_pool_get(struct rng_pool *rngp, uint8_t *buf, uint16_t len) available = available - len; if ((available <= rngp->threshold) && !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); } @@ -300,7 +300,7 @@ static void stm32_rng_isr(const void *arg) byte); if (ret < 0) { 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); @@ -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 * 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); diff --git a/drivers/i2c/i2c_cc13xx_cc26xx.c b/drivers/i2c/i2c_cc13xx_cc26xx.c index 7654aacdd3e..a87c59f6bc9 100644 --- a/drivers/i2c/i2c_cc13xx_cc26xx.c +++ b/drivers/i2c/i2c_cc13xx_cc26xx.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL #include @@ -198,7 +198,7 @@ static int i2c_cc13xx_cc26xx_transfer(const struct device *dev, k_sem_take(&data->lock, K_FOREVER); #ifdef CONFIG_PM - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); #endif 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 - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); #endif k_sem_give(&data->lock); diff --git a/drivers/serial/uart_cc13xx_cc26xx.c b/drivers/serial/uart_cc13xx_cc26xx.c index b76b73c2041..13e6aec65fb 100644 --- a/drivers/serial/uart_cc13xx_cc26xx.c +++ b/drivers/serial/uart_cc13xx_cc26xx.c @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -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 * would interfere with a transfer. */ - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); data->tx_constrained = true; } #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; if (data->tx_constrained) { - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); data->tx_constrained = false; } #endif @@ -298,7 +298,7 @@ static void uart_cc13xx_cc26xx_irq_rx_enable(const struct device *dev) * standby. */ if (!data->rx_constrained) { - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); data->rx_constrained = true; } #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; if (data->rx_constrained) { - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); data->rx_constrained = false; } #endif diff --git a/drivers/serial/uart_ite_it8xxx2.c b/drivers/serial/uart_ite_it8xxx2.c index 7686ba864f8..d0f4d07a5be 100644 --- a/drivers/serial/uart_ite_it8xxx2.c +++ b/drivers/serial/uart_ite_it8xxx2.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -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 * 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); #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 * 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); #endif } @@ -117,7 +116,7 @@ static void uart_it8xxx2_rx_refresh_timeout(struct k_work *work) { ARG_UNUSED(work); - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); } #endif #endif /* CONFIG_PM_DEVICE */ diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index 0752e71c8eb..bc0ff12792a 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #ifdef CONFIG_PINCTRL #include #endif @@ -38,7 +38,7 @@ struct mcux_lpuart_data { void *cb_data; #endif #ifdef CONFIG_PM - bool pm_constraint_on; + bool pm_state_lock_on; bool tx_poll_stream_on; bool tx_int_stream_on; #endif /* CONFIG_PM */ @@ -46,23 +46,23 @@ struct mcux_lpuart_data { }; #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; - if (!data->pm_constraint_on) { - data->pm_constraint_on = true; - pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); + if (!data->pm_state_lock_on) { + data->pm_state_lock_on = true; + 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; - if (data->pm_constraint_on) { - data->pm_constraint_on = false; - pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); + if (data->pm_state_lock_on) { + data->pm_state_lock_on = false; + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE); } } #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) { data->tx_poll_stream_on = true; - mcux_lpuart_pm_constraint_set(dev); + mcux_lpuart_pm_policy_state_lock_get(dev); /* Enable TC interrupt */ LPUART_EnableInterrupts(config->base, 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_int_stream_on = true; /* 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 LPUART_EnableInterrupts(config->base, mask); #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, * transmission is complete. Release pm constraint. */ - mcux_lpuart_pm_constraint_release(dev); + mcux_lpuart_pm_policy_state_lock_put(dev); irq_unlock(key); #endif } @@ -329,7 +329,7 @@ static void mcux_lpuart_isr(const struct device *dev) LPUART_DisableInterrupts(config->base, kLPUART_TransmissionCompleteInterruptEnable); data->tx_poll_stream_on = false; - mcux_lpuart_pm_constraint_release(dev); + mcux_lpuart_pm_policy_state_lock_put(dev); } } #endif /* CONFIG_PM */ @@ -484,7 +484,7 @@ static int mcux_lpuart_init(const struct device *dev) #endif #ifdef CONFIG_PM - data->pm_constraint_on = false; + data->pm_state_lock_on = false; data->tx_poll_stream_on = false; data->tx_int_stream_on = false; #endif diff --git a/drivers/serial/uart_npcx.c b/drivers/serial/uart_npcx.c index 5fac7ef6032..2094bf2c659 100644 --- a/drivers/serial/uart_npcx.c +++ b/drivers/serial/uart_npcx.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "soc_miwu.h" #include "soc_power.h" @@ -35,11 +35,11 @@ struct uart_npcx_config { const struct npcx_alt *alts_list; }; -enum uart_pm_constraint_flag { - UART_PM_CONSTRAINT_TX_FLAG, - UART_PM_CONSTRAINT_RX_FLAG, +enum uart_pm_policy_state_flag { + UART_PM_POLICY_STATE_TX_FLAG, + UART_PM_POLICY_STATE_RX_FLAG, - UART_PM_CONSTRAINT_FLAG_COUNT, + UART_PM_POLICY_STATE_FLAG_COUNT, }; /* Driver data */ @@ -52,7 +52,7 @@ struct uart_npcx_data { void *user_data; #endif #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 struct k_work_delayable rx_refresh_timeout_work; #endif @@ -60,19 +60,19 @@ struct uart_npcx_data { }; #if defined(CONFIG_PM) && defined(CONFIG_UART_INTERRUPT_DRIVEN) -static void uart_npcx_pm_constraint_set(struct uart_npcx_data *data, - enum uart_pm_constraint_flag flag) +static void uart_npcx_pm_policy_state_lock_get(struct uart_npcx_data *data, + enum uart_pm_policy_state_flag flag) { - if (atomic_test_and_set_bit(data->pm_constraint_flag, flag) == 0) { - pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); + if (atomic_test_and_set_bit(data->pm_policy_state_flag, flag) == 0) { + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE); } } -static void uart_npcx_pm_constraint_rel(struct uart_npcx_data *data, - enum uart_pm_constraint_flag flag) +static void uart_npcx_pm_policy_state_lock_put(struct uart_npcx_data *data, + enum uart_pm_policy_state_flag flag) { - if (atomic_test_and_clear_bit(data->pm_constraint_flag, flag) == 1) { - pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, flag) == 1) { + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE); } } #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 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->UFTCTL |= BIT(NPCX_UFTCTL_NXMIP_EN); #else @@ -277,7 +277,7 @@ static void uart_npcx_isr(const struct device *dev) if (uart_npcx_irq_rx_ready(dev)) { 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); } #endif @@ -291,7 +291,7 @@ static void uart_npcx_isr(const struct device *dev) if (IS_BIT_SET(inst->UFTCTL, NPCX_UFTCTL_NXMIP_EN) && 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); } #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; 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); #endif @@ -398,7 +398,7 @@ static void uart_npcx_rx_refresh_timeout(struct k_work *work) struct uart_npcx_data *data = 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 diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 5a2a012d49f..c3f06f8c725 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #include @@ -681,7 +681,7 @@ static void uart_ns16550_irq_tx_enable(const struct device *dev) * different states. */ 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 @@ -718,7 +718,7 @@ static void uart_ns16550_irq_tx_disable(const struct device *dev) * to different states. */ 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 diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 297e6e4abd3..f14d1ffe197 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #ifdef CONFIG_UART_ASYNC_API #include @@ -72,23 +72,23 @@ uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint32_t baud_rate) #define TIMEOUT 1000 #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; - if (!data->pm_constraint_on) { - data->pm_constraint_on = true; - pm_constraint_set(PM_STATE_SUSPEND_TO_IDLE); + if (!data->pm_policy_state_on) { + data->pm_policy_state_on = true; + 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; - if (data->pm_constraint_on) { - data->pm_constraint_on = false; - pm_constraint_release(PM_STATE_SUSPEND_TO_IDLE); + if (data->pm_policy_state_on) { + data->pm_policy_state_on = false; + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE); } } #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 * 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 * constraint when done @@ -695,7 +695,7 @@ static void uart_stm32_irq_tx_enable(const struct device *dev) key = irq_lock(); data->tx_poll_stream_on = false; data->tx_int_stream_on = true; - uart_stm32_pm_constraint_set(dev); + uart_stm32_pm_policy_state_lock_get(dev); #endif LL_USART_EnableIT_TC(config->usart); @@ -718,7 +718,7 @@ static void uart_stm32_irq_tx_disable(const struct device *dev) #ifdef CONFIG_PM data->tx_int_stream_on = false; - uart_stm32_pm_constraint_release(dev); + uart_stm32_pm_policy_state_lock_put(dev); #endif #ifdef CONFIG_PM @@ -972,7 +972,7 @@ static void uart_stm32_isr(const struct device *dev) */ LL_USART_DisableIT_TC(config->usart); 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, * 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); #ifdef CONFIG_PM - uart_stm32_pm_constraint_release(dev); + uart_stm32_pm_policy_state_lock_put(dev); #endif } else if (LL_USART_IsEnabledIT_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 /* 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 /* Enable TX DMA requests */ diff --git a/drivers/serial/uart_stm32.h b/drivers/serial/uart_stm32.h index c8b45c5a8d3..e47ebc1baf2 100644 --- a/drivers/serial/uart_stm32.h +++ b/drivers/serial/uart_stm32.h @@ -78,7 +78,7 @@ struct uart_stm32_data { #ifdef CONFIG_PM bool tx_poll_stream_on; bool tx_int_stream_on; - bool pm_constraint_on; + bool pm_policy_state_on; #endif }; diff --git a/drivers/spi/spi_cc13xx_cc26xx.c b/drivers/spi/spi_cc13xx_cc26xx.c index e896c4ce735..92894bcb0ec 100644 --- a/drivers/spi/spi_cc13xx_cc26xx.c +++ b/drivers/spi/spi_cc13xx_cc26xx.c @@ -12,7 +12,7 @@ LOG_MODULE_REGISTER(spi_cc13xx_cc26xx); #include #include -#include +#include #include #include @@ -142,7 +142,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev, spi_context_lock(ctx, false, NULL, config); #ifdef CONFIG_PM - pm_constraint_set(PM_STATE_STANDBY); + pm_policy_state_lock_get(PM_STATE_STANDBY); #endif err = spi_cc13xx_cc26xx_configure(dev, config); @@ -178,7 +178,7 @@ static int spi_cc13xx_cc26xx_transceive(const struct device *dev, done: #ifdef CONFIG_PM - pm_constraint_release(PM_STATE_STANDBY); + pm_policy_state_lock_put(PM_STATE_STANDBY); #endif spi_context_release(ctx, err); return err; diff --git a/include/pm/pm.h b/include/pm/pm.h index 9470033ae3b..0b039c3f9bb 100644 --- a/include/pm/pm.h +++ b/include/pm/pm.h @@ -114,55 +114,6 @@ int pm_notifier_unregister(struct pm_notifier *notifier); */ 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; } -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) { ARG_UNUSED(state); diff --git a/include/pm/policy.h b/include/pm/policy.h index fc46158cfeb..3f0a571b8a5 100644 --- a/include/pm/policy.h +++ b/include/pm/policy.h @@ -7,13 +7,22 @@ #ifndef ZEPHYR_INCLUDE_PM_POLICY_H_ #define ZEPHYR_INCLUDE_PM_POLICY_H_ +#include #include + #include #ifdef __cplusplus extern "C" { #endif +/** + * @brief System Power Management Policy API + * @defgroup subsys_pm_sys_policy Policy + * @ingroup subsys_pm_sys + * @{ + */ + /** @cond INTERNAL_HIDDEN */ /** @@ -33,6 +42,66 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks); /** @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 } #endif diff --git a/samples/boards/nrf/system_off/src/main.c b/samples/boards/nrf/system_off/src/main.c index 06af29c2954..56d81a2d846 100644 --- a/samples/boards/nrf/system_off/src/main.c +++ b/samples/boards/nrf/system_off/src/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "retained.h" #include @@ -30,7 +31,7 @@ static int disable_ds_1(const struct device *dev) { ARG_UNUSED(dev); - pm_constraint_set(PM_STATE_SOFT_OFF); + pm_policy_state_lock_get(PM_STATE_SOFT_OFF); return 0; } diff --git a/soc/arm/ti_simplelink/cc13x2_cc26x2/power.c b/soc/arm/ti_simplelink/cc13x2_cc26x2/power.c index f1d2d32378a..7fe95635092 100644 --- a/soc/arm/ti_simplelink/cc13x2_cc26x2/power.c +++ b/soc/arm/ti_simplelink/cc13x2_cc26x2/power.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/subsys/pm/CMakeLists.txt b/subsys/pm/CMakeLists.txt index e99fb5783db..1ddc7861a72 100644 --- a/subsys/pm/CMakeLists.txt +++ b/subsys/pm/CMakeLists.txt @@ -1,9 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 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_POLICY_DEFAULT policy.c) endif() zephyr_sources_ifdef(CONFIG_PM_DEVICE device.c) diff --git a/subsys/pm/constraint.c b/subsys/pm/constraint.c deleted file mode 100644 index 1f6e1aff656..00000000000 --- a/subsys/pm/constraint.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -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); -} diff --git a/subsys/pm/policy.c b/subsys/pm/policy.c index ab6fb51782a..3e01fc9df24 100644 --- a/subsys/pm/policy.c +++ b/subsys/pm/policy.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Intel Corporation. + * Copyright (c) 2022 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,7 +9,13 @@ #include #include #include +#include +#include +/** 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) { 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]; uint32_t min_residency, exit_latency; - if (!pm_constraint_get(state->state)) { + if (pm_policy_state_lock_is_active(state->state)) { continue; } @@ -35,3 +42,19 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) 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); +}