blob: 8993949630b3e7cb3863ff825cacb8b1782cf221 [file] [log] [blame]
/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT renesas_ra_rtc
#include <zephyr/devicetree.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/rtc.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/irq.h>
#include <zephyr/sys/util.h>
#include <zephyr/logging/log.h>
#include <cold_start.h>
#include <r_rtc.h>
#include <soc.h>
#include "rtc_utils.h"
#include <stdlib.h>
LOG_MODULE_REGISTER(renesas_ra_rtc, CONFIG_RTC_LOG_LEVEL);
/* Zephyr mask supported by RTC Renesas RA device, values from RTC_ALARM_TIME_MASK */
#define RTC_RENESAS_RA_SUPPORTED_ALARM_FIELDS \
(RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \
RTC_ALARM_TIME_MASK_WEEKDAY | RTC_ALARM_TIME_MASK_MONTHDAY | RTC_ALARM_TIME_MASK_MONTH | \
RTC_ALARM_TIME_MASK_YEAR)
#define RTC_RENESAS_RA_MAX_ERROR_ADJUSTMENT_VALUE (63)
/* RTC Renesas RA start year: 2000 */
#define RTC_RENESAS_RA_YEAR_REF 2000
/* struct tm start year: 1900 */
#define TM_YEAR_REF 1900
struct rtc_renesas_ra_config {
void (*irq_config_func)(const struct device *dev);
const struct device *clock_dev;
#ifdef CONFIG_RTC_ALARM
uint16_t alarms_count;
#endif
};
struct rtc_renesas_ra_data {
rtc_instance_ctrl_t fsp_ctrl;
rtc_cfg_t fsp_cfg;
rtc_error_adjustment_cfg_t fsp_err_cfg;
#ifdef CONFIG_RTC_ALARM
rtc_alarm_callback alarm_cb;
void *alarm_cb_data;
bool is_alarm_pending;
#endif /* CONFIG_RTC_ALARM */
#ifdef CONFIG_RTC_UPDATE
rtc_update_callback update_cb;
void *update_cb_data;
#endif /* CONFIG_RTC_UPDATE */
};
/* FSP ISR */
extern void rtc_alarm_periodic_isr(void);
extern void rtc_carry_isr(void);
#if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)
static void renesas_ra_rtc_callback(rtc_callback_args_t *p_args)
{
const struct device *dev = p_args->p_context;
__maybe_unused struct rtc_renesas_ra_data *data = dev->data;
#ifdef CONFIG_RTC_ALARM
rtc_alarm_callback alarm_cb = data->alarm_cb;
void *alarm_cb_data = data->alarm_cb_data;
#endif /* CONFIG_RTC_ALARM */
#ifdef CONFIG_RTC_UPDATE
rtc_update_callback update_cb = data->update_cb;
void *update_cb_data = data->update_cb_data;
#endif /* CONFIG_RTC_UPDATE */
if (RTC_EVENT_ALARM_IRQ == p_args->event) {
#ifdef CONFIG_RTC_ALARM
if (alarm_cb) {
alarm_cb(dev, 0, alarm_cb_data);
data->is_alarm_pending = false;
} else {
data->is_alarm_pending = true;
}
#endif /* CONFIG_RTC_ALARM */
}
#ifdef CONFIG_RTC_UPDATE
else if (RTC_EVENT_PERIODIC_IRQ == p_args->event) {
if (update_cb) {
update_cb(dev, update_cb_data);
}
}
#endif /* CONFIG_RTC_UPDATE */
else {
LOG_ERR("Invalid callback event");
}
}
#endif /* CONFIG_RTC_ALARM || CONFIG_RTC_UPDATE */
static int rtc_renesas_ra_init(const struct device *dev)
{
struct rtc_renesas_ra_data *data = dev->data;
const struct rtc_renesas_ra_config *config = dev->config;
const char *clock_dev_name = config->clock_dev->name;
fsp_err_t fsp_err;
uint32_t rate;
int ret;
if (!device_is_ready(config->clock_dev)) {
return -ENODEV;
}
if (strcmp(clock_dev_name, "clock-loco") == 0) {
data->fsp_cfg.clock_source = RTC_CLOCK_SOURCE_LOCO;
ret = clock_control_get_rate(config->clock_dev, (clock_control_subsys_t)0, &rate);
if (ret) {
return ret;
}
/* The RTC time counter operates on a 128-Hz clock signal as the base clock.
* Therefore, when LOCO is selected, LOCO is divided by the prescaler to
* generate a 128-Hz clock signal. Calculation method of frequency
* comparison value: (LOCO clock frequency) / 128 - 1
*/
data->fsp_cfg.freq_compare_value = (rate / 128) - 1;
} else {
data->fsp_cfg.clock_source = RTC_CLOCK_SOURCE_SUBCLK;
}
#if defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)
data->fsp_cfg.p_callback = renesas_ra_rtc_callback;
#if defined(CONFIG_RTC_ALARM)
data->alarm_cb = NULL;
data->alarm_cb_data = NULL;
data->is_alarm_pending = false;
#endif /* CONFIG_RTC_ALARM */
#if defined(CONFIG_RTC_UPDATE)
data->update_cb = NULL;
data->update_cb_data = NULL;
#endif /* CONFIG_RTC_UPDATE */
#else
data->fsp_cfg.p_callback = NULL;
#endif
fsp_err = R_RTC_Open(&data->fsp_ctrl, &data->fsp_cfg);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Failed to initialize the device");
return -EIO;
}
#if defined(CONFIG_RENESAS_RA_BATTERY_BACKUP_MANUAL_CONFIGURE)
if (is_backup_domain_reset_happen()) {
R_RTC_ClockSourceSet(&data->fsp_ctrl);
}
#else
if (is_power_on_reset_happen()) {
R_RTC_ClockSourceSet(&data->fsp_ctrl);
}
#endif /* CONFIG_RENESAS_RA_BATTERY_BACKUP_MANUAL_CONFIGURE */
#ifdef CONFIG_RTC_UPDATE
fsp_err = R_RTC_PeriodicIrqRateSet(&data->fsp_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Failed to configure update interrupt");
return -EIO;
}
#endif /* CONFIG_RTC_UPDATE */
config->irq_config_func(dev);
return 0;
}
static int rtc_renesas_ra_set_time(const struct device *dev, const struct rtc_time *timeptr)
{
struct rtc_renesas_ra_data *data = dev->data;
fsp_err_t fsp_err;
if (timeptr == NULL) {
LOG_ERR("No pointer is provided to set time");
return -EINVAL;
}
if (timeptr->tm_year + TM_YEAR_REF < RTC_RENESAS_RA_YEAR_REF) {
LOG_ERR("RTC time exceeds HW capabilities. Year must be 2000-2099");
return -EINVAL;
}
if (!rtc_utils_validate_rtc_time(timeptr, RTC_RENESAS_RA_SUPPORTED_ALARM_FIELDS)) {
LOG_ERR("RTC time is invalid");
return -EINVAL;
}
fsp_err = R_RTC_CalendarTimeSet(&data->fsp_ctrl, (struct tm *const)timeptr);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Time set operation was not successful.");
return -EIO;
}
return 0;
}
static int rtc_renesas_ra_get_time(const struct device *dev, struct rtc_time *timeptr)
{
struct rtc_renesas_ra_data *data = dev->data;
fsp_err_t fsp_err;
rtc_info_t rtc_info;
if (timeptr == NULL) {
LOG_ERR("Pointer provided to store the requested time is NULL");
return -EINVAL;
}
fsp_err = R_RTC_InfoGet(&data->fsp_ctrl, &rtc_info);
if (fsp_err != FSP_SUCCESS) {
return -EIO;
}
if (rtc_info.status != RTC_STATUS_RUNNING) {
LOG_ERR("RTC time has not been set");
return -ENODATA;
}
fsp_err = R_RTC_CalendarTimeGet(&data->fsp_ctrl, rtc_time_to_tm(timeptr));
if (fsp_err != FSP_SUCCESS) {
return -EIO;
}
/* value for unsupported fields */
timeptr->tm_yday = -1;
timeptr->tm_isdst = -1;
timeptr->tm_nsec = 0;
return 0;
}
#ifdef CONFIG_RTC_ALARM
static int rtc_renesas_ra_alarm_get_supported_fields(const struct device *dev, uint16_t id,
uint16_t *mask)
{
const struct rtc_renesas_ra_config *config = dev->config;
if (mask == NULL) {
LOG_ERR("Mask pointer is NULL");
return -EINVAL;
}
if (id > config->alarms_count) {
LOG_ERR("Invalid alarm ID %d", id);
return -EINVAL;
}
*mask = (uint16_t)RTC_RENESAS_RA_SUPPORTED_ALARM_FIELDS;
return 0;
}
#define ALARM_FIELD_CHECK_ENABLE(mask, field) (mask & field)
static int rtc_renesas_ra_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask,
const struct rtc_time *timeptr)
{
struct rtc_renesas_ra_data *data = dev->data;
const struct rtc_renesas_ra_config *config = dev->config;
fsp_err_t fsp_err;
rtc_alarm_time_t fsp_alarm_cfg;
if ((timeptr == NULL) && (mask != 0)) {
LOG_ERR("No pointer is provided to set alarm");
return -EINVAL;
}
if (id > config->alarms_count) {
LOG_ERR("Invalid alarm ID %d", id);
return -EINVAL;
}
if (mask & ~RTC_RENESAS_RA_SUPPORTED_ALARM_FIELDS) {
LOG_ERR("Invalid alarm mask");
return -EINVAL;
}
if (mask > 0) {
if (!rtc_utils_validate_rtc_time(timeptr, mask)) {
LOG_ERR("Invalid alarm fields values");
return -EINVAL;
}
fsp_alarm_cfg.time.tm_sec = timeptr->tm_sec;
fsp_alarm_cfg.time.tm_min = timeptr->tm_min;
fsp_alarm_cfg.time.tm_hour = timeptr->tm_hour;
fsp_alarm_cfg.time.tm_mday = timeptr->tm_mday;
fsp_alarm_cfg.time.tm_mon = timeptr->tm_mon;
fsp_alarm_cfg.time.tm_year = timeptr->tm_year;
fsp_alarm_cfg.time.tm_wday = timeptr->tm_wday;
}
fsp_alarm_cfg.channel = id;
fsp_alarm_cfg.sec_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_SECOND);
fsp_alarm_cfg.min_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_MINUTE);
fsp_alarm_cfg.hour_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_HOUR);
fsp_alarm_cfg.mday_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_MONTHDAY);
fsp_alarm_cfg.mon_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_MONTH);
fsp_alarm_cfg.year_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_YEAR);
fsp_alarm_cfg.dayofweek_match = ALARM_FIELD_CHECK_ENABLE(mask, RTC_ALARM_TIME_MASK_WEEKDAY);
fsp_err = R_RTC_CalendarAlarmSet(&data->fsp_ctrl, &fsp_alarm_cfg);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Alarm time set is not successful!");
return -EIO;
}
return 0;
}
static int rtc_renesas_ra_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask,
struct rtc_time *timeptr)
{
struct rtc_renesas_ra_data *data = dev->data;
const struct rtc_renesas_ra_config *config = dev->config;
fsp_err_t fsp_err;
rtc_alarm_time_t fsp_alarm_cfg;
if ((mask == NULL) || (timeptr == NULL)) {
LOG_ERR("No pointer is provided to store the requested alarm time/mask");
return -EINVAL;
}
if (id > config->alarms_count) {
LOG_ERR("Invalid alarm ID %d", id);
return -EINVAL;
}
fsp_err = R_RTC_CalendarAlarmGet(&data->fsp_ctrl, &fsp_alarm_cfg);
if (fsp_err != FSP_SUCCESS) {
LOG_ERR("Alarm time get is not successful!");
return -EIO;
}
timeptr->tm_sec = fsp_alarm_cfg.time.tm_sec;
timeptr->tm_min = fsp_alarm_cfg.time.tm_min;
timeptr->tm_hour = fsp_alarm_cfg.time.tm_hour;
timeptr->tm_mday = fsp_alarm_cfg.time.tm_mday;
timeptr->tm_mon = fsp_alarm_cfg.time.tm_mon;
timeptr->tm_year = fsp_alarm_cfg.time.tm_year;
timeptr->tm_wday = fsp_alarm_cfg.time.tm_wday;
/* value for unsupported fields */
timeptr->tm_yday = -1;
timeptr->tm_isdst = -1;
timeptr->tm_nsec = 0;
*mask = 0;
if (fsp_alarm_cfg.sec_match) {
*mask |= RTC_ALARM_TIME_MASK_SECOND;
}
if (fsp_alarm_cfg.min_match) {
*mask |= RTC_ALARM_TIME_MASK_MINUTE;
}
if (fsp_alarm_cfg.hour_match) {
*mask |= RTC_ALARM_TIME_MASK_HOUR;
}
if (fsp_alarm_cfg.mday_match) {
*mask |= RTC_ALARM_TIME_MASK_MONTHDAY;
}
if (fsp_alarm_cfg.mon_match) {
*mask |= RTC_ALARM_TIME_MASK_MONTH;
}
if (fsp_alarm_cfg.year_match) {
*mask |= RTC_ALARM_TIME_MASK_YEAR;
}
if (fsp_alarm_cfg.dayofweek_match) {
*mask |= RTC_ALARM_TIME_MASK_WEEKDAY;
}
return 0;
}
static int rtc_renesas_ra_alarm_set_callback(const struct device *dev, uint16_t id,
rtc_alarm_callback callback, void *user_data)
{
struct rtc_renesas_ra_data *data = dev->data;
const struct rtc_renesas_ra_config *config = dev->config;
unsigned int key;
if (id > config->alarms_count) {
LOG_ERR("invalid alarm ID %d", id);
return -EINVAL;
}
key = irq_lock();
data->alarm_cb = callback;
data->alarm_cb_data = user_data;
irq_unlock(key);
return 0;
}
static int rtc_renesas_ra_alarm_is_pending(const struct device *dev, uint16_t id)
{
struct rtc_renesas_ra_data *data = dev->data;
const struct rtc_renesas_ra_config *config = dev->config;
unsigned int key;
int ret;
if (!(id < config->alarms_count)) {
LOG_ERR("invalid alarm ID %d", id);
return -EINVAL;
}
key = irq_lock();
ret = data->is_alarm_pending ? 1 : 0;
data->is_alarm_pending = false;
irq_unlock(key);
return ret;
}
#endif /* CONFIG_RTC_ALARM */
#ifdef CONFIG_RTC_UPDATE
static int rtc_renesas_ra_update_set_callback(const struct device *dev,
rtc_update_callback callback, void *user_data)
{
struct rtc_renesas_ra_data *data = dev->data;
unsigned int key;
key = irq_lock();
data->update_cb = callback;
data->update_cb_data = user_data;
irq_unlock(key);
return 0;
}
#endif /* CONFIG_RTC_UPDATE */
#ifdef CONFIG_RTC_CALIBRATION
/* Convert number of clock cycles added or removed in 10 seconds or 1 minute
* For each 10 second (total 327,680 clock cycles):
* ppb = cycles * 10^9 / total_cycles = cycles * 10^9 / 327,680
* = cycles * 390625 / 128
*/
#define CYCLES_TO_PPB_EACH_10_SECOND(cycles) DIV_ROUND_CLOSEST((cycles) * 390625, 128)
/* For each 1 minute (total 1,966,080 clock cycles):
* ppb = cycles * 10^9 / total_cycles = cycles * 10^9 / 1,966,080
* = cycles * 390625 / 768
*/
#define CYCLES_TO_PPB_EACH_1_MINUTE(cycles) DIV_ROUND_CLOSEST((cycles) * 390625, 768)
/* Convert part per billion calibration value to a number of clock cycles added or removed
* to part per billion calibration value.
* For each 10 second (total 327,680 clock cycles):
* cycles = ppb * total_cycles / 10^9 = ppb * 327,680 / 10^9
* = ppb * 128 / 390625
*/
#define PPB_TO_CYCLES_PER_10_SECOND(ppb) DIV_ROUND_CLOSEST((ppb) * 128, 390625)
/*
* For each 1 minute (total 1,966,080 clock cycles):
* cycles = ppb * total_cycles / 10^9 = ppb * 1,966,080 / 10^9
* = ppb * 768 / 390625
*/
#define PPB_TO_CYCLES_PER_1_MINUTE(ppb) DIV_ROUND_CLOSEST((ppb) * 768, 390625)
static int rtc_renesas_ra_set_calibration(const struct device *dev, int32_t calibration)
{
struct rtc_renesas_ra_data *data = dev->data;
fsp_err_t fsp_err;
uint32_t adjustment_cycles = 0;
uint32_t adjustment_cycles_ten_seconds = 0;
uint32_t adjustment_cycles_one_minute = 0;
int32_t abs_calibration = abs(calibration);
/* Calibration is not available while using the LOCO clock */
if (data->fsp_cfg.clock_source == RTC_CLOCK_SOURCE_LOCO) {
LOG_DBG("Calibration is not available while using the LOCO clock");
return -ENOTSUP;
}
if (calibration == 0) {
data->fsp_err_cfg.adjustment_type = RTC_ERROR_ADJUSTMENT_NONE;
data->fsp_err_cfg.adjustment_value = 0;
} else {
adjustment_cycles_ten_seconds = PPB_TO_CYCLES_PER_10_SECOND(abs_calibration);
adjustment_cycles_one_minute = PPB_TO_CYCLES_PER_1_MINUTE(abs_calibration);
if ((adjustment_cycles_ten_seconds > RTC_RENESAS_RA_MAX_ERROR_ADJUSTMENT_VALUE) &&
(adjustment_cycles_one_minute > RTC_RENESAS_RA_MAX_ERROR_ADJUSTMENT_VALUE)) {
LOG_ERR("Calibration out of HW range");
return -EINVAL;
}
/* 1 minute period has low range part per bilion than 10 minute period when transfer
* from ppb to cycles. So check it first.
*/
if (adjustment_cycles_one_minute > RTC_RENESAS_RA_MAX_ERROR_ADJUSTMENT_VALUE) {
adjustment_cycles = adjustment_cycles_ten_seconds;
data->fsp_err_cfg.adjustment_period = RTC_ERROR_ADJUSTMENT_PERIOD_10_SECOND;
} else {
int32_t err_ten_seconds =
abs(CYCLES_TO_PPB_EACH_10_SECOND(adjustment_cycles_ten_seconds) -
abs_calibration);
int32_t err_one_minute =
abs(CYCLES_TO_PPB_EACH_1_MINUTE(adjustment_cycles_one_minute) -
abs_calibration);
LOG_DBG("10 seconds error: %d; 1 minute error: %d", err_ten_seconds,
err_one_minute);
if (err_one_minute < err_ten_seconds) {
data->fsp_err_cfg.adjustment_period =
RTC_ERROR_ADJUSTMENT_PERIOD_1_MINUTE;
adjustment_cycles = adjustment_cycles_one_minute;
} else {
data->fsp_err_cfg.adjustment_period =
RTC_ERROR_ADJUSTMENT_PERIOD_10_SECOND;
adjustment_cycles = adjustment_cycles_ten_seconds;
}
}
data->fsp_err_cfg.adjustment_type =
(calibration > 0) ? RTC_ERROR_ADJUSTMENT_ADD_PRESCALER
: RTC_ERROR_ADJUSTMENT_SUBTRACT_PRESCALER;
data->fsp_err_cfg.adjustment_value = adjustment_cycles;
}
data->fsp_err_cfg.adjustment_mode = RTC_ERROR_ADJUSTMENT_MODE_AUTOMATIC;
fsp_err = R_RTC_ErrorAdjustmentSet(&data->fsp_ctrl, &data->fsp_err_cfg);
if (fsp_err != FSP_SUCCESS) {
return -EIO;
}
return 0;
}
#endif /* CONFIG_RTC_CALIBRATION */
static DEVICE_API(rtc, rtc_renesas_ra_driver_api) = {
.set_time = rtc_renesas_ra_set_time,
.get_time = rtc_renesas_ra_get_time,
#ifdef CONFIG_RTC_ALARM
.alarm_get_supported_fields = rtc_renesas_ra_alarm_get_supported_fields,
.alarm_set_time = rtc_renesas_ra_alarm_set_time,
.alarm_get_time = rtc_renesas_ra_alarm_get_time,
.alarm_set_callback = rtc_renesas_ra_alarm_set_callback,
.alarm_is_pending = rtc_renesas_ra_alarm_is_pending,
#endif /* CONFIG_RTC_ALARM */
#ifdef CONFIG_RTC_UPDATE
.update_set_callback = rtc_renesas_ra_update_set_callback,
#endif /* CONFIG_RTC_UPDATE */
#ifdef CONFIG_RTC_CALIBRATION
.set_calibration = rtc_renesas_ra_set_calibration,
#endif /* CONFIG_RTC_CALIBRATION */
};
#define RTC_RENESAS_RA_ALARM_COUNT_GET(index) \
IF_ENABLED(CONFIG_RTC_ALARM, \
(.alarms_count = DT_INST_PROP(index, alarms_count),))
#define RTC_RENESAS_RA_CALIBRATION_MODE \
COND_CODE_1(CONFIG_RTC_CALIBRATION, (RTC_ERROR_ADJUSTMENT_MODE_AUTOMATIC), \
(RTC_ERROR_ADJUSTMENT_MODE_MANUAL))
#define RTC_RENESAS_RA_CALIBRATION_PERIOD \
COND_CODE_1(CONFIG_RTC_CALIBRATION, (RTC_ERROR_ADJUSTMENT_PERIOD_1_MINUTE), \
(RTC_ERROR_ADJUSTMENT_PERIOD_NONE))
#define RTC_RENESAS_RA_IRQ_GET(id, name, cell) \
COND_CODE_1(DT_INST_IRQ_HAS_NAME(id, name), \
(DT_INST_IRQ_BY_NAME(id, name, cell)), \
((IRQn_Type) BSP_IRQ_DISABLED))
#define ALARM_IRQ_ENABLE(index) \
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(index, alm, irq)] = ELC_EVENT_RTC_ALARM; \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, alm, irq), \
DT_INST_IRQ_BY_NAME(index, alm, priority), rtc_alarm_periodic_isr, (NULL), 0);
#define PERODIC_IRQ_ENABLE(index) \
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(index, prd, irq)] = ELC_EVENT_RTC_PERIOD; \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, prd, irq), \
DT_INST_IRQ_BY_NAME(index, prd, priority), rtc_alarm_periodic_isr, (NULL), 0);
#define ALARM_IRQ_INIT(index) IF_ENABLED(CONFIG_RTC_ALARM, (ALARM_IRQ_ENABLE(index)))
#define PERODIC_IRQ_INIT(index) IF_ENABLED(CONFIG_RTC_UPDATE, (PERODIC_IRQ_ENABLE(index)))
#define RTC_RENESAS_RA_INIT(index) \
static void rtc_renesas_ra_irq_config_func##index(const struct device *dev) \
{ \
R_ICU->IELSR[DT_INST_IRQ_BY_NAME(index, cup, irq)] = ELC_EVENT_RTC_CARRY; \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(index, cup, irq), \
DT_INST_IRQ_BY_NAME(index, cup, priority), rtc_carry_isr, (NULL), 0); \
irq_enable(DT_INST_IRQ_BY_NAME(index, cup, irq)); \
\
ALARM_IRQ_INIT(index) \
PERODIC_IRQ_INIT(index) \
} \
static const struct rtc_renesas_ra_config rtc_renesas_ra_config_##index = { \
.irq_config_func = rtc_renesas_ra_irq_config_func##index, \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(index)), \
RTC_RENESAS_RA_ALARM_COUNT_GET(index)}; \
static struct rtc_renesas_ra_data rtc_renesas_ra_data_##index = { \
.fsp_err_cfg = \
{ \
.adjustment_mode = RTC_RENESAS_RA_CALIBRATION_MODE, \
.adjustment_period = RTC_RENESAS_RA_CALIBRATION_PERIOD, \
.adjustment_type = RTC_ERROR_ADJUSTMENT_NONE, \
.adjustment_value = 0x00, \
}, \
.fsp_cfg = \
{ \
.p_err_cfg = &rtc_renesas_ra_data_##index.fsp_err_cfg, \
.alarm_irq = RTC_RENESAS_RA_IRQ_GET(index, alm, irq), \
.alarm_ipl = RTC_RENESAS_RA_IRQ_GET(index, alm, priority), \
.periodic_irq = RTC_RENESAS_RA_IRQ_GET(index, prd, irq), \
.periodic_ipl = RTC_RENESAS_RA_IRQ_GET(index, prd, priority), \
.carry_irq = RTC_RENESAS_RA_IRQ_GET(index, cup, irq), \
.carry_ipl = RTC_RENESAS_RA_IRQ_GET(index, cup, priority), \
.p_context = (void *)DEVICE_DT_INST_GET(index), \
.p_extend = NULL, \
}, \
}; \
\
DEVICE_DT_INST_DEFINE(index, &rtc_renesas_ra_init, NULL, &rtc_renesas_ra_data_##index, \
&rtc_renesas_ra_config_##index, PRE_KERNEL_1, \
CONFIG_RTC_INIT_PRIORITY, &rtc_renesas_ra_driver_api);
DT_INST_FOREACH_STATUS_OKAY(RTC_RENESAS_RA_INIT)