diff --git a/dts/arm/silabs/siwg917.dtsi b/dts/arm/silabs/siwg917.dtsi index 39059dcbb45..aea93747c8a 100644 --- a/dts/arm/silabs/siwg917.dtsi +++ b/dts/arm/silabs/siwg917.dtsi @@ -24,6 +24,20 @@ cpu0: cpu@0 { compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&pstate_ps4_standby &pstate_ps4_sleep>; + }; + + power-states { + pstate_ps4_standby: ps4_standby { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + }; + pstate_ps4_sleep: ps4_sleep { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <100000>; + exit-latency-us = <3000>; + }; }; }; diff --git a/modules/hal_silabs/wiseconnect/CMakeLists.txt b/modules/hal_silabs/wiseconnect/CMakeLists.txt index 838b5e6a642..146c4c3b8fb 100644 --- a/modules/hal_silabs/wiseconnect/CMakeLists.txt +++ b/modules/hal_silabs/wiseconnect/CMakeLists.txt @@ -3,6 +3,7 @@ set(SISDK_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/simplicity_sdk) set(WISECONNECT_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/wiseconnect) +set(COMMON_DIR ${ZEPHYR_HAL_SILABS_MODULE_DIR}/simplicity_sdk/platform/common) # Keep these values sync with # components/device/silabs/si91x/mcu/core/chip/component/siwg917*.slcc @@ -23,16 +24,25 @@ zephyr_include_directories( ${SISDK_DIR}/platform/common/inc ${SISDK_DIR}/platform/common/config ${SISDK_DIR}/platform/service/mem_pool/inc - ${WISECONNECT_DIR}/components/board/silabs/inc + # Wiseconnect do not provide generic RTE_Device_917.h. However, all the boards + # share more-or-less the same definitions. So we could take any of them. + # In addtion, this file is only required for the compilation, but none the + # symbols are normally used by Zephyr (it is required to compile CMSIS API + # which is not not used). + ${WISECONNECT_DIR}/components/board/silabs/config/brd4342a ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/config ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/config + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/common/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/rom_driver/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/inc + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/inc + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/config ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/systemlevel/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/config + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_api/config/sl_i2s_config ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/unified_peripheral_drivers/inc ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/config ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver @@ -141,7 +151,7 @@ endif() # CONFIG_BT_SILABS_SIWX91X if(CONFIG_WISECONNECT_NETWORK_STACK) zephyr_compile_definitions( SLI_SI91X_ENABLE_OS - SL_SI91X_SI917_RAM_MEM_CONFIG=1 + SL_SI91X_SI917_RAM_MEM_CONFIG=2 SL_WIFI_COMPONENT_INCLUDED # Depite de the name, required for everything ) zephyr_include_directories( @@ -198,5 +208,49 @@ if(CONFIG_SOC_SILABS_SLEEPTIMER) ) endif() # CONFIG_SOC_SILABS_SLEEPTIMER +if(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR) + zephyr_library_sources( + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/common/src/rsi_debug.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/src/rsi_ps_ram_func.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/USART.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/UDMA.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/cmsis_driver/SAI.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/sl_si91x_m4_ps.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_usart.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_udma_wrapper.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_udma.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sl_si91x_power_manager.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sli_si91x_power_manager.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/clock_manager/src/sli_si91x_clock_manager.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/systemlevel/src/rsi_temp_sensor.c + ${COMMON_DIR}/src/sl_slist.c + ) + zephyr_include_directories( + ${COMMON_DIR}/inc + ) + zephyr_compile_definitions( + SL_CODE_COMPONENT_POWER_MANAGER=power_manager + SL_SI91X_TICKLESS_MODE + SL_SLEEP_TIMER + SL_SI91X_SI917_RAM_MEM_CONFIG=2 + SL_CODE_COMPONENT_CORE=core + DEBUG_ENABLE + DEBUG_UART + SLI_WIRELESS_COMPONENT_PRESENT + ) + zephyr_code_relocate(FILES + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/core/chip/src/rsi_deepsleep_soc.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sl_si91x_power_manager.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/power_manager/src/sli_si91x_power_manager.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/service/sleeptimer/src/sl_sleeptimer_hal_si91x_sysrtc.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/mcu/drivers/peripheral_drivers/src/rsi_sysrtc.c + ${SISDK_DIR}/platform/service/sleeptimer/src/sl_sleeptimer.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/wireless/ahb_interface/src/rsi_hal_mcu_m4_ram.c + ${WISECONNECT_DIR}/components/device/silabs/si91x/wireless/ahb_interface/src/rsi_hal_mcu_m4_rom.c + ${ZEPHYR_BASE}/drivers/gpio/*.c + LOCATION RAM + ) +endif() # CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR + zephyr_linker_sources(ROM_SECTIONS linker/code_classification_text.ld) zephyr_linker_sources(RAMFUNC_SECTION linker/code_classification_ramfunc.ld) diff --git a/soc/silabs/silabs_siwx91x/Kconfig b/soc/silabs/silabs_siwx91x/Kconfig index 458d55dc2c8..9f508223585 100644 --- a/soc/silabs/silabs_siwx91x/Kconfig +++ b/soc/silabs/silabs_siwx91x/Kconfig @@ -9,6 +9,7 @@ config SOC_FAMILY_SILABS_SIWX91X select CPU_HAS_ARM_MPU select HAS_SILABS_WISECONNECT select HAS_SEGGER_RTT if ZEPHYR_SEGGER_MODULE + select HAS_PM if SOC_FAMILY_SILABS_SIWX91X @@ -19,6 +20,16 @@ config SOC_SILABS_SLEEPTIMER help The Sleeptimer HAL module is used for SIWX91X. +config SOC_SIWX91X_PM_BACKEND_PMGR + bool + select WISECONNECT_NETWORK_STACK + select SILABS_SLEEPTIMER_TIMER + select SRAM_VECTOR_TABLE + select CODE_DATA_RELOCATION_SRAM + default y if PM + help + Implement PM using sl_power_manager service from Gecko SDK + config SIWX91X_NWP_INIT_PRIORITY int "SiWx91x Network Processor init priority" default 39 diff --git a/soc/silabs/silabs_siwx91x/Kconfig.defconfig b/soc/silabs/silabs_siwx91x/Kconfig.defconfig index f1498b6e003..5f9e8640dd5 100644 --- a/soc/silabs/silabs_siwx91x/Kconfig.defconfig +++ b/soc/silabs/silabs_siwx91x/Kconfig.defconfig @@ -3,9 +3,6 @@ if SOC_FAMILY_SILABS_SIWX91X -configdefault SILABS_SLEEPTIMER_TIMER - default y if PM - configdefault CORTEX_M_SYSTICK default n if SILABS_SLEEPTIMER_TIMER diff --git a/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt b/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt index d49353f7781..cbe06c37ac0 100644 --- a/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt +++ b/soc/silabs/silabs_siwx91x/siwg917/CMakeLists.txt @@ -3,5 +3,6 @@ zephyr_sources_ifdef(CONFIG_SOC_SERIES_SIWG917 soc.c) zephyr_sources_ifdef(CONFIG_WISECONNECT_NETWORK_STACK nwp.c) +zephyr_sources_ifdef(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR soc_siwx91x_power_pmgr.c) set(SOC_LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld CACHE INTERNAL "") diff --git a/soc/silabs/silabs_siwx91x/siwg917/nwp.c b/soc/silabs/silabs_siwx91x/siwg917/nwp.c index 8395925ebe9..6ee6c4c0e49 100644 --- a/soc/silabs/silabs_siwx91x/siwg917/nwp.c +++ b/soc/silabs/silabs_siwx91x/siwg917/nwp.c @@ -19,6 +19,7 @@ #ifdef CONFIG_BT_SILABS_SIWX91X #include "rsi_ble_common_config.h" #endif +#include "sl_si91x_power_manager.h" #define AP_MAX_NUM_STA 4 @@ -243,6 +244,8 @@ static int siwg917_nwp_init(void) { sl_wifi_device_configuration_t network_config; sl_status_t status; + __maybe_unused sl_wifi_performance_profile_t performance_profile = { + .profile = DEEP_SLEEP_WITH_RAM_RETENTION}; siwx91x_get_nwp_config(&network_config, WIFI_STA_MODE, false, 0); /* TODO: If sl_net_*_profile() functions will be needed for WiFi then call @@ -253,6 +256,14 @@ static int siwg917_nwp_init(void) return -EINVAL; } + if (IS_ENABLED(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR)) { + status = sl_wifi_set_performance_profile(&performance_profile); + if (status != SL_STATUS_OK) { + return -EINVAL; + } + /* Remove the previously added PS4 power state requirement */ + sl_si91x_power_manager_remove_ps_requirement(SL_SI91X_POWER_MANAGER_PS4); + } return 0; } #if defined(CONFIG_MBEDTLS_INIT) diff --git a/soc/silabs/silabs_siwx91x/siwg917/soc.c b/soc/silabs/silabs_siwx91x/siwg917/soc.c index 139b7f3492a..83f07c9a2f4 100644 --- a/soc/silabs/silabs_siwx91x/siwg917/soc.c +++ b/soc/silabs/silabs_siwx91x/siwg917/soc.c @@ -10,10 +10,28 @@ #include #include "em_device.h" +#ifdef CONFIG_WISECONNECT_NETWORK_STACK +#include "sli_siwx917_soc.h" +#endif +#include "sl_si91x_power_manager.h" void soc_early_init_hook(void) { + __maybe_unused sl_power_peripheral_t peripheral_config = {}; + __maybe_unused sl_power_ram_retention_config_t ram_configuration = { + .configure_ram_banks = false, + .m4ss_ram_size_kb = (DT_REG_SIZE(DT_NODELABEL(sram0)) / 1024), + .ulpss_ram_size_kb = 4, + }; SystemInit(); +#if IS_ENABLED(CONFIG_SOC_SIWX91X_PM_BACKEND_PMGR) + sli_si91x_platform_init(); + sl_si91x_power_manager_init(); + sl_si91x_power_manager_remove_peripheral_requirement(&peripheral_config); + sl_si91x_power_manager_configure_ram_retention(&ram_configuration); + sl_si91x_power_manager_add_ps_requirement(SL_SI91X_POWER_MANAGER_PS4); + sl_si91x_power_manager_set_clock_scaling(SL_SI91X_POWER_MANAGER_PERFORMANCE); +#endif } /* SiWx917's bootloader requires IRQn 32 to hold payload's entry point address. */ diff --git a/soc/silabs/silabs_siwx91x/siwg917/soc_siwx91x_power_pmgr.c b/soc/silabs/silabs_siwx91x/siwg917/soc_siwx91x_power_pmgr.c new file mode 100644 index 00000000000..b2cf1310673 --- /dev/null +++ b/soc/silabs/silabs_siwx91x/siwg917/soc_siwx91x_power_pmgr.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024-2025 Silicon Laboratories Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "sl_si91x_power_manager.h" +#include "sli_si91x_clock_manager.h" +#include "sl_rsi_utility.h" +#include "sl_si91x_m4_ps.h" + +LOG_MODULE_REGISTER(siwx91x_pm); + +extern uint32_t frontend_switch_control; + +/* + * Power state map: + * PM_STATE_RUNTIME_IDLE: SL_SI91X_POWER_MANAGER_STANDBY (PS4) + * PM_STATE_SUSPEND_TO_IDLE: SL_SI91X_POWER_MANAGER_SLEEP (PS4 Sleep) + */ +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(substate_id); + + /* Set PRIMASK */ + __disable_irq(); + /* Set BASEPRI to 0. */ + irq_unlock(0); + + if (!sl_si91x_power_manager_is_ok_to_sleep()) { + /* Device is not ready to sleep; perform necessary actions if required. */ + goto out; + } + + if (state == PM_STATE_RUNTIME_IDLE) { + sl_si91x_power_manager_standby(); + } else { + if (sli_si91x_config_clocks_to_mhz_rc() != 0) { + LOG_ERR("Failed to configure clocks for sleep mode"); + goto out; + } + if (IS_ENABLED(CONFIG_WISECONNECT_NETWORK_STACK)) { + if (!(M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS)) { + if (!sl_si91x_is_device_initialized()) { + LOG_ERR("Device is not initialized"); + goto out; + } + sli_si91x_xtal_turn_off_request_from_m4_to_TA(); + } + } + sl_si91x_power_manager_sleep(); + } + + if (!(M4_ULP_SLP_STATUS_REG & ULP_MODE_SWITCHED_NPSS)) { + if (frontend_switch_control != 0) { + sli_si91x_configure_wireless_frontend_controls(frontend_switch_control); + } + + sl_si91x_host_clear_sleep_indicator(); + sli_si91x_m4_ta_wakeup_configurations(); + } +out: + /* Clear PRIMASK */ + __enable_irq(); +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + ARG_UNUSED(state); + ARG_UNUSED(substate_id); +}