diff --git a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-devkit/index.rst b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-devkit/index.rst index b47ed4e8513ed..fd39f95e10997 100644 --- a/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-devkit/index.rst +++ b/Documentation/platforms/risc-v/esp32c3/boards/esp32c3-devkit/index.rst @@ -447,6 +447,10 @@ Note: When normal mode COUNT is 0, it will switch to the next PM state where COU Note: During light sleep, overall current consumption of board should drop from 18mA (without any system load) to 1 mA on ESP32-C3 DevkitM-1. +To save power without using sleep modes, lowering the clock speed is another approach. For dynamic frequency scaling +``CONFIG_ESPRESSIF_DFS`` option needs to enabled and minimum CPU frequency needs to set under ``CONFIG_ESPRESSIF_MIN_CPU_FREQ`` option. +With these options, the device scales the CPU clock according to workload. + pwm --- diff --git a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst index 0cfd58ae90760..fb527062f4346 100644 --- a/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst +++ b/Documentation/platforms/risc-v/esp32c6/boards/esp32c6-devkitc/index.rst @@ -464,6 +464,10 @@ Note: When normal mode COUNT is 0, it will switch to the next PM state where COU Note: During light sleep, overall current consumption of board should drop from 22mA (without any system load) to 1.3 mA on ESP32-C6 DevkitC-1. During deep sleep, current consumption of module (ESP32-C6-WROOM-1) should drop from 22mA (without any system load) to 48 μA. +To save power without using sleep modes, lowering the clock speed is another approach. For dynamic frequency scaling +``CONFIG_ESPRESSIF_DFS`` option needs to enabled and minimum CPU frequency needs to set under ``CONFIG_ESPRESSIF_MIN_CPU_FREQ`` option. +With these options, the device scales the CPU clock according to workload. + pwm --- diff --git a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst index a89b8589d76de..e32d5ecd98c70 100644 --- a/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst +++ b/Documentation/platforms/risc-v/esp32h2/boards/esp32h2-devkit/index.rst @@ -390,6 +390,10 @@ Note: When normal mode COUNT is 0, it will switch to the next PM state where COU Note: During light sleep, overall current consumption of board should drop from 14mA (without any system load) to 880 μA on ESP32-H2 DevkitM-1. During deep sleep, current consumption of module (ESP32-H2-MINI-1) should drop from 9mA (without any system load) to 8 μA. +To save power without using sleep modes, lowering the clock speed is another approach. For dynamic frequency scaling +``CONFIG_ESPRESSIF_DFS`` option needs to enabled and minimum CPU frequency needs to set under ``CONFIG_ESPRESSIF_MIN_CPU_FREQ`` option. +With these options, the device scales the CPU clock according to workload. + pwm --- diff --git a/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-function-ev-board/index.rst b/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-function-ev-board/index.rst index 65cd8e1075014..1ece4a287a9a1 100644 --- a/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-function-ev-board/index.rst +++ b/Documentation/platforms/risc-v/esp32p4/boards/esp32p4-function-ev-board/index.rst @@ -291,6 +291,10 @@ System switch to the PM sleep mode, you need to enter:: nsh> pmconfig relax normal nsh> pmconfig relax normal +To save power without using sleep modes, lowering the clock speed is another approach. For dynamic frequency scaling +``CONFIG_ESPRESSIF_DFS`` option needs to enabled and minimum CPU frequency needs to set under ``CONFIG_ESPRESSIF_MIN_CPU_FREQ`` option. +With these options, the device scales the CPU clock according to workload. + pwm --- diff --git a/arch/risc-v/src/common/espressif/CMakeLists.txt b/arch/risc-v/src/common/espressif/CMakeLists.txt index 749c7c4deb6fb..c9e75969c0814 100644 --- a/arch/risc-v/src/common/espressif/CMakeLists.txt +++ b/arch/risc-v/src/common/espressif/CMakeLists.txt @@ -209,7 +209,7 @@ if(DEFINED ENV{ESP_HAL_3RDPARTY_VERSION}) CACHE STRING "ESP HAL 3rdparty version") else() set(ESP_HAL_3RDPARTY_VERSION - b7e51db97a3f9dc82d3b3524d2bad298ba1e2647 + 2209449c9864c6d83a0ee2295f5b5299a2c6fb39 CACHE STRING "ESP HAL 3rdparty version") endif() diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index f91c5d80300bb..d59b5e21fc87c 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -126,6 +126,11 @@ config ESPRESSIF_CPU_FREQ_MHZ default 360 if ESPRESSIF_CPU_FREQ_360 default 400 if ESPRESSIF_CPU_FREQ_400 +config ESPRESSIF_DFS + bool "Enable DFS (Dynamic Frequency Scaling)" + select PM + default n + config ESPRESSIF_REGION_PROTECTION bool "Enable region protection" default y @@ -162,6 +167,93 @@ config ESPRESSIF_SOC_RTC_MEM_SUPPORTED bool default n +menu "Espressif DFS Options" + depends on ESPRESSIF_DFS + +choice ESPRESSIF_MIN_CPU_FREQ + prompt "Minimum CPU frequency" + default ESPRESSIF_MIN_CPU_FREQ_40 if ARCH_CHIP_ESP32P4 && ESPRESSIF_IDF_ENV_FPGA + default ESPRESSIF_MIN_CPU_FREQ_96 if ARCH_CHIP_ESP32H2 + default ESPRESSIF_MIN_CPU_FREQ_160 if ARCH_CHIP_ESP32C3 || ARCH_CHIP_ESP32C6 + default ESPRESSIF_MIN_CPU_FREQ_360 if ARCH_CHIP_ESP32P4 && ESP32P4_SELECTS_REV_LESS_V3 + default ESPRESSIF_MIN_CPU_FREQ_400 if ARCH_CHIP_ESP32P4 && !ESP32P4_SELECTS_REV_LESS_V3 + ---help--- + Minimum CPU frequency to be scale. + +config ESPRESSIF_MIN_CPU_FREQ_40 + bool "40 MHz" + depends on ARCH_CHIP_ESP32C3 || ARCH_CHIP_ESP32C6 || ARCH_CHIP_ESP32P4 + ---help--- + Set the minimum CPU frequency to 40 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_48 + bool "48 MHz" + depends on ARCH_CHIP_ESP32H2 + ---help--- + Set the minimum CPU frequency to 48 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_64 + bool "64 MHz" + depends on ARCH_CHIP_ESP32H2 + ---help--- + Set the minimum CPU frequency to 64 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_80 + bool "80 MHz" + depends on ARCH_CHIP_ESP32C3 || ARCH_CHIP_ESP32C6 + ---help--- + Set the minimum CPU frequency to 80 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_96 + bool "96 MHz" + depends on ARCH_CHIP_ESP32H2 + ---help--- + Set the minimum CPU frequency to 96 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_160 + bool "160 MHz" + depends on ARCH_CHIP_ESP32C3 || ARCH_CHIP_ESP32C6 + ---help--- + Set the minimum CPU frequency to 160 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_360 + bool "360 MHz" + depends on ARCH_CHIP_ESP32P4 && ESP32P4_SELECTS_REV_LESS_V3 + ---help--- + Set the minimum CPU frequency to 360 MHz. + +config ESPRESSIF_MIN_CPU_FREQ_400 + bool "400 MHz" + depends on ARCH_CHIP_ESP32P4 && !ESP32P4_SELECTS_REV_LESS_V3 + ---help--- + Set the minimum CPU frequency to 400 MHz. + +endchoice # ESPRESSIF_MIN_CPU_FREQ + +config ESPRESSIF_MAX_CPU_FREQ_MHZ + int + default 40 if ESPRESSIF_MAX_CPU_FREQ_40 + default 48 if ESPRESSIF_MAX_CPU_FREQ_48 + default 64 if ESPRESSIF_MAX_CPU_FREQ_64 + default 80 if ESPRESSIF_MAX_CPU_FREQ_80 + default 96 if ESPRESSIF_MAX_CPU_FREQ_96 + default 160 if ESPRESSIF_MAX_CPU_FREQ_160 + default 360 if ESPRESSIF_MAX_CPU_FREQ_360 + default 400 if ESPRESSIF_MAX_CPU_FREQ_400 + +config ESPRESSIF_MIN_CPU_FREQ_MHZ + int + default 40 if ESPRESSIF_MIN_CPU_FREQ_40 + default 48 if ESPRESSIF_MIN_CPU_FREQ_48 + default 64 if ESPRESSIF_MIN_CPU_FREQ_64 + default 80 if ESPRESSIF_MIN_CPU_FREQ_80 + default 96 if ESPRESSIF_MIN_CPU_FREQ_96 + default 160 if ESPRESSIF_MIN_CPU_FREQ_160 + default 360 if ESPRESSIF_MIN_CPU_FREQ_360 + default 400 if ESPRESSIF_MIN_CPU_FREQ_400 + +endmenu # + menu "Espressif Log Level" visible if DEBUG_FEATURES diff --git a/arch/risc-v/src/common/espressif/Make.defs b/arch/risc-v/src/common/espressif/Make.defs index 10c8a2aca1af0..e91515f85f22a 100644 --- a/arch/risc-v/src/common/espressif/Make.defs +++ b/arch/risc-v/src/common/espressif/Make.defs @@ -217,7 +217,7 @@ endif ESP_HAL_3RDPARTY_REPO = esp-hal-3rdparty ifndef ESP_HAL_3RDPARTY_VERSION - ESP_HAL_3RDPARTY_VERSION = b7e51db97a3f9dc82d3b3524d2bad298ba1e2647 + ESP_HAL_3RDPARTY_VERSION = 2209449c9864c6d83a0ee2295f5b5299a2c6fb39 endif ifndef ESP_HAL_3RDPARTY_URL diff --git a/arch/risc-v/src/common/espressif/esp_gptimer.c b/arch/risc-v/src/common/espressif/esp_gptimer.c index a7d000f3c8209..3fb1c4faa8d75 100644 --- a/arch/risc-v/src/common/espressif/esp_gptimer.c +++ b/arch/risc-v/src/common/espressif/esp_gptimer.c @@ -46,6 +46,9 @@ #include "periph_ctrl.h" #include "soc/clk_tree_defs.h" #include "esp_private/esp_clk_tree_common.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -77,6 +80,9 @@ struct esp_timer_lowerhalf_s bool started; /* True: Timer has been started */ void *upper; /* Pointer to timer_upperhalf_s */ int group_id; /* Timer group number */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -122,7 +128,10 @@ static const struct timer_ops_s g_timer_ops = static struct esp_timer_lowerhalf_s g_timer0_lowerhalf = { .ops = &g_timer_ops, - .group_id = 0 + .group_id = 0, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; /* TIMER1 lower-half */ @@ -130,7 +139,10 @@ static struct esp_timer_lowerhalf_s g_timer0_lowerhalf = static struct esp_timer_lowerhalf_s g_timer1_lowerhalf = { .ops = &g_timer_ops, - .group_id = 1 + .group_id = 1, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; /**************************************************************************** @@ -171,6 +183,13 @@ static int esp_timer_start(struct timer_lowerhalf_s *lower) timer_hal_context_t *hal = &(priv->hal); +#ifdef CONFIG_PM + if (priv->pm_lock != NULL) + { + esp_pm_lock_acquire(priv->pm_lock); + } +#endif + /* Make sure the timer is stopped to avoid unpredictable behavior */ timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(hal->timer_id), @@ -282,6 +301,13 @@ static int esp_timer_stop(struct timer_lowerhalf_s *lower) false); timer_ll_enable_counter(hal->dev, hal->timer_id, false); +#ifdef CONFIG_PM + if (priv->pm_lock != NULL) + { + esp_pm_lock_release(priv->pm_lock); + } +#endif + priv->started = false; priv->callback = NULL; @@ -542,6 +568,11 @@ int esp_timer_initialize(int group_id) char *devpath; shared_periph_module_t periph; int irq; +#ifdef CONFIG_PM + int ret; + bool need_pm_lock = true; + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; +#endif switch (group_id) { @@ -590,6 +621,34 @@ int esp_timer_initialize(int group_id) timer_hal_init(&lower->hal, lower->group_id, lower->hal.timer_id); +#ifdef CONFIG_PM +# if TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST + if (GPTIMER_CLK_SRC_DEFAULT == GPTIMER_CLK_SRC_RC_FAST) + { + need_pm_lock = false; + } +# endif + +# if TIMER_LL_FUNC_CLOCK_SUPPORT_APB + if (GPTIMER_CLK_SRC_DEFAULT == GPTIMER_CLK_SRC_APB) + { + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } +# endif + + if (need_pm_lock && lower->pm_lock == NULL) + { + ret = esp_pm_lock_create(pm_lock_type, 0, + "TIMER", + &lower->pm_lock); + if (ret != OK) + { + tmrerr("Failed to create GPTIMER PM lock\n"); + return -ENOMEM; + } + } +#endif + /* Register the timer driver as /dev/timerX. If the registration goes * right the returned value from timer_register is a pointer to * timer_upperhalf_s that can be either used with timer_unregister() diff --git a/arch/risc-v/src/common/espressif/esp_i2c.c b/arch/risc-v/src/common/espressif/esp_i2c.c index 541a1355dd08e..fbc39b3da3f9a 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c.c +++ b/arch/risc-v/src/common/espressif/esp_i2c.c @@ -72,6 +72,9 @@ # include "soc/i2c_struct.h" # include "driver/lp_io.h" #endif +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -272,6 +275,9 @@ struct esp_i2c_priv_s #endif i2c_hal_context_t *ctx; /* Common layer struct */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -371,7 +377,10 @@ static struct esp_i2c_priv_s esp_i2c0_priv = .ready_read = false, .clk_src = I2C_CLK_SRC_DEFAULT, .clk_freq = 0, - .ctx = &i2c0_ctx + .ctx = &i2c0_ctx, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; #endif @@ -412,7 +421,10 @@ static struct esp_i2c_priv_s esp_i2c1_priv = .ready_read = false, .clk_src = I2C_CLK_SRC_DEFAULT, .clk_freq = 0, - .ctx = &i2c1_ctx + .ctx = &i2c1_ctx, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; # else # error "This device contains only a single HP I2C port." @@ -456,7 +468,10 @@ static struct esp_i2c_priv_s esp_lp_i2c0_priv = .ready_read = false, .clk_src = LP_I2C_SCLK_DEFAULT, .clk_freq = 0, - .ctx = &lp_i2c0_ctx + .ctx = &lp_i2c0_ctx, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; # else # error "This device does not contain a LP I2C port." @@ -1138,6 +1153,10 @@ static int esp_i2c_transfer(struct i2c_master_s *dev, return ret; } +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif + if (priv->i2cstate != I2CSTATE_IDLE) { esp_i2c_reset_fsmc(priv); @@ -1239,6 +1258,9 @@ static int esp_i2c_transfer(struct i2c_master_s *dev, /* Dump the trace result */ esp_i2c_tracedump(priv); +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif nxmutex_unlock(&priv->lock); return ret; @@ -1665,8 +1687,9 @@ static inline void esp_i2c_process(struct esp_i2c_priv_s *priv, struct i2c_master_s *esp_i2cbus_initialize(int port) { struct esp_i2c_priv_s *priv; -#ifndef CONFIG_I2C_POLLED int ret; +#ifdef CONFIG_PM + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; #endif switch (port) @@ -1702,6 +1725,42 @@ struct i2c_master_s *esp_i2cbus_initialize(int port) return (struct i2c_master_s *)priv; } +#ifdef CONFIG_PM +# if SOC_I2C_SUPPORT_RTC + if (I2C_CLK_SRC_DEFAULT == I2C_CLK_SRC_RC_FAST) + { + pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; + } +# endif + +# if SOC_I2C_SUPPORT_APB + if (I2C_CLK_SRC_DEFAULT == I2C_CLK_SRC_APB) + { + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } +# endif + +# ifdef CONFIG_ESPRESSIF_LP_I2C0 + if (priv->id == ESPRESSIF_LP_I2C0) + { + pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; + } +# endif + + ret = esp_pm_lock_create(pm_lock_type, + 0, + i2c_periph_signal[priv->id].module_name, + &priv->pm_lock); + if (ret != OK) + { + priv->refs--; + nxmutex_unlock(&priv->lock); + i2cerr("Failed to create I2C PM lock." + "Handler: %p\n", priv); + return NULL; + } +#endif + #ifndef CONFIG_I2C_POLLED if (priv->cpuint != -ENOMEM) { @@ -1779,6 +1838,14 @@ int esp_i2cbus_uninitialize(struct i2c_master_s *dev) priv->cpuint = -ENOMEM; #endif +#ifdef CONFIG_PM + if (priv->pm_lock != NULL) + { + esp_pm_lock_delete(priv->pm_lock); + priv->pm_lock = NULL; + } +#endif + esp_i2c_deinit(priv); nxmutex_unlock(&priv->lock); diff --git a/arch/risc-v/src/common/espressif/esp_i2c_slave.c b/arch/risc-v/src/common/espressif/esp_i2c_slave.c index fa44cc358ff4b..10ca9e0687781 100644 --- a/arch/risc-v/src/common/espressif/esp_i2c_slave.c +++ b/arch/risc-v/src/common/espressif/esp_i2c_slave.c @@ -65,6 +65,9 @@ #if defined(CONFIG_ARCH_CHIP_ESP32H2) || defined(CONFIG_ARCH_CHIP_ESP32C6) # include "soc/pcr_reg.h" #endif +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -138,6 +141,9 @@ struct esp_i2c_priv_s uint8_t tx_buffer[I2C_SLAVE_BUFF_SIZE]; /* I2C Slave TX queue buffer */ uint32_t rx_length; /* Location of next RX value */ uint8_t rx_buffer[I2C_SLAVE_BUFF_SIZE]; /* I2C Slave RX queue buffer */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -225,6 +231,9 @@ static struct esp_i2c_priv_s esp_i2c0_priv = { 0 }, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; #endif @@ -274,6 +283,9 @@ static struct esp_i2c_priv_s esp_i2c1_priv = { 0 }, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; #endif /* CONFIG_ESPRESSIF_I2C1 */ @@ -616,7 +628,7 @@ static void esp_i2c_slave_deinit(struct esp_i2c_priv_s *priv) * ****************************************************************************/ #ifndef CONFIG_I2C_POLLED -static int esp_i2c_slave_irq(void *arg) +static int esp_i2c_slave_irq(int irq, void *context, void *arg) { struct esp_i2c_priv_s *priv = (struct esp_i2c_priv_s *)arg; uint32_t irq_status = 0; @@ -627,8 +639,14 @@ static int esp_i2c_slave_irq(void *arg) return OK; } +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif esp_i2c_process(priv , irq_status); i2c_ll_clear_intr_mask(priv->ctx->dev, irq_status); +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif return OK; } #endif @@ -721,7 +739,13 @@ static int esp_i2c_slave_thread(int argc, char **argv) nxsched_usleep(1000); while (true) { +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif esp_i2c_slave_polling_waitdone(priv); +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif /* Sleeping thread before checking i2c peripheral */ @@ -833,6 +857,9 @@ struct i2c_slave_s *esp_i2cbus_slave_initialize(int port, int addr) { struct esp_i2c_priv_s *priv; int ret; +#ifdef CONFIG_PM + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; +#endif switch (port) { @@ -862,6 +889,35 @@ struct i2c_slave_s *esp_i2cbus_slave_initialize(int port, int addr) return (struct i2c_slave_s *)priv; } +#ifdef CONFIG_PM +# if SOC_I2C_SUPPORT_RTC + if (I2C_CLK_SRC_DEFAULT == I2C_CLK_SRC_RC_FAST) + { + pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; + } +# endif + +# if SOC_I2C_SUPPORT_APB + if (I2C_CLK_SRC_DEFAULT == I2C_CLK_SRC_APB) + { + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } +# endif + + ret = esp_pm_lock_create(pm_lock_type, + 0, + i2c_periph_signal[priv->id].module_name, + &priv->pm_lock); + if (ret != OK) + { + priv->refs--; + nxmutex_unlock(&priv->lock); + i2cerr("Failed to create I2C PM lock." + "Handler: %p\n", priv); + return NULL; + } +#endif + #ifndef CONFIG_I2C_POLLED if (priv->cpuint != -ENOMEM) { @@ -956,6 +1012,14 @@ int esp_i2cbus_slave_uninitialize(struct i2c_slave_s *dev) return OK; } +#ifdef CONFIG_PM + if (priv->pm_lock != NULL) + { + esp_pm_lock_delete(priv->pm_lock); + priv->pm_lock = NULL; + } +#endif + #ifndef CONFIG_I2C_POLLED up_disable_irq(ESP_SOURCE2IRQ(i2c_periph_signal[priv->id].irq)); esp_teardown_irq(i2c_periph_signal[priv->id].irq, priv->cpuint); diff --git a/arch/risc-v/src/common/espressif/esp_i2s.c b/arch/risc-v/src/common/espressif/esp_i2s.c index 6d3837cde0eaf..cd60b631e93a6 100644 --- a/arch/risc-v/src/common/espressif/esp_i2s.c +++ b/arch/risc-v/src/common/espressif/esp_i2s.c @@ -64,19 +64,24 @@ #include "soc/lldesc.h" #include "hal/dma_types.h" #if SOC_I2S_SUPPORTS_APLL -#include "hal/clk_tree_ll.h" -#include "clk_ctrl_os.h" +# include "hal/clk_tree_ll.h" +# include "clk_ctrl_os.h" #endif #include "hal/gdma_periph.h" #include "hal/gdma_ll.h" #if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE -#include "hal/cache_hal.h" -#include "hal/cache_ll.h" +# include "hal/cache_hal.h" +# include "hal/cache_ll.h" #endif #if SOC_GDMA_SUPPORTED -#include "esp_private/gdma.h" +# include "esp_private/gdma.h" +#endif + +#ifdef CONFIG_PM +# include "soc/soc_caps.h" +# include "include/esp_pm.h" #endif /**************************************************************************** @@ -235,6 +240,9 @@ struct esp_i2s_config_s i2s_hal_context_t *ctx; /* Common layer struct */ i2s_hal_clock_info_t *clk_info; /* Common layer clock info struct */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; struct esp_buffer_s @@ -470,6 +478,9 @@ static struct esp_i2s_config_s esp_i2s0_config = .audio_std_mode = I2S_TDM_PHILIPS, .ctx = &ctx_i2s0, .clk_info = &clk_info_i2s0, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; static struct esp_i2s_s esp_i2s0_priv = @@ -2224,6 +2235,10 @@ static void i2s_tx_channel_start(struct esp_i2s_s *priv) { if (priv->config->tx_en) { +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->config->pm_lock); +#endif + /* Reset the TX channel */ i2s_hal_tx_reset(priv->config->ctx); @@ -2262,6 +2277,10 @@ static void i2s_rx_channel_start(struct esp_i2s_s *priv) { if (priv->config->rx_en) { +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->config->pm_lock); +#endif + /* Reset the RX channel */ i2s_hal_rx_reset(priv->config->ctx); @@ -2317,6 +2336,9 @@ static int i2s_tx_channel_stop(struct esp_i2s_s *priv) } priv->tx_started = false; +#ifdef CONFIG_PM + esp_pm_lock_release(priv->config->pm_lock); +#endif i2sinfo("Stopped TX channel of port %ld\n", priv->config->port); } @@ -2363,6 +2385,9 @@ static int i2s_rx_channel_stop(struct esp_i2s_s *priv) } priv->rx_started = false; +#ifdef CONFIG_PM + esp_pm_lock_release(priv->config->pm_lock); +#endif i2sinfo("Stopped RX channel of port %ld\n", priv->config->port); } @@ -3412,6 +3437,9 @@ struct i2s_dev_s *esp_i2sbus_initialize(int port) int ret; struct esp_i2s_s *priv = NULL; irqstate_t flags; +#ifdef CONFIG_PM + esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX; +#endif i2sinfo("port: %d\n", port); @@ -3438,6 +3466,30 @@ struct i2s_dev_s *esp_i2sbus_initialize(int port) flags = spin_lock_irqsave(&priv->slock); +#ifdef CONFIG_PM +# if SOC_I2S_SUPPORTS_APLL && SOC_I2S_HW_VERSION_2 + if (priv.tx_clk_src == I2S_CLK_SRC_APLL && + priv.tx_clk_src == I2S_CLK_SRC_APLL) + { + pm_type = ESP_PM_NO_LIGHT_SLEEP; + } +# endif + + if (priv->config->pm_lock == NULL) + { + esp_pm_lock_handle_t pm_lock = priv->config->pm_lock; + ret = esp_pm_lock_create(pm_type, + 0, + "i2s_driver", + &pm_lock); + if (ret != OK) + { + i2serr("Failed to create I2S PM lock\n"); + goto err; + } + } +#endif + ret = i2s_configure(priv); if (ret < 0) { diff --git a/arch/risc-v/src/common/espressif/esp_idle.c b/arch/risc-v/src/common/espressif/esp_idle.c index b09dc5bc51b0f..1d1384ab7d3ae 100644 --- a/arch/risc-v/src/common/espressif/esp_idle.c +++ b/arch/risc-v/src/common/espressif/esp_idle.c @@ -47,8 +47,8 @@ #include "esp_tickless.h" #endif -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP #include "esp_private/pm_impl.h" +#if defined(CONFIG_ESPRESSIF_AUTO_SLEEP) || defined(CONFIG_ESPRESSIF_DFS) #include "platform/os.h" #endif @@ -236,12 +236,8 @@ void up_idle(void) * sleep in a reduced power mode until an interrupt occurs to save power */ -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP esp_pm_impl_idle_hook(); esp_pm_impl_waiti(); -#else - asm("WFI"); -#endif /* Perform IDLE mode power management */ diff --git a/arch/risc-v/src/common/espressif/esp_mcpwm.c b/arch/risc-v/src/common/espressif/esp_mcpwm.c index 10643b6c8622c..a3a33dc6bbcc4 100644 --- a/arch/risc-v/src/common/espressif/esp_mcpwm.c +++ b/arch/risc-v/src/common/espressif/esp_mcpwm.c @@ -54,6 +54,9 @@ #include "hal/clk_tree_hal.h" #include "esp_clk_tree.h" #include "esp_private/esp_clk_tree_common.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif #ifdef CONFIG_ESP_MCPWM @@ -162,6 +165,9 @@ struct mcpwm_dev_common_s bool initialized; /* MCPWM periph. and HAL has been initialized */ bool isr_initialized; /* Shared ISR has been initialized */ int group_prescale; +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; #ifdef CONFIG_ESP_MCPWM_MOTOR @@ -318,6 +324,9 @@ static struct mcpwm_dev_common_s g_mcpwm_common = .initialized = false, .isr_initialized = false, .group_prescale = MCPWM_DEV_CLK_PRESCALE, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; /* Motor specific data structures */ @@ -537,6 +546,10 @@ static int esp_motor_shutdown(struct motor_lowerhalf_s *dev) esp_motor_fault_configure(priv, false); #endif +#ifdef CONFIG_PM + esp_pm_lock_release(g_mcpwm_common.pm_lock); +#endif + spin_unlock_irqrestore(&g_mcpwm_common.mcpwm_spinlock, flags); return OK; } @@ -641,6 +654,11 @@ static int esp_motor_start(struct motor_lowerhalf_s *dev) float duty; flags = spin_lock_irqsave(&g_mcpwm_common.mcpwm_spinlock); + +#ifdef CONFIG_PM + esp_pm_lock_acquire(g_mcpwm_common.pm_lock); +#endif + if (priv->state.state == MOTOR_STATE_RUN) { spin_unlock_irqrestore(&g_mcpwm_common.mcpwm_spinlock, flags); @@ -1450,6 +1468,10 @@ static int esp_capture_start(struct cap_lowerhalf_s *lower) mcpwm_hal_context_t *hal = &priv->common->hal; flags = spin_lock_irqsave(&priv->common->mcpwm_spinlock); +#ifdef CONFIG_PM + esp_pm_lock_acquire(g_mcpwm_common.pm_lock); +#endif + /* Enable channel and interruption for rising edge */ mcpwm_ll_capture_enable_timer(g_mcpwm_common.hal.dev, true); @@ -1512,6 +1534,10 @@ static int esp_capture_stop(struct cap_lowerhalf_s *lower) false); priv->enabled = false; +#ifdef CONFIG_PM + esp_pm_lock_release(g_mcpwm_common.pm_lock); +#endif + spin_unlock_irqrestore(&priv->common->mcpwm_spinlock, flags); cpinfo("Channel disabled: %d\n", priv->channel_id); return OK; @@ -1955,6 +1981,16 @@ struct motor_lowerhalf_s *esp_motor_bdc_initialize(int channel, if (!g_mcpwm_common.initialized) { +#ifdef CONFIG_PM + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, + "mcpwm", &g_mcpwm_common.pm_lock); + if (ret != OK) + { + mtrerr("Failed to create MCPWM PM lock\n"); + return NULL; + } +#endif + esp_mcpwm_group_start(); } @@ -2028,6 +2064,9 @@ struct cap_lowerhalf_s *esp_mcpwm_capture_initialize(int channel, int pin) { struct mcpwm_cap_channel_lowerhalf_s *lower = NULL; uint32_t group_clock; +#ifdef CONFIG_PM + int ret; +#endif /* Single time initialization for the entire MCPWM Peripheral * and MCPWM Capture group. @@ -2035,6 +2074,16 @@ struct cap_lowerhalf_s *esp_mcpwm_capture_initialize(int channel, int pin) if (!g_mcpwm_common.initialized) { +#ifdef CONFIG_PM + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, + "mcpwm", &g_mcpwm_common.pm_lock); + if (ret != OK) + { + mtrerr("Failed to create MCPWM PM lock\n"); + return NULL; + } +#endif + esp_mcpwm_group_start(); } diff --git a/arch/risc-v/src/common/espressif/esp_oneshot.c b/arch/risc-v/src/common/espressif/esp_oneshot.c index 281188baac4ae..8c3567c5e909e 100644 --- a/arch/risc-v/src/common/espressif/esp_oneshot.c +++ b/arch/risc-v/src/common/espressif/esp_oneshot.c @@ -47,6 +47,9 @@ #include "periph_ctrl.h" #include "soc/clk_tree_defs.h" #include "esp_private/esp_clk_tree_common.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -81,6 +84,9 @@ struct esp_oneshot_lowerhalf_s struct oneshot_lowerhalf_s lh; /* Lower half instance */ timer_hal_context_t hal; /* HAL context */ bool running; /* True: the timer is running */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -124,6 +130,9 @@ static struct esp_oneshot_lowerhalf_s g_oneshot_lowerhalf = { .ops = &g_oneshot_ops, }, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; /**************************************************************************** @@ -196,6 +205,13 @@ static void esp_oneshot_start(struct oneshot_lowerhalf_s *lower, timer_hal_context_t *hal = &(priv->hal); +#ifdef CONFIG_PM + if (priv->pm_lock) + { + esp_pm_lock_acquire(priv->pm_lock); + } +#endif + /* Make sure the timer is stopped to avoid unpredictable behavior */ timer_ll_enable_intr(hal->dev, TIMER_LL_EVENT_ALARM(hal->timer_id), @@ -298,6 +314,13 @@ static void esp_oneshot_cancel(struct oneshot_lowerhalf_s *lower) timer_ll_enable_counter(hal->dev, hal->timer_id, false); } +#ifdef CONFIG_PM + if (priv->pm_lock) + { + esp_pm_lock_release(priv->pm_lock); + } +#endif + priv->running = false; } @@ -405,6 +428,10 @@ struct oneshot_lowerhalf_s *oneshot_initialize(int chan, uint16_t resolution) int ret = OK; shared_periph_module_t periph; int irq; +#ifdef CONFIG_PM + bool need_pm_lock = true; + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; +#endif UNUSED(chan); @@ -455,6 +482,34 @@ struct oneshot_lowerhalf_s *oneshot_initialize(int chan, uint16_t resolution) timer_ll_set_clock_prescale(lower->hal.dev, lower->hal.timer_id, prescale); +#ifdef CONFIG_PM +# if TIMER_LL_FUNC_CLOCK_SUPPORT_RC_FAST + if (GPTIMER_CLK_SRC_DEFAULT == GPTIMER_CLK_SRC_RC_FAST) + { + need_pm_lock = false; + } +# endif + +# if TIMER_LL_FUNC_CLOCK_SUPPORT_APB + if (GPTIMER_CLK_SRC_DEFAULT == GPTIMER_CLK_SRC_APB) + { + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } +# endif + + if (need_pm_lock && lower->pm_lock == NULL) + { + ret = esp_pm_lock_create(pm_lock_type, 0, + "ONESHOT", + &lower->pm_lock); + if (ret != OK) + { + tmrerr("Failed to create oneshot PM lock\n"); + return NULL; + } + } +#endif + irq = soc_timg_gptimer_signals[GROUP_ID][TIMER_ID].irq_id; esp_setup_irq(irq, diff --git a/arch/risc-v/src/common/espressif/esp_pcnt.c b/arch/risc-v/src/common/espressif/esp_pcnt.c index 9141cdfc22dbe..5ef94528b3b27 100644 --- a/arch/risc-v/src/common/espressif/esp_pcnt.c +++ b/arch/risc-v/src/common/espressif/esp_pcnt.c @@ -60,6 +60,9 @@ #include "esp_clk.h" #include "esp_irq.h" #include "esp_attr.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -117,6 +120,9 @@ struct esp_pcnt_priv_s uint32_t accum_value; /* Accumulator value of overflowed PCNT unit */ bool channels[PCNT_LL_GET(CHANS_PER_UNIT)]; /* Channel information of PCNT unit */ struct esp_pcnt_watch_point_priv_s watchers[PCNT_LL_WATCH_EVENT_MAX]; /* array of PCNT watchers */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -508,6 +514,10 @@ static int esp_pcnt_unit_enable(struct cap_lowerhalf_s *dev) true); } +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif + priv->state = PCNT_UNIT_ENABLE; return OK; } @@ -548,6 +558,10 @@ static int esp_pcnt_unit_disable(struct cap_lowerhalf_s *dev) false); } +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif + priv->state = PCNT_UNIT_INIT; return OK; } @@ -818,6 +832,9 @@ struct cap_lowerhalf_s *esp_pcnt_new_unit( int ret; int i; irqstate_t flags; +#ifdef CONFIG_PM + esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP; +#endif if (config == NULL) { @@ -874,6 +891,25 @@ struct cap_lowerhalf_s *esp_pcnt_new_unit( spin_unlock_irqrestore(&g_pcnt_lock, flags); cpinfo("Allocated pcnt unit: %" PRId16 "\n", unit_id); +#ifdef CONFIG_PM +# if PCNT_LL_CLOCK_SUPPORT_APB + if (PCNT_CLK_SRC_DEFAULT == PCNT_CLK_SRC_APB) + { + pm_lock_type = ESP_PM_APB_FREQ_MAX; + } + +# endif + ret = esp_pm_lock_create(pm_lock_type, + 0, + soc_pcnt_signals[unit_id].module_name, + &pcnt_units[unit_id].pm_lock); + if (ret != OK) + { + cperr("Failed to create PCNT PM lock\n"); + return NULL; + } +#endif + if (!g_pcnt_intr) { nxmutex_lock(&g_pcnt_mutex); @@ -987,6 +1023,11 @@ int esp_pcnt_del_unit(struct cap_lowerhalf_s *dev) esp_teardown_irq(soc_pcnt_signals[0].irq_id, -ENOMEM); } +#ifdef CONFIG_PM + esp_pm_lock_delete(priv->pm_lock); + priv->pm_lock = NULL; +#endif + spin_unlock_irqrestore(&priv->lock, flags); return OK; diff --git a/arch/risc-v/src/common/espressif/esp_pm.c b/arch/risc-v/src/common/espressif/esp_pm.c index f4a9e900826cc..0bd28b90dfa3b 100644 --- a/arch/risc-v/src/common/espressif/esp_pm.c +++ b/arch/risc-v/src/common/espressif/esp_pm.c @@ -862,8 +862,6 @@ void esp_pmsleep(uint64_t time_in_us) esp_pm_deep_sleep_start(); } -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP - /**************************************************************************** * Name: esp_pmconfigure * @@ -891,9 +889,13 @@ int esp_pmconfigure(void) esp_pm_config_t pm_config = { .max_freq_mhz = CONFIG_ESPRESSIF_CPU_FREQ_MHZ, +#ifdef CONFIG_ESPRESSIF_DFS + .min_freq_mhz = CONFIG_ESPRESSIF_MIN_CPU_FREQ_MHZ, +#else .min_freq_mhz = CONFIG_ESPRESSIF_CPU_FREQ_MHZ, +#endif #ifdef CONFIG_ESPRESSIF_AUTO_SLEEP - .light_sleep_enable = true + .light_sleep_enable = false #endif }; @@ -916,6 +918,7 @@ int esp_pmconfigure(void) esp_pm_uart_wakeup_prepare(); #endif /* CONFIG_PM_UART_WAKEUP */ +#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP err = esp_pm_register_skip_light_sleep_callback( esp_pm_skip_light_sleep); if (err != ESP_OK) @@ -948,7 +951,7 @@ int esp_pmconfigure(void) pwrerr("Failed to set console UART handling mode: %d\n", err); return -ENOMEM; } +#endif return ret; } -#endif /* CONFIG_ESPRESSIF_AUTO_SLEEP */ diff --git a/arch/risc-v/src/common/espressif/esp_pm.h b/arch/risc-v/src/common/espressif/esp_pm.h index 596c7083f88cb..6962fcfc971eb 100644 --- a/arch/risc-v/src/common/espressif/esp_pm.h +++ b/arch/risc-v/src/common/espressif/esp_pm.h @@ -148,9 +148,8 @@ void esp_pmsleep(uint64_t time_in_us); * Returns OK on success; a negated errno value on failure. * ****************************************************************************/ -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP + int esp_pmconfigure(void); -#endif /**************************************************************************** * Name: esp_pm_wakeup_set_last_reason diff --git a/arch/risc-v/src/common/espressif/esp_sdm.c b/arch/risc-v/src/common/espressif/esp_sdm.c index d53db13449d81..a5af4132c4ec2 100644 --- a/arch/risc-v/src/common/espressif/esp_sdm.c +++ b/arch/risc-v/src/common/espressif/esp_sdm.c @@ -47,6 +47,9 @@ #include "hal/sdm_periph.h" #include "hal/sdm_caps.h" #include "hal/gpio_ll.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -73,6 +76,9 @@ struct esp_sdm_group_priv_s sdm_hal_context_t hal; /* Common layer context */ soc_periph_sdm_clk_src_t clk_src; /* Clock source */ struct esp_sdm_channel_priv_s *channels[SDM_CAPS_GET(CHANS_PER_INST)]; /* Array of SDM channels */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; struct esp_sdm_priv_s @@ -167,6 +173,13 @@ static int dac_setup(struct dac_dev_s *dev) { struct esp_sdm_group_priv_s *group = (struct esp_sdm_group_priv_s *) dev->ad_priv; +#ifdef CONFIG_PM + if (group->pm_lock) + { + esp_pm_lock_acquire(group->pm_lock); + } +#endif + sdm_ll_enable_clock(group->hal.dev, true); return OK; } @@ -189,6 +202,13 @@ static void dac_shutdown(struct dac_dev_s *dev) { struct esp_sdm_group_priv_s *group = (struct esp_sdm_group_priv_s *) dev->ad_priv; +#ifdef CONFIG_PM + if (group->pm_lock) + { + esp_pm_lock_release(group->pm_lock); + } +#endif + sdm_ll_enable_clock(group->hal.dev, false); } @@ -407,6 +427,10 @@ static struct esp_sdm_group_priv_s *esp_sdm_init( int group_id = 0; int chan_id = -1; irqstate_t flags; +#ifdef CONFIG_PM + esp_pm_lock_type_t pm_type = ESP_PM_NO_LIGHT_SLEEP; + int res; +#endif DEBUGASSERT(GPIO_IS_VALID_GPIO(config.gpio_num)); @@ -420,6 +444,7 @@ static struct esp_sdm_group_priv_s *esp_sdm_init( if (g_esp_sdm.groups[i] == NULL) { aerr("Error! No mem for group (%d)\n", i); + nxrmutex_unlock(&(g_esp_sdm.lock)); return NULL; } else @@ -435,6 +460,24 @@ static struct esp_sdm_group_priv_s *esp_sdm_init( sdm_hal_init(&g_esp_sdm.groups[i]->hal, &hal_config); sdm_ll_enable_clock(g_esp_sdm.groups[i]->hal.dev, true); ainfo("new group (%d) at %p\n", i, g_esp_sdm.groups[i]); +#ifdef CONFIG_PM +# if SDM_CAPS_GET(FUNC_CLOCK_SUPPORT_APB) + if (clk_src == SDM_CLK_SRC_APB) + { + pm_type = ESP_PM_APB_FREQ_MAX; + } +# endif + + res = esp_pm_lock_create(pm_type, 0, + soc_sdm_signals[group_id].module_name, + &g_esp_sdm.groups[i]->pm_lock); + if (res != OK) + { + aerr("Error! No mem to PM lock for group (%d)\n", i); + nxrmutex_unlock(&(g_esp_sdm.lock)); + return NULL; + } +#endif break; } } diff --git a/arch/risc-v/src/common/espressif/esp_spi.c b/arch/risc-v/src/common/espressif/esp_spi.c index 114e67a57d2f3..ca6760d28e7e5 100644 --- a/arch/risc-v/src/common/espressif/esp_spi.c +++ b/arch/risc-v/src/common/espressif/esp_spi.c @@ -73,6 +73,10 @@ # include "esp_private/gdma.h" #endif +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -224,6 +228,9 @@ struct esp_spi_priv_s spi_hal_context_t *ctx; /* Context struct of common layer */ spi_hal_dev_config_t *dev_cfg; /* Device configuration struct of common layer */ spi_hal_timing_param_t *timing_param; /* Timing struct of common layer */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -387,6 +394,9 @@ static struct esp_spi_priv_s esp_spi2_priv = .sem_isr = SEM_INITIALIZER(0), .cpuint = -ENOMEM, #endif +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; #endif /* CONFIG_ESPRESSIF_SPI2 */ @@ -1086,8 +1096,17 @@ static uint32_t esp_spi_poll_send(struct esp_spi_priv_s *priv, uint32_t wd) static uint32_t esp_spi_send(struct spi_dev_s *dev, uint32_t wd) { struct esp_spi_priv_s *priv = (struct esp_spi_priv_s *)dev; + int ret; + +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif + ret = esp_spi_poll_send(priv, wd); +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif - return esp_spi_poll_send(priv, wd); + return ret; } /**************************************************************************** @@ -1214,6 +1233,9 @@ static void esp_spi_exchange(struct spi_dev_s *dev, { struct esp_spi_priv_s *priv = (struct esp_spi_priv_s *)dev; +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif #ifdef CONFIG_ESPRESSIF_SPI2_DMA size_t thld = CONFIG_ESPRESSIF_SPI2_DMATHRESHOLD; @@ -1226,6 +1248,10 @@ static void esp_spi_exchange(struct spi_dev_s *dev, { esp_spi_poll_exchange(priv, txbuffer, rxbuffer, nwords); } + +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif } #ifndef CONFIG_SPI_EXCHANGE @@ -1539,6 +1565,9 @@ struct spi_dev_s *esp_spibus_initialize(int port) { struct spi_dev_s *spi_dev; struct esp_spi_priv_s *priv; +#ifdef CONFIG_PM + int ret; +#endif switch (port) { @@ -1561,6 +1590,20 @@ struct spi_dev_s *esp_spibus_initialize(int port) return spi_dev; } +#ifdef CONFIG_PM +# if CONFIG_ARCH_CHIP_ESP32P4 + ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "spi", &priv->pm_lock); +# else + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi", &priv->pm_lock); +# endif + if (ret != OK) + { + nxmutex_unlock(&priv->lock); + spierr("Failed to create SPI PM lock for SPI:%" PRId8 "\n", priv->id); + return NULL; + } +#endif + /* Initialize the blank array */ for (int i = 0; i < SPI_BLANK_ARRAY_SIZE; i++) @@ -1639,6 +1682,11 @@ int esp_spibus_uninitialize(struct spi_dev_s *dev) priv->cpuint = -ENOMEM; #endif +#ifdef CONFIG_PM + esp_pm_lock_delete(priv->pm_lock); + priv->pm_lock = NULL; +#endif + esp_spi_deinit(dev); nxmutex_unlock(&priv->lock); diff --git a/arch/risc-v/src/common/espressif/esp_spi_slave.c b/arch/risc-v/src/common/espressif/esp_spi_slave.c index 71077e34cdaf8..87669a9306061 100644 --- a/arch/risc-v/src/common/espressif/esp_spi_slave.c +++ b/arch/risc-v/src/common/espressif/esp_spi_slave.c @@ -65,6 +65,10 @@ #include "riscv_internal.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -220,6 +224,9 @@ struct spislave_priv_s bool is_tx_enabled; spi_slave_hal_context_t ctx; /* Context struct of the common layer */ spi_slave_hal_config_t cfg; /* Configuration struct of the common layer */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -1045,6 +1052,9 @@ static void spislave_bind(struct spi_slave_ctrlr_s *ctrlr, DEBUGASSERT(nbits > 0); flags = enter_critical_section(); +#ifdef CONFIG_PM + esp_pm_lock_acquire(priv->pm_lock); +#endif priv->dev = dev; @@ -1172,6 +1182,9 @@ static void spislave_unbind(struct spi_slave_ctrlr_s *ctrlr) #endif priv->dev = NULL; +#ifdef CONFIG_PM + esp_pm_lock_release(priv->pm_lock); +#endif leave_critical_section(flags); } @@ -1407,6 +1420,22 @@ struct spi_slave_ctrlr_s *esp_spislave_ctrlr_initialize(int port) return spislave_dev; } +#ifdef CONFIG_PM +# if CONFIG_ARCH_CHIP_ESP32P4 + ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, + "spi_slave", &priv->pm_lock); +# else + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, + "spi_slave", &priv->pm_lock); +# endif + if (ret != OK) + { + spierr("Failed to create SPI PM lock for SPI slave driver\n"); + leave_critical_section(flags); + return NULL; + } +#endif + /* Attach IRQ for CS pin interrupt */ ret = esp_gpio_irq(priv->config->cs_pin, @@ -1509,6 +1538,13 @@ int esp_spislave_ctrlr_uninitialize(struct spi_slave_ctrlr_s *ctrlr) priv->rx_length = 0; priv->is_processing = false; priv->is_tx_enabled = false; +#ifdef CONFIG_PM + if (priv->pm_lock != NULL) + { + esp_pm_lock_delete(priv->pm_lock); + priv->pm_lock = NULL; + } +#endif leave_critical_section(flags); diff --git a/arch/risc-v/src/common/espressif/esp_twai.c b/arch/risc-v/src/common/espressif/esp_twai.c index 96ff99d130a82..77920410d3e46 100644 --- a/arch/risc-v/src/common/espressif/esp_twai.c +++ b/arch/risc-v/src/common/espressif/esp_twai.c @@ -55,6 +55,9 @@ #include "hal/twai_periph.h" #include "soc/gpio_sig_map.h" #include "soc/reg_base.h" +#ifdef CONFIG_PM +# include "include/esp_pm.h" +#endif /**************************************************************************** * Pre-processor Definitions @@ -142,6 +145,9 @@ struct esp_twai_dev_s int8_t cpuint; /* CPU interrupt assigned to this TWAI */ twai_hal_context_t ctx; /* Context struct of common layer */ twai_timing_config_t t_config; /* Timing struct of common layer */ +#ifdef CONFIG_PM + esp_pm_lock_handle_t pm_lock; /* Power management lock */ +#endif }; /**************************************************************************** @@ -190,6 +196,9 @@ static struct esp_twai_dev_s g_twai0priv = .port = 0, .cpuint = -ENOMEM, .t_config = TWAI0_TIMING_CONFIG, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; static struct can_dev_s g_twai0dev = @@ -205,6 +214,9 @@ static struct esp_twai_dev_s g_twai1priv = .port = 1, .cpuint = -ENOMEM, .t_config = TWAI1_TIMING_CONFIG, +#ifdef CONFIG_PM + .pm_lock = NULL, +#endif }; static struct can_dev_s g_twai1dev = @@ -273,6 +285,13 @@ static void esp_twai_reset(struct can_dev_s *dev) ASSERT(ret); twai_hal_configure(&priv->ctx, &priv->t_config, &f_config, 0); +#ifdef CONFIG_PM + if (priv->pm_lock) + { + esp_pm_lock_acquire(priv->pm_lock); + } +#endif + /* Restart the TWAI */ twai_hal_start(&priv->ctx); @@ -799,6 +818,10 @@ struct can_dev_s *esp_twaiinitialize(int port) { struct can_dev_s *dev; irqstate_t flags; +#ifdef CONFIG_PM + int ret; + struct esp_twai_dev_s *priv; +#endif caninfo("TWAI%" PRIu8 "\n", port); @@ -848,6 +871,34 @@ struct can_dev_s *esp_twaiinitialize(int port) return NULL; } +#ifdef CONFIG_PM + priv = (struct esp_twai_dev_s *)dev->cd_priv; + + if (priv->pm_lock == NULL) + { +# if TWAI_LL_SUPPORT(APB_CLK) + if (TWAI_CLK_SRC_DEFAULT == TWAI_CLK_SRC_APB) + { + ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, + 0, + twai_periph_signals[port].module_name, + &priv->pm_lock); + } +# else + ret = esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, + 0, + twai_periph_signals[port].module_name, + &priv->pm_lock); +# endif + if (ret != OK) + { + canerr("Failed to create TWAI%" PRIu8 "PM lock\n", port); + leave_critical_section(flags); + return NULL; + } + } +#endif + /* Then just perform a TWAI reset operation */ esp_twai_reset(dev); diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake index bdf4c85144438..2bafc54031acc 100644 --- a/arch/risc-v/src/esp32p4/hal_esp32p4.cmake +++ b/arch/risc-v/src/esp32p4/hal_esp32p4.cmake @@ -305,6 +305,7 @@ list( ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/periph_ctrl.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/lowpower/port/${CHIP_SERIES}/sleep_cpu_asm.S ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/lowpower/port/${CHIP_SERIES}/sleep_cpu.c + ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/lowpower/port/${CHIP_SERIES}/sleep_cpu_static.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/lowpower/port/${CHIP_SERIES}/sleep_clock.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/port/${CHIP_SERIES}/cpu_region_protect.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_hw_support/port/${CHIP_SERIES}/esp_clk_tree.c @@ -341,6 +342,8 @@ list( ${ESP_HAL_3RDPARTY_REPO}/components/esp_mm/esp_cache_utils.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_mm/esp_mmu_map.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_mm/port/${CHIP_SERIES}/ext_mem_layout.c + ${ESP_HAL_3RDPARTY_REPO}/components/esp_pm/pm_impl.c + ${ESP_HAL_3RDPARTY_REPO}/components/esp_pm/pm_locks.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_rom/patches/esp_rom_clic.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_rom/patches/esp_rom_crc.c ${ESP_HAL_3RDPARTY_REPO}/components/esp_rom/patches/esp_rom_efuse.c diff --git a/arch/risc-v/src/esp32p4/hal_esp32p4.mk b/arch/risc-v/src/esp32p4/hal_esp32p4.mk index 6b4fb09f47745..e9d1f703163b0 100644 --- a/arch/risc-v/src/esp32p4/hal_esp32p4.mk +++ b/arch/risc-v/src/esp32p4/hal_esp32p4.mk @@ -265,6 +265,7 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)periph_ctrl.c CHIP_ASRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_cpu_asm.S CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_cpu.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_cpu_static.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)lowpower$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)sleep_clock.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)regdma_link.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_hw_support$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)cpu_region_protect.c @@ -301,6 +302,8 @@ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_ CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)esp_cache_utils.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)esp_mmu_map.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_mm$(DELIM)port$(DELIM)$(CHIP_SERIES)$(DELIM)ext_mem_layout.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_pm$(DELIM)pm_impl.c +CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_pm$(DELIM)pm_locks.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)patches$(DELIM)esp_rom_clic.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)patches$(DELIM)esp_rom_crc.c CHIP_CSRCS += chip$(DELIM)$(ESP_HAL_3RDPARTY_REPO)$(DELIM)components$(DELIM)esp_rom$(DELIM)patches$(DELIM)esp_rom_efuse.c diff --git a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c index fa2db59a6fd37..65cb798ae342b 100644 --- a/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c +++ b/boards/risc-v/esp32c3/esp32c3-devkit/src/esp32c3_bringup.c @@ -461,7 +461,7 @@ int esp_bringup(void) } #endif /* CONFIG_ESPRESSIF_LEDC */ -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP +#ifdef CONFIG_PM /* Configure PM */ ret = esp_pmconfigure(); diff --git a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c index 78c6668e2c607..6340b3cf73012 100644 --- a/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c +++ b/boards/risc-v/esp32c6/esp32c6-devkitc/src/esp32c6_bringup.c @@ -509,7 +509,7 @@ int esp_bringup(void) } #endif -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP +#ifdef CONFIG_PM /* Configure PM */ ret = esp_pmconfigure(); diff --git a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c index 8c4120eff806d..b45476008b6bf 100644 --- a/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c +++ b/boards/risc-v/esp32h2/esp32h2-devkit/src/esp32h2_bringup.c @@ -451,7 +451,7 @@ int esp_bringup(void) } #endif -#ifdef CONFIG_ESPRESSIF_AUTO_SLEEP +#ifdef CONFIG_PM /* Configure PM */ ret = esp_pmconfigure(); diff --git a/boards/risc-v/esp32p4/esp32p4-function-ev-board/src/esp32p4_bringup.c b/boards/risc-v/esp32p4/esp32p4-function-ev-board/src/esp32p4_bringup.c index 5b6b1cf2265cf..ca25f2aee8fe9 100644 --- a/boards/risc-v/esp32p4/esp32p4-function-ev-board/src/esp32p4_bringup.c +++ b/boards/risc-v/esp32p4/esp32p4-function-ev-board/src/esp32p4_bringup.c @@ -109,6 +109,10 @@ # include "esp_board_adc.h" #endif +#ifdef CONFIG_PM +# include "espressif/esp_pm.h" +#endif + #ifdef CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP_WO_TOOL # include "espressif/esp_nxdiag.h" #endif @@ -423,6 +427,16 @@ int esp_bringup(void) } #endif +#ifdef CONFIG_PM + /* Configure PM */ + + ret = esp_pmconfigure(); + if (ret < 0) + { + syslog(LOG_ERR, "ERROR: esp_pmconfigure failed: %d\n", ret); + } +#endif + #ifdef CONFIG_SYSTEM_NXDIAG_ESPRESSIF_CHIP_WO_TOOL ret = esp_nxdiag_initialize(); if (ret < 0)