From 5a71eeb35cb4c20cf1be20d25496df228c40ece0 Mon Sep 17 00:00:00 2001 From: Gerard Marull-Paretas Date: Thu, 20 Jan 2022 16:06:28 +0100 Subject: [PATCH] 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 --- boards/arm/cc1352r1_launchxl/doc/index.rst | 4 +- boards/arm/cc1352r_sensortag/doc/index.rst | 4 +- boards/arm/cc26x2r1_launchxl/doc/index.rst | 4 +- doc/guides/pm/system.rst | 24 +++---- doc/reference/pm/index.rst | 6 +- drivers/entropy/entropy_cc13xx_cc26xx.c | 8 +-- drivers/entropy/entropy_stm32.c | 8 +-- drivers/i2c/i2c_cc13xx_cc26xx.c | 6 +- drivers/serial/uart_cc13xx_cc26xx.c | 10 +-- drivers/serial/uart_ite_it8xxx2.c | 7 +-- drivers/serial/uart_mcux_lpuart.c | 30 ++++----- drivers/serial/uart_npcx.c | 38 ++++++------ drivers/serial/uart_ns16550.c | 6 +- drivers/serial/uart_stm32.c | 30 ++++----- drivers/serial/uart_stm32.h | 2 +- drivers/spi/spi_cc13xx_cc26xx.c | 6 +- include/pm/pm.h | 66 -------------------- include/pm/policy.h | 69 +++++++++++++++++++++ samples/boards/nrf/system_off/src/main.c | 3 +- soc/arm/ti_simplelink/cc13x2_cc26x2/power.c | 1 + subsys/pm/CMakeLists.txt | 3 +- subsys/pm/constraint.c | 26 -------- subsys/pm/policy.c | 25 +++++++- 23 files changed, 191 insertions(+), 195 deletions(-) delete mode 100644 subsys/pm/constraint.c 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); +}