Skip to content

Commit 7ae800a

Browse files
KhanhNguyen-RVCkartben
authored andcommitted
drivers: timer: Add ULPT timer for power management on Renesas RA MCUs
drivers: - Added ULPT timer driver in `renesas_ra_ulpt_timer.c`. - Updated `clock_control_renesas_ra_cgc.c` for ULPT clock settings. - Updated `uart_renesas_ra8_sci_b.c` for power management support. - Updated `CMakeLists.txt` and `Kconfig` to integrate ULPT timer. - Added `Kconfig.renesas_ra_ulpt` for ULPT-specific configurations. dts bindings: - Added `renesas,ra-ulpt.yaml` for ULPT node bindings. - Added `renesas,ra-ulpt-timer.yaml` for ULPT timer bindings. modules: - Updated `Kconfig.renesas_fsp` to support ULPT and LPM. Signed-off-by: Khanh Nguyen <[email protected]>
1 parent 8f2879a commit 7ae800a

File tree

9 files changed

+413
-2
lines changed

9 files changed

+413
-2
lines changed

drivers/clock_control/clock_control_renesas_ra_cgc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static volatile uint32_t *mstp_regs[] = {
2323
static volatile uint32_t *mstp_regs[] = {};
2424
#endif
2525

26-
#if !defined(CONFIG_PM)
26+
#if defined(CONFIG_CORTEX_M_SYSTICK)
2727
/* If a CPU clock exists in the system, it will be the source for the CPU */
2828
#if BSP_FEATURE_CGC_HAS_CPUCLK
2929
#define sys_clk DT_NODELABEL(cpuclk)

drivers/serial/uart_renesas_ra8_sci_b.c

Lines changed: 155 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
#include <zephyr/drivers/pinctrl.h>
1111
#include <zephyr/sys/util.h>
1212
#include <zephyr/irq.h>
13+
#include <zephyr/pm/device.h>
14+
#include <zephyr/pm/policy.h>
15+
#include <zephyr/pm/device_runtime.h>
1316
#include <soc.h>
1417
#include "r_sci_b_uart.h"
1518
#include "r_dtc.h"
@@ -73,8 +76,78 @@ struct uart_ra_sci_b_data {
7376
uart_callback_t async_user_cb;
7477
void *async_user_cb_data;
7578
#endif
79+
#ifdef CONFIG_PM
80+
bool rx_ongoing;
81+
bool tx_ongoing;
82+
#endif
7683
};
7784

85+
#if CONFIG_PM
86+
static inline void uart_ra_sci_b_rx_pm_policy_state_lock_get(const struct device *dev)
87+
{
88+
struct uart_ra_sci_b_data *data = dev->data;
89+
90+
if (!data->rx_ongoing) {
91+
data->rx_ongoing = true;
92+
#if CONFIG_PM_NEED_ALL_DEVICES_IDLE
93+
pm_device_busy_set(dev);
94+
#else
95+
pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
96+
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
97+
#endif
98+
}
99+
}
100+
101+
static inline void uart_ra_sci_b_rx_pm_policy_state_lock_put(const struct device *dev)
102+
{
103+
struct uart_ra_sci_b_data *data = dev->data;
104+
105+
if (data->rx_ongoing) {
106+
data->rx_ongoing = false;
107+
#if CONFIG_PM_NEED_ALL_DEVICES_IDLE
108+
if (!data->tx_ongoing) {
109+
pm_device_busy_clear(dev);
110+
}
111+
#else
112+
pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
113+
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
114+
#endif
115+
}
116+
}
117+
118+
static inline void uart_ra_sci_b_tx_pm_policy_state_lock_get(const struct device *dev)
119+
{
120+
struct uart_ra_sci_b_data *data = dev->data;
121+
122+
if (!data->tx_ongoing) {
123+
data->tx_ongoing = true;
124+
#if CONFIG_PM_NEED_ALL_DEVICES_IDLE
125+
pm_device_busy_set(dev);
126+
#else
127+
pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
128+
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
129+
#endif
130+
}
131+
}
132+
133+
static inline void uart_ra_sci_b_tx_pm_policy_state_lock_put(const struct device *dev)
134+
{
135+
struct uart_ra_sci_b_data *data = dev->data;
136+
137+
if (data->tx_ongoing) {
138+
data->tx_ongoing = false;
139+
#if CONFIG_PM_NEED_ALL_DEVICES_IDLE
140+
if (!data->rx_ongoing) {
141+
pm_device_busy_clear(dev);
142+
}
143+
#else
144+
pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
145+
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
146+
#endif
147+
}
148+
}
149+
#endif
150+
78151
static int uart_ra_sci_b_poll_in(const struct device *dev, unsigned char *c)
79152
{
80153
const struct uart_ra_sci_b_config *cfg = dev->config;
@@ -100,10 +173,21 @@ static void uart_ra_sci_b_poll_out(const struct device *dev, unsigned char c)
100173
{
101174
const struct uart_ra_sci_b_config *cfg = dev->config;
102175

176+
#if CONFIG_PM
177+
uart_ra_sci_b_tx_pm_policy_state_lock_get(dev);
178+
#endif
179+
103180
while (cfg->regs->CSR_b.TEND == 0U) {
104181
}
105182

106183
cfg->regs->TDR_BY = c;
184+
185+
while (cfg->regs->CSR_b.TEND == 0U) {
186+
}
187+
188+
#if CONFIG_PM
189+
uart_ra_sci_b_tx_pm_policy_state_lock_put(dev);
190+
#endif
107191
}
108192

109193
static int uart_ra_sci_b_err_check(const struct device *dev)
@@ -311,6 +395,10 @@ static void uart_ra_sci_b_irq_tx_enable(const struct device *dev)
311395
{
312396
const struct uart_ra_sci_b_config *cfg = dev->config;
313397

398+
#if CONFIG_PM
399+
uart_ra_sci_b_tx_pm_policy_state_lock_get(dev);
400+
#endif
401+
314402
cfg->regs->CCR0 |= (BIT(R_SCI_B0_CCR0_TIE_Pos) | BIT(R_SCI_B0_CCR0_TEIE_Pos));
315403
}
316404

@@ -319,6 +407,10 @@ static void uart_ra_sci_b_irq_tx_disable(const struct device *dev)
319407
const struct uart_ra_sci_b_config *cfg = dev->config;
320408

321409
cfg->regs->CCR0 &= ~(BIT(R_SCI_B0_CCR0_TIE_Pos) | BIT(R_SCI_B0_CCR0_TEIE_Pos));
410+
411+
#if CONFIG_PM
412+
uart_ra_sci_b_tx_pm_policy_state_lock_put(dev);
413+
#endif
322414
}
323415

324416
static int uart_ra_sci_b_irq_tx_ready(const struct device *dev)
@@ -342,6 +434,10 @@ static void uart_ra_sci_b_irq_rx_enable(const struct device *dev)
342434
{
343435
const struct uart_ra_sci_b_config *cfg = dev->config;
344436

437+
#if CONFIG_PM
438+
uart_ra_sci_b_rx_pm_policy_state_lock_get(dev);
439+
#endif
440+
345441
cfg->regs->CCR0_b.RIE = 1U;
346442
}
347443

@@ -350,6 +446,10 @@ static void uart_ra_sci_b_irq_rx_disable(const struct device *dev)
350446
const struct uart_ra_sci_b_config *cfg = dev->config;
351447

352448
cfg->regs->CCR0_b.RIE = 0U;
449+
450+
#if CONFIG_PM
451+
uart_ra_sci_b_rx_pm_policy_state_lock_put(dev);
452+
#endif
353453
}
354454

355455
static int uart_ra_sci_b_irq_rx_ready(const struct device *dev)
@@ -637,6 +737,10 @@ static int uart_ra_sci_b_async_tx(const struct device *dev, const uint8_t *buf,
637737
data->tx_buffer = (uint8_t *)buf;
638738
data->tx_buffer_cap = len;
639739

740+
#if CONFIG_PM
741+
uart_ra_sci_b_tx_pm_policy_state_lock_get(dev);
742+
#endif
743+
640744
uart_ra_sci_b_async_timer_start(&data->tx_timeout_work, timeout);
641745

642746
unlock:
@@ -687,6 +791,10 @@ static int uart_ra_sci_b_async_tx_abort(const struct device *dev)
687791

688792
async_tx_abort(dev);
689793

794+
#if CONFIG_PM
795+
uart_ra_sci_b_tx_pm_policy_state_lock_put(dev);
796+
#endif
797+
690798
return 0;
691799
}
692800

@@ -720,6 +828,10 @@ static int uart_ra_sci_b_async_rx_enable(const struct device *dev, uint8_t *buf,
720828
goto unlock;
721829
}
722830

831+
#if CONFIG_PM
832+
uart_ra_sci_b_rx_pm_policy_state_lock_get(dev);
833+
#endif
834+
723835
data->rx_timeout = timeout;
724836
data->rx_buffer = buf;
725837
data->rx_buffer_cap = len;
@@ -772,6 +884,10 @@ static int uart_ra_sci_b_async_rx_disable(const struct device *dev)
772884
cfg->regs->CFCLR_b.RDRFC = 1U;
773885

