drivers: counter: Initial support for RZ/G3S
Add Counter driver support for Renesas RZ/G3S Signed-off-by: Hieu Nguyen <hieu.nguyen.ym@bp.renesas.com> Signed-off-by: Nhut Nguyen <nhut.nguyen.kc@renesas.com>
This commit is contained in:
parent
b5c5ba8c83
commit
bf6c665d73
7 changed files with 598 additions and 0 deletions
|
@ -53,3 +53,4 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_TIMER_MAX32 counter_max32_ti
|
|||
zephyr_library_sources_ifdef(CONFIG_COUNTER_RTC_MAX32 counter_max32_rtc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_MRT counter_nxp_mrt.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_RA_AGT counter_renesas_ra_agt.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_COUNTER_RENESAS_RZ_GTM counter_renesas_rz_gtm.c)
|
||||
|
|
|
@ -104,4 +104,6 @@ source "drivers/counter/Kconfig.nxp_mrt"
|
|||
|
||||
source "drivers/counter/Kconfig.renesas_ra"
|
||||
|
||||
source "drivers/counter/Kconfig.renesas_rz"
|
||||
|
||||
endif # COUNTER
|
||||
|
|
10
drivers/counter/Kconfig.renesas_rz
Normal file
10
drivers/counter/Kconfig.renesas_rz
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config COUNTER_RENESAS_RZ_GTM
|
||||
bool "Renesas RZ General Timer (GTM) Counter driver"
|
||||
default y
|
||||
depends on DT_HAS_RENESAS_RZ_GTM_COUNTER_ENABLED
|
||||
select USE_RZ_FSP_GTM
|
||||
help
|
||||
Enable the counter driver for the Renesas RZ General Timer (GTM).
|
553
drivers/counter/counter_renesas_rz_gtm.c
Normal file
553
drivers/counter/counter_renesas_rz_gtm.c
Normal file
|
@ -0,0 +1,553 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Renesas Electronics Corporation
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT renesas_rz_gtm_counter
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/counter.h>
|
||||
#include <r_gtm.h>
|
||||
|
||||
#define RZ_GTM_TOP_VALUE UINT32_MAX
|
||||
|
||||
#define counter_rz_gtm_clear_pending(irq) NVIC_ClearPendingIRQ(irq)
|
||||
#define counter_rz_gtm_set_pending(irq) NVIC_SetPendingIRQ(irq)
|
||||
#define counter_rz_gtm_is_pending(irq) NVIC_GetPendingIRQ(irq)
|
||||
|
||||
struct counter_rz_gtm_config {
|
||||
struct counter_config_info config_info;
|
||||
const timer_api_t *fsp_api;
|
||||
uint8_t irqn;
|
||||
};
|
||||
|
||||
struct counter_rz_gtm_data {
|
||||
timer_cfg_t *fsp_cfg;
|
||||
gtm_instance_ctrl_t *fsp_ctrl;
|
||||
/* top callback function */
|
||||
counter_top_callback_t top_cb;
|
||||
/* alarm callback function */
|
||||
counter_alarm_callback_t alarm_cb;
|
||||
void *user_data;
|
||||
uint32_t clk_freq;
|
||||
struct k_spinlock lock;
|
||||
uint32_t guard_period;
|
||||
uint32_t top_val;
|
||||
bool is_started;
|
||||
bool is_periodic;
|
||||
};
|
||||
|
||||
static int counter_rz_gtm_get_value(const struct device *dev, uint32_t *ticks)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
timer_status_t timer_status;
|
||||
fsp_err_t err;
|
||||
|
||||
err = cfg->fsp_api->statusGet(data->fsp_ctrl, &timer_status);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
uint32_t value = (uint32_t)timer_status.counter;
|
||||
*ticks = value;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void counter_rz_gtm_irq_handler(timer_callback_args_t *p_args)
|
||||
{
|
||||
const struct device *dev = p_args->p_context;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
counter_alarm_callback_t alarm_callback = data->alarm_cb;
|
||||
k_spinlock_key_t key;
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (alarm_callback) {
|
||||
uint32_t now;
|
||||
|
||||
counter_rz_gtm_get_value(dev, &now);
|
||||
data->alarm_cb = NULL;
|
||||
alarm_callback(dev, 0, now, data->user_data);
|
||||
} else if (data->top_cb) {
|
||||
data->top_cb(dev, data->user_data);
|
||||
}
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_init(const struct device *dev)
|
||||
{
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
int err;
|
||||
|
||||
data->top_val = data->fsp_cfg->period_counts;
|
||||
|
||||
err = cfg->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
|
||||
if (err != FSP_SUCCESS) {
|
||||
return err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static void counter_rz_gtm_start_freerun(const struct device *dev)
|
||||
{
|
||||
/* enable counter in free running mode */
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
|
||||
gtm_extended_cfg_t *fsp_cfg_extend = (gtm_extended_cfg_t *)data->fsp_cfg->p_extend;
|
||||
|
||||
fsp_cfg_extend->gtm_mode = GTM_TIMER_MODE_FREERUN;
|
||||
cfg->fsp_api->close(data->fsp_ctrl);
|
||||
cfg->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
|
||||
cfg->fsp_api->start(data->fsp_ctrl);
|
||||
}
|
||||
|
||||
static void counter_rz_gtm_start_interval(const struct device *dev)
|
||||
{
|
||||
/* start timer in interval mode */
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
|
||||
gtm_extended_cfg_t *fsp_cfg_extend = (gtm_extended_cfg_t *)data->fsp_cfg->p_extend;
|
||||
|
||||
fsp_cfg_extend->gtm_mode = GTM_TIMER_MODE_INTERVAL;
|
||||
cfg->fsp_api->close(data->fsp_ctrl);
|
||||
cfg->fsp_api->open(data->fsp_ctrl, data->fsp_cfg);
|
||||
cfg->fsp_api->start(data->fsp_ctrl);
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_start(const struct device *dev)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (data->is_started) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (data->is_periodic) {
|
||||
data->fsp_cfg->period_counts = data->top_val;
|
||||
counter_rz_gtm_start_interval(dev);
|
||||
} else {
|
||||
counter_rz_gtm_start_freerun(dev);
|
||||
}
|
||||
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
data->is_started = true;
|
||||
if (data->top_cb) {
|
||||
irq_enable(cfg->irqn);
|
||||
}
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_stop(const struct device *dev)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (!data->is_started) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fsp_err_t err = FSP_SUCCESS;
|
||||
|
||||
/* Stop timer */
|
||||
err = cfg->fsp_api->stop(data->fsp_ctrl);
|
||||
|
||||
/* dis irq */
|
||||
irq_disable(cfg->irqn);
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
|
||||
data->top_cb = NULL;
|
||||
data->alarm_cb = NULL;
|
||||
data->user_data = NULL;
|
||||
|
||||
data->is_started = false;
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_set_alarm(const struct device *dev, uint8_t chan,
|
||||
const struct counter_alarm_cfg *alarm_cfg)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
|
||||
bool absolute = alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE;
|
||||
uint32_t val = alarm_cfg->ticks;
|
||||
k_spinlock_key_t key;
|
||||
bool irq_on_late;
|
||||
uint32_t max_rel_val;
|
||||
uint32_t now, diff;
|
||||
int err = 0;
|
||||
|
||||
if (!alarm_cfg) {
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Alarm callback is mandatory */
|
||||
if (!alarm_cfg->callback) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (!data->is_started) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/** Alarm_cb need equal NULL before */
|
||||
if (data->alarm_cb) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/** Timer is currently in interval mode*/
|
||||
if (data->is_periodic) {
|
||||
/** return error because val exceeded the limit set alarm */
|
||||
if (val > data->fsp_cfg->period_counts) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* restore free running mode */
|
||||
irq_disable(cfg->irqn);
|
||||
data->top_cb = NULL;
|
||||
data->alarm_cb = alarm_cfg->callback;
|
||||
data->user_data = NULL;
|
||||
data->top_val = RZ_GTM_TOP_VALUE;
|
||||
data->is_periodic = false;
|
||||
|
||||
if (data->is_started) {
|
||||
data->fsp_cfg->period_counts = data->top_val;
|
||||
counter_rz_gtm_start_freerun(dev);
|
||||
}
|
||||
}
|
||||
|
||||
counter_rz_gtm_get_value(dev, &now);
|
||||
data->alarm_cb = alarm_cfg->callback;
|
||||
data->user_data = alarm_cfg->user_data;
|
||||
|
||||
if (absolute) {
|
||||
max_rel_val = RZ_GTM_TOP_VALUE - data->guard_period;
|
||||
irq_on_late = alarm_cfg->flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE;
|
||||
} else {
|
||||
/* If relative value is smaller than half of the counter range
|
||||
* it is assumed that there is a risk of setting value too late
|
||||
* and late detection algorithm must be applied. When late
|
||||
* setting is detected, interrupt shall be triggered for
|
||||
* immediate expiration of the timer. Detection is performed
|
||||
* by limiting relative distance between CC and counter.
|
||||
*
|
||||
* Note that half of counter range is an arbitrary value.
|
||||
*/
|
||||
irq_on_late = val < (RZ_GTM_TOP_VALUE / 2U);
|
||||
/* limit max to detect short relative being set too late. */
|
||||
max_rel_val = irq_on_late ? RZ_GTM_TOP_VALUE / 2U : RZ_GTM_TOP_VALUE;
|
||||
val = (now + val) & RZ_GTM_TOP_VALUE;
|
||||
}
|
||||
|
||||
/** Set new period */
|
||||
data->fsp_cfg->period_counts = val;
|
||||
err = cfg->fsp_api->periodSet(data->fsp_ctrl, data->fsp_cfg->period_counts);
|
||||
if (err != FSP_SUCCESS) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t read_counter_again = 0;
|
||||
|
||||
counter_rz_gtm_get_value(dev, &read_counter_again);
|
||||
diff = ((val - 1U) - read_counter_again) & RZ_GTM_TOP_VALUE;
|
||||
if (diff > max_rel_val) {
|
||||
if (absolute) {
|
||||
err = -ETIME;
|
||||
}
|
||||
|
||||
/* Interrupt is triggered always for relative alarm and
|
||||
* for absolute depending on the flag.
|
||||
*/
|
||||
if (irq_on_late) {
|
||||
irq_enable(cfg->irqn);
|
||||
counter_rz_gtm_set_pending(cfg->irqn);
|
||||
} else {
|
||||
data->alarm_cb = NULL;
|
||||
}
|
||||
} else {
|
||||
if (diff == 0) {
|
||||
/* RELOAD value could be set just in time for interrupt
|
||||
* trigger or too late. In any case time is interrupt
|
||||
* should be triggered. No need to enable interrupt
|
||||
* on TIMER just make sure interrupt is pending.
|
||||
*/
|
||||
irq_enable(cfg->irqn);
|
||||
counter_rz_gtm_set_pending(cfg->irqn);
|
||||
} else {
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
irq_enable(cfg->irqn);
|
||||
}
|
||||
}
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_cancel_alarm(const struct device *dev, uint8_t chan)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
|
||||
ARG_UNUSED(chan);
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (!data->is_started) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!data->alarm_cb) {
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
irq_disable(cfg->irqn);
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
data->alarm_cb = NULL;
|
||||
data->user_data = NULL;
|
||||
|
||||
k_spin_unlock(&data->lock, key);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_set_top_value(const struct device *dev,
|
||||
const struct counter_top_cfg *top_cfg)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
k_spinlock_key_t key;
|
||||
uint32_t cur_tick;
|
||||
int ret = 0;
|
||||
|
||||
if (!top_cfg) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/** -EBUSY if any alarm is active */
|
||||
if (data->alarm_cb) {
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
key = k_spin_lock(&data->lock);
|
||||
|
||||
if (!data->is_periodic && top_cfg->ticks == RZ_GTM_TOP_VALUE) {
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
if (top_cfg->ticks == RZ_GTM_TOP_VALUE) {
|
||||
/* restore free running mode */
|
||||
irq_disable(cfg->irqn);
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
data->top_cb = NULL;
|
||||
data->user_data = NULL;
|
||||
data->top_val = RZ_GTM_TOP_VALUE;
|
||||
data->is_periodic = false;
|
||||
|
||||
if (data->is_started) {
|
||||
counter_rz_gtm_start_freerun(dev);
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
}
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
data->top_cb = top_cfg->callback;
|
||||
data->user_data = top_cfg->user_data;
|
||||
data->top_val = top_cfg->ticks;
|
||||
|
||||
if (!data->is_started) {
|
||||
data->is_periodic = true;
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
if (!data->is_periodic) {
|
||||
/* switch to interval mode first time, restart timer */
|
||||
ret = cfg->fsp_api->stop(data->fsp_ctrl);
|
||||
irq_disable(cfg->irqn);
|
||||
data->is_periodic = true;
|
||||
data->fsp_cfg->period_counts = data->top_val;
|
||||
counter_rz_gtm_start_interval(dev);
|
||||
|
||||
if (data->top_cb) {
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
irq_enable(cfg->irqn);
|
||||
}
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
if (!data->top_cb) {
|
||||
/* new top cfg is without callback - stop IRQs */
|
||||
irq_disable(cfg->irqn);
|
||||
counter_rz_gtm_clear_pending(cfg->irqn);
|
||||
}
|
||||
/* timer already in interval mode - only change top value */
|
||||
data->fsp_cfg->period_counts = data->top_val;
|
||||
cfg->fsp_api->periodSet(&data->fsp_ctrl, data->fsp_cfg->period_counts);
|
||||
|
||||
/* check if counter reset is required */
|
||||
if (top_cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
|
||||
/* Don't reset counter */
|
||||
counter_rz_gtm_get_value(dev, &cur_tick);
|
||||
|
||||
if (cur_tick >= data->top_val) {
|
||||
ret = -ETIME;
|
||||
if (top_cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE) {
|
||||
/* Reset counter if current is late */
|
||||
cfg->fsp_api->stop(data->fsp_ctrl);
|
||||
cfg->fsp_api->start(data->fsp_ctrl);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* reset counter */
|
||||
cfg->fsp_api->stop(data->fsp_ctrl);
|
||||
cfg->fsp_api->start(data->fsp_ctrl);
|
||||
}
|
||||
|
||||
exit_unlock:
|
||||
k_spin_unlock(&data->lock, key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t counter_rz_gtm_get_pending_int(const struct device *dev)
|
||||
{
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
|
||||
/* There is no register to check TIMER peripheral to check for interrupt
|
||||
* pending, check directly in NVIC.
|
||||
*/
|
||||
return counter_rz_gtm_is_pending(cfg->irqn);
|
||||
}
|
||||
|
||||
static uint32_t counter_rz_gtm_get_top_value(const struct device *dev)
|
||||
{
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
uint32_t top_val = RZ_GTM_TOP_VALUE;
|
||||
|
||||
if (data->is_periodic) {
|
||||
timer_info_t info;
|
||||
|
||||
cfg->fsp_api->infoGet(data->fsp_ctrl, &info);
|
||||
top_val = info.period_counts;
|
||||
}
|
||||
|
||||
return top_val;
|
||||
}
|
||||
static uint32_t counter_rz_gtm_get_guard_period(const struct device *dev, uint32_t flags)
|
||||
{
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
|
||||
ARG_UNUSED(flags);
|
||||
return data->guard_period;
|
||||
}
|
||||
|
||||
static int counter_rz_gtm_set_guard_period(const struct device *dev, uint32_t guard, uint32_t flags)
|
||||
{
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
|
||||
ARG_UNUSED(flags);
|
||||
__ASSERT_NO_MSG(guard < counter_rz_gtm_get_top_value(dev));
|
||||
|
||||
data->guard_period = guard;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t counter_rz_gtm_get_freq(const struct device *dev)
|
||||
{
|
||||
struct counter_rz_gtm_data *data = dev->data;
|
||||
const struct counter_rz_gtm_config *cfg = dev->config;
|
||||
timer_info_t info;
|
||||
|
||||
cfg->fsp_api->infoGet(data->fsp_ctrl, &info);
|
||||
|
||||
return info.clock_frequency;
|
||||
}
|
||||
|
||||
static DEVICE_API(counter, counter_rz_gtm_driver_api) = {
|
||||
.start = counter_rz_gtm_start,
|
||||
.stop = counter_rz_gtm_stop,
|
||||
.get_value = counter_rz_gtm_get_value,
|
||||
.set_alarm = counter_rz_gtm_set_alarm,
|
||||
.cancel_alarm = counter_rz_gtm_cancel_alarm,
|
||||
.set_top_value = counter_rz_gtm_set_top_value,
|
||||
.get_pending_int = counter_rz_gtm_get_pending_int,
|
||||
.get_top_value = counter_rz_gtm_get_top_value,
|
||||
.get_guard_period = counter_rz_gtm_get_guard_period,
|
||||
.set_guard_period = counter_rz_gtm_set_guard_period,
|
||||
.get_freq = counter_rz_gtm_get_freq,
|
||||
};
|
||||
|
||||
extern void gtm_int_isr(void);
|
||||
|
||||
#define GTM(idx) DT_INST_PARENT(idx)
|
||||
|
||||
#define COUNTER_RZG_GTM_INIT(inst) \
|
||||
static gtm_instance_ctrl_t g_timer##inst##_ctrl; \
|
||||
static gtm_extended_cfg_t g_timer##inst##_extend = { \
|
||||
.generate_interrupt_when_starts = GTM_GIWS_TYPE_DISABLED, \
|
||||
.gtm_mode = GTM_TIMER_MODE_FREERUN, \
|
||||
}; \
|
||||
static timer_cfg_t g_timer##inst##_cfg = { \
|
||||
.mode = TIMER_MODE_PERIODIC, \
|
||||
.period_counts = (uint32_t)RZ_GTM_TOP_VALUE, \
|
||||
.channel = DT_PROP(GTM(inst), channel), \
|
||||
.p_callback = counter_rz_gtm_irq_handler, \
|
||||
.p_context = DEVICE_DT_GET(DT_DRV_INST(inst)), \
|
||||
.p_extend = &g_timer##inst##_extend, \
|
||||
.cycle_end_ipl = DT_IRQ_BY_NAME(GTM(inst), overflow, priority), \
|
||||
.cycle_end_irq = DT_IRQ_BY_NAME(GTM(inst), overflow, irq), \
|
||||
}; \
|
||||
static const struct counter_rz_gtm_config counter_rz_gtm_config_##inst = { \
|
||||
.config_info = \
|
||||
{ \
|
||||
.max_top_value = RZ_GTM_TOP_VALUE, \
|
||||
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
|
||||
.channels = 1, \
|
||||
}, \
|
||||
.fsp_api = &g_timer_on_gtm, \
|
||||
.irqn = DT_IRQ_BY_NAME(GTM(inst), overflow, irq), \
|
||||
}; \
|
||||
static struct counter_rz_gtm_data counter_rz_gtm_data_##inst = { \
|
||||
.fsp_cfg = &g_timer##inst##_cfg, .fsp_ctrl = &g_timer##inst##_ctrl}; \
|
||||
static int counter_rz_gtm_init_##inst(const struct device *dev) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_IRQ_BY_NAME(GTM(inst), overflow, irq), \
|
||||
DT_IRQ_BY_NAME(GTM(inst), overflow, priority), gtm_int_isr, \
|
||||
DEVICE_DT_INST_GET(inst), 0); \
|
||||
return counter_rz_gtm_init(dev); \
|
||||
} \
|
||||
DEVICE_DT_INST_DEFINE(inst, counter_rz_gtm_init_##inst, NULL, &counter_rz_gtm_data_##inst, \
|
||||
&counter_rz_gtm_config_##inst, PRE_KERNEL_1, \
|
||||
CONFIG_COUNTER_INIT_PRIORITY, &counter_rz_gtm_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(COUNTER_RZG_GTM_INIT)
|
8
dts/bindings/counter/renesas,rz-gtm-counter.yaml
Normal file
8
dts/bindings/counter/renesas,rz-gtm-counter.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas RZ GTM Counter
|
||||
|
||||
compatible: "renesas,rz-gtm-counter"
|
||||
|
||||
include: [base.yaml]
|
19
dts/bindings/timer/renesas,rz-gtm.yaml
Normal file
19
dts/bindings/timer/renesas,rz-gtm.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2024 Renesas Electronics Corporation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: Renesas RZ GTM Timer
|
||||
|
||||
compatible: "renesas,rz-gtm"
|
||||
|
||||
include: base.yaml
|
||||
|
||||
properties:
|
||||
reg:
|
||||
required: true
|
||||
|
||||
channel:
|
||||
type: int
|
||||
required: true
|
||||
|
||||
interrupts:
|
||||
required: true
|
|
@ -163,4 +163,9 @@ config USE_RZ_FSP_SCIF_UART
|
|||
help
|
||||
Enable RZ FSP SCIF UART driver
|
||||
|
||||
config USE_RZ_FSP_GTM
|
||||
bool
|
||||
help
|
||||
Enable RZ FSP GTM driver
|
||||
|
||||
endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue