soc: renesas: Add power management support for Renesas RA8

Updated `CMakeLists.txt` and `Kconfig` to integrate power management
for RA8D1, RA8M1, and RA8T1.

Modified `Kconfig.defconfig` to configure ULPT timer as the system timer
when power management is enabled:
- Adjusted `SYS_CLOCK_HW_CYCLES_PER_SEC` and `SYS_CLOCK_TICKS_PER_SEC`
for ULPT timer.
- Disabled `CORTEX_M_SYSTICK` when ULPT timer is used as the system timer.

Implemented power management logic in the new `power.c` file for:
- RA8D1 (`soc/renesas/ra/ra8d1/power.c`)
- RA8M1 (`soc/renesas/ra/ra8m1/power.c`)
- RA8T1 (`soc/renesas/ra/ra8t1/power.c`)

Signed-off-by: Khanh Nguyen <khanh.nguyen.wz@bp.renesas.com>
This commit is contained in:
Khanh Nguyen 2025-02-26 09:27:37 +07:00 committed by Benjamin Cabé
commit fb572d59a2
12 changed files with 358 additions and 16 deletions

View file

@ -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 "")

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/pm/pm.h>
#include <zephyr/init.h>
#include <soc.h>
#include <r_lpm.h>
#include <zephyr/logging/log.h>
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);
}

View file

@ -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 "")

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/pm/pm.h>
#include <zephyr/init.h>
#include <soc.h>
#include <r_lpm.h>
#include <zephyr/logging/log.h>
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);
}

View file

@ -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 "")

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/pm/pm.h>
#include <zephyr/init.h>
#include <soc.h>
#include <r_lpm.h>
#include <zephyr/logging/log.h>
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);
}