774886
unlock:
887+
#if CONFIG_PM
888+
uart_ra_sci_b_rx_pm_policy_state_lock_put(dev);
889+
#endif
890+
775891
irq_unlock(key);
776892
return err;
777893
}
@@ -833,6 +949,40 @@ static void uart_ra_sci_b_callback_adapter(struct st_uart_callback_arg *fsp_args
833949

834950
#endif /* CONFIG_UART_ASYNC_API */
835951

952+
#ifdef CONFIG_PM_DEVICE
953+
static int uart_ra_sci_b_pm_action(const struct device *dev, enum pm_device_action action)
954+
{
955+
struct uart_ra_sci_b_data *data = dev->data;
956+
fsp_err_t fsp_err;
957+
958+
switch (action) {
959+
case PM_DEVICE_ACTION_SUSPEND:
960+
/* Deinitialize the device */
961+
fsp_err = R_SCI_B_UART_Close(&data->sci);
962+
__ASSERT(fsp_err == 0, "sci_uart: initialization: close failed");
963+
break;
964+
965+
case PM_DEVICE_ACTION_RESUME:
966+
/* Reinitialize the device */
967+
int ret = uart_ra_sci_b_apply_config(&data->uart_config, &data->fsp_config,
968+
&data->fsp_config_extend,
969+
&data->fsp_baud_setting);
970+
if (ret < 0) {
971+
return ret;
972+
}
973+
974+
fsp_err = R_SCI_B_UART_Open(&data->sci, &data->fsp_config);
975+
__ASSERT(fsp_err == 0, "sci_uart: initialization: open failed");
976+
break;
977+
978+
default:
979+
return -ENOTSUP;
980+
}
981+
982+
return 0;
983+
}
984+
#endif /* CONFIG_PM_DEVICE */
985+
836986
static DEVICE_API(uart, uart_ra_sci_b_driver_api) = {
837987
.poll_in = uart_ra_sci_b_poll_in,
838988
.poll_out = uart_ra_sci_b_poll_out,
@@ -971,6 +1121,9 @@ static void uart_ra_sci_b_tei_isr(const struct device *dev)
9711121
#if defined(CONFIG_UART_ASYNC_API)
9721122
k_work_cancel_delayable(&data->tx_timeout_work);
9731123
sci_b_uart_tei_isr();
1124+
#if CONFIG_PM
1125+
uart_ra_sci_b_tx_pm_policy_state_lock_put(dev);
1126+
#endif
9741127
#else
9751128
R_ICU->IELSR_b[data->fsp_config.tei_irq].IR = 0U;
9761129
#endif
@@ -1152,7 +1305,8 @@ static void uart_ra_sci_b_eri_isr(const struct device *dev)
11521305
return 0; \
11531306
} \
11541307
\
1155-
DEVICE_DT_INST_DEFINE(index, uart_ra_sci_b_init_##index, NULL, \
1308+
PM_DEVICE_DT_INST_DEFINE(index, uart_ra_sci_b_pm_action); \
1309+
DEVICE_DT_INST_DEFINE(index, uart_ra_sci_b_init_##index, PM_DEVICE_DT_INST_GET(index), \
11561310
&uart_ra_sci_b_data_##index, &uart_ra_sci_b_config_##index, \
11571311
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
11581312
&uart_ra_sci_b_driver_api);

drivers/timer/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_NPCX_ITIM_TIMER npcx_itim_timer.c)
3232
zephyr_library_sources_ifdef(CONFIG_NRF_GRTC_TIMER nrf_grtc_timer.c)
3333
zephyr_library_sources_ifdef(CONFIG_NRF_RTC_TIMER nrf_rtc_timer.c)
3434
zephyr_library_sources_ifdef(CONFIG_RCAR_CMT_TIMER rcar_cmt_timer.c)
35+
zephyr_library_sources_ifdef(CONFIG_RENESAS_RA_ULPT_TIMER renesas_ra_ulpt_timer.c)
3536
zephyr_library_sources_ifdef(CONFIG_RISCV_MACHINE_TIMER riscv_machine_timer.c)
3637
zephyr_library_sources_ifdef(CONFIG_RV32M1_LPTMR_TIMER rv32m1_lptmr_timer.c)
3738
zephyr_library_sources_ifdef(CONFIG_REALTEK_RTS5912_RTMR realtek_rts5912_rtmr.c)

drivers/timer/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ source "drivers/timer/Kconfig.xlnx_psttc"
102102
source "drivers/timer/Kconfig.xtensa"
103103
source "drivers/timer/Kconfig.mtk_adsp"
104104
source "drivers/timer/Kconfig.sy1xx_sys_timer"
105+
source "drivers/timer/Kconfig.renesas_ra_ulpt"
105106

106107
endmenu
107108

drivers/timer/Kconfig.renesas_ra_ulpt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2025 Renesas Electronics Corporation
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config RENESAS_RA_ULPT_TIMER
5+
bool "Renesas RA Series ULPT Timer"
6+
default y if PM
7+
depends on DT_HAS_RENESAS_RA_ULPT_TIMER_ENABLED
8+
select TICKLESS_CAPABLE
9+
help
10+
This module implements a kernel device driver for the Renesas RA series
11+
ULPT timer and provides the standard "system clock driver" interfaces.

0 commit comments

Comments
 (0)