diff --git a/soc/renesas/ra/ra8d1/CMakeLists.txt b/soc/renesas/ra/ra8d1/CMakeLists.txt index 1c7457569ef..d648d3689af 100644 --- a/soc/renesas/ra/ra8d1/CMakeLists.txt +++ b/soc/renesas/ra/ra8d1/CMakeLists.txt @@ -7,6 +7,10 @@ zephyr_sources( soc.c ) +zephyr_sources_ifdef(CONFIG_PM + power.c +) + zephyr_linker_sources(SECTIONS sections.ld) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/renesas/ra/ra8d1/Kconfig b/soc/renesas/ra/ra8d1/Kconfig index 50907d2be70..b229ca38168 100644 --- a/soc/renesas/ra/ra8d1/Kconfig +++ b/soc/renesas/ra/ra8d1/Kconfig @@ -15,3 +15,4 @@ config SOC_SERIES_RA8D1 select HAS_RENESAS_RA_FSP select SOC_EARLY_INIT_HOOK select GPIO_RA_HAS_VBTICTLR + select HAS_PM diff --git a/soc/renesas/ra/ra8d1/Kconfig.defconfig b/soc/renesas/ra/ra8d1/Kconfig.defconfig index afcb85a5dce..b74c5986b14 100644 --- a/soc/renesas/ra/ra8d1/Kconfig.defconfig +++ b/soc/renesas/ra/ra8d1/Kconfig.defconfig @@ -6,11 +6,6 @@ if SOC_SERIES_RA8D1 config NUM_IRQS default 96 -DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) - config BUILD_OUTPUT_HEX default y @@ -27,4 +22,20 @@ config DCACHE config CACHE_MANAGEMENT default n +config CORTEX_M_SYSTICK + default n if RENESAS_RA_ULPT_TIMER + +DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) +DT_LOCO_PATH := $(dt_nodelabel_path,loco) + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) if CORTEX_M_SYSTICK + default $(dt_node_int_prop_int,$(DT_LOCO_PATH),clock-frequency) if RENESAS_RA_ULPT_TIMER + +config SYS_CLOCK_TICKS_PER_SEC + default 4096 if RENESAS_RA_ULPT_TIMER + +config PM_DEVICE + default y if PM + endif # SOC_SERIES_RA8D1 diff --git a/soc/renesas/ra/ra8d1/power.c b/soc/renesas/ra/ra8d1/power.c new file mode 100644 index 00000000000..fe8b7c291f4 --- /dev/null +++ b/soc/renesas/ra/ra8d1/power.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +/* Low Power Mode instance control structure */ +static lpm_instance_ctrl_t pm_state_ctrl; + +/* Configuration for Runtime Idle Power State */ +const lpm_cfg_t pm_state_runtime_idle_cfg = { + .low_power_mode = LPM_MODE_SLEEP, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +/* Configuration for Standby Power State */ +const lpm_cfg_t pm_state_standby_cfg = { + .low_power_mode = LPM_MODE_STANDBY, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + R_LPM_LowPowerReconfigure(&pm_state_ctrl, &pm_state_runtime_idle_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + case PM_STATE_STANDBY: + R_LPM_Open(&pm_state_ctrl, &pm_state_standby_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + default: + break; + } +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + __fallthrough; + case PM_STATE_STANDBY: + R_LPM_Close(&pm_state_ctrl); + break; + + default: + break; + } + irq_unlock(0); +} diff --git a/soc/renesas/ra/ra8m1/CMakeLists.txt b/soc/renesas/ra/ra8m1/CMakeLists.txt index 1c7457569ef..d648d3689af 100644 --- a/soc/renesas/ra/ra8m1/CMakeLists.txt +++ b/soc/renesas/ra/ra8m1/CMakeLists.txt @@ -7,6 +7,10 @@ zephyr_sources( soc.c ) +zephyr_sources_ifdef(CONFIG_PM + power.c +) + zephyr_linker_sources(SECTIONS sections.ld) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/renesas/ra/ra8m1/Kconfig b/soc/renesas/ra/ra8m1/Kconfig index 31d4aaefda5..e7ee4978139 100644 --- a/soc/renesas/ra/ra8m1/Kconfig +++ b/soc/renesas/ra/ra8m1/Kconfig @@ -15,5 +15,6 @@ config SOC_SERIES_RA8M1 select HAS_RENESAS_RA_FSP select SOC_EARLY_INIT_HOOK select GPIO_RA_HAS_VBTICTLR + select HAS_PM help Enable support for Renesas RA8M1 MCU series diff --git a/soc/renesas/ra/ra8m1/Kconfig.defconfig b/soc/renesas/ra/ra8m1/Kconfig.defconfig index 18f1da7e08d..faaec2c2068 100644 --- a/soc/renesas/ra/ra8m1/Kconfig.defconfig +++ b/soc/renesas/ra/ra8m1/Kconfig.defconfig @@ -1,4 +1,4 @@ -# Copyright (c) 2024 Renesas Electronics Corporation +# Copyright (c) 2024-2025 Renesas Electronics Corporation # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_RA8M1 @@ -6,11 +6,6 @@ if SOC_SERIES_RA8M1 config NUM_IRQS default 96 -DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) - config BUILD_OUTPUT_HEX default y @@ -21,4 +16,20 @@ config CLOCK_CONTROL config FLASH_FILL_BUFFER_SIZE default 128 +config CORTEX_M_SYSTICK + default n if RENESAS_RA_ULPT_TIMER + +DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) +DT_LOCO_PATH := $(dt_nodelabel_path,loco) + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) if CORTEX_M_SYSTICK + default $(dt_node_int_prop_int,$(DT_LOCO_PATH),clock-frequency) if RENESAS_RA_ULPT_TIMER + +config SYS_CLOCK_TICKS_PER_SEC + default 4096 if RENESAS_RA_ULPT_TIMER + +config PM_DEVICE + default y if PM + endif # SOC_SERIES_RA8M1 diff --git a/soc/renesas/ra/ra8m1/power.c b/soc/renesas/ra/ra8m1/power.c new file mode 100644 index 00000000000..fe8b7c291f4 --- /dev/null +++ b/soc/renesas/ra/ra8m1/power.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +/* Low Power Mode instance control structure */ +static lpm_instance_ctrl_t pm_state_ctrl; + +/* Configuration for Runtime Idle Power State */ +const lpm_cfg_t pm_state_runtime_idle_cfg = { + .low_power_mode = LPM_MODE_SLEEP, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +/* Configuration for Standby Power State */ +const lpm_cfg_t pm_state_standby_cfg = { + .low_power_mode = LPM_MODE_STANDBY, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + R_LPM_LowPowerReconfigure(&pm_state_ctrl, &pm_state_runtime_idle_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + case PM_STATE_STANDBY: + R_LPM_Open(&pm_state_ctrl, &pm_state_standby_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + default: + break; + } +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + __fallthrough; + case PM_STATE_STANDBY: + R_LPM_Close(&pm_state_ctrl); + break; + + default: + break; + } + irq_unlock(0); +} diff --git a/soc/renesas/ra/ra8t1/CMakeLists.txt b/soc/renesas/ra/ra8t1/CMakeLists.txt index 1c7457569ef..d648d3689af 100644 --- a/soc/renesas/ra/ra8t1/CMakeLists.txt +++ b/soc/renesas/ra/ra8t1/CMakeLists.txt @@ -7,6 +7,10 @@ zephyr_sources( soc.c ) +zephyr_sources_ifdef(CONFIG_PM + power.c +) + zephyr_linker_sources(SECTIONS sections.ld) set(SOC_LINKER_SCRIPT ${ZEPHYR_BASE}/include/zephyr/arch/arm/cortex_m/scripts/linker.ld CACHE INTERNAL "") diff --git a/soc/renesas/ra/ra8t1/Kconfig b/soc/renesas/ra/ra8t1/Kconfig index 5fe21152ad4..17afc4ced60 100644 --- a/soc/renesas/ra/ra8t1/Kconfig +++ b/soc/renesas/ra/ra8t1/Kconfig @@ -15,3 +15,4 @@ config SOC_SERIES_RA8T1 select HAS_RENESAS_RA_FSP select SOC_EARLY_INIT_HOOK select GPIO_RA_HAS_VBTICTLR + select HAS_PM diff --git a/soc/renesas/ra/ra8t1/Kconfig.defconfig b/soc/renesas/ra/ra8t1/Kconfig.defconfig index 44acb5cf413..60aaa70c148 100644 --- a/soc/renesas/ra/ra8t1/Kconfig.defconfig +++ b/soc/renesas/ra/ra8t1/Kconfig.defconfig @@ -6,11 +6,6 @@ if SOC_SERIES_RA8T1 config NUM_IRQS default 96 -DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) - -config SYS_CLOCK_HW_CYCLES_PER_SEC - default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) - config BUILD_OUTPUT_HEX default y @@ -21,4 +16,20 @@ config CLOCK_CONTROL config FLASH_FILL_BUFFER_SIZE default 128 +config CORTEX_M_SYSTICK + default n if RENESAS_RA_ULPT_TIMER + +DT_ICLK_PATH := $(dt_nodelabel_path,cpuclk) +DT_LOCO_PATH := $(dt_nodelabel_path,loco) + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default $(dt_node_int_prop_int,$(DT_ICLK_PATH),clock-frequency) if CORTEX_M_SYSTICK + default $(dt_node_int_prop_int,$(DT_LOCO_PATH),clock-frequency) if RENESAS_RA_ULPT_TIMER + +config SYS_CLOCK_TICKS_PER_SEC + default 4096 if RENESAS_RA_ULPT_TIMER + +config PM_DEVICE + default y if PM + endif # SOC_SERIES_RA8T1 diff --git a/soc/renesas/ra/ra8t1/power.c b/soc/renesas/ra/ra8t1/power.c new file mode 100644 index 00000000000..fe8b7c291f4 --- /dev/null +++ b/soc/renesas/ra/ra8t1/power.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(soc, CONFIG_SOC_LOG_LEVEL); + +/* Low Power Mode instance control structure */ +static lpm_instance_ctrl_t pm_state_ctrl; + +/* Configuration for Runtime Idle Power State */ +const lpm_cfg_t pm_state_runtime_idle_cfg = { + .low_power_mode = LPM_MODE_SLEEP, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +/* Configuration for Standby Power State */ +const lpm_cfg_t pm_state_standby_cfg = { + .low_power_mode = LPM_MODE_STANDBY, + .standby_wake_sources = LPM_STANDBY_WAKE_SOURCE_ULP0U, + .output_port_enable = LPM_OUTPUT_PORT_ENABLE_RETAIN, + .io_port_state = LPM_IO_PORT_NO_CHANGE, + .power_supply_state = LPM_POWER_SUPPLY_DEEP_STANDBY_MODE1, + .deep_standby_cancel_source = (lpm_deep_standby_cancel_source_t)0, + .deep_standby_cancel_edge = (lpm_deep_standby_cancel_edge_t)0, + .ram_retention_cfg.ram_retention = (uint16_t)(0x7F), + .ram_retention_cfg.tcm_retention = true, + .ram_retention_cfg.standby_ram_retention = true, + .ldo_standby_cfg.pll1_ldo = false, + .ldo_standby_cfg.pll2_ldo = false, + .ldo_standby_cfg.hoco_ldo = false, + .p_extend = NULL, +}; + +void pm_state_set(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + R_LPM_LowPowerReconfigure(&pm_state_ctrl, &pm_state_runtime_idle_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + case PM_STATE_STANDBY: + R_LPM_Open(&pm_state_ctrl, &pm_state_standby_cfg); + __disable_irq(); + __set_BASEPRI(0); + __ISB(); + + R_LPM_LowPowerModeEnter(&pm_state_ctrl); + __enable_irq(); + __ISB(); + break; + + default: + break; + } +} + +void pm_state_exit_post_ops(enum pm_state state, uint8_t substate_id) +{ + switch (state) { + case PM_STATE_RUNTIME_IDLE: + __fallthrough; + case PM_STATE_STANDBY: + R_LPM_Close(&pm_state_ctrl); + break; + + default: + break; + } + irq_unlock(0); +}