drivers: counter: Update NXP CTimer to implement set_top_value

Implement the set_top_value. This reserves one of the Match channels
to set the top value and to reset the counter.
Therefore the number of channels available to the user is reduced by 1.

Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
This commit is contained in:
Mahesh Mahadevan 2022-04-22 10:19:45 -05:00 committed by Carles Cufí
commit 5a5c1ae76d

View file

@ -12,7 +12,8 @@
#include <dt-bindings/clock/mcux_lpc_syscon_clock.h>
LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL);
#define NUM_CHANNELS 4
/* One of the CTimer channels is reserved to implement set_top_value API */
#define NUM_CHANNELS 3
struct mcux_lpc_ctimer_channel_data {
counter_alarm_callback_t alarm_callback;
@ -21,6 +22,8 @@ struct mcux_lpc_ctimer_channel_data {
struct mcux_lpc_ctimer_data {
struct mcux_lpc_ctimer_channel_data channels[NUM_CHANNELS];
counter_top_callback_t top_callback;
void *top_user_data;
};
struct mcux_lpc_ctimer_config {
@ -64,6 +67,19 @@ static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks)
return 0;
}
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
{
const struct mcux_lpc_ctimer_config *config = dev->config;
CTIMER_Type *base = config->base;
/* Return the top value if it has been set, else return the max top value */
if (base->MR[NUM_CHANNELS] != 0) {
return base->MR[NUM_CHANNELS];
} else {
return config->info.max_top_value;
}
}
static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
@ -73,6 +89,10 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
uint32_t ticks = alarm_cfg->ticks;
uint32_t current = mcux_lpc_ctimer_read(config->base);
if (alarm_cfg->ticks > mcux_lpc_ctimer_get_top_value(dev)) {
return -EINVAL;
}
if (data->channels[chan_id].alarm_callback != NULL) {
LOG_ERR("channel already in use");
return -EBUSY;
@ -113,9 +133,33 @@ static int mcux_lpc_ctimer_cancel_alarm(const struct device *dev, uint8_t chan_i
static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
const struct counter_top_cfg *cfg)
{
ARG_UNUSED(dev);
ARG_UNUSED(cfg);
return -ENOTSUP;
const struct mcux_lpc_ctimer_config *config = dev->config;
struct mcux_lpc_ctimer_data *data = dev->data;
bool counter_reset = true;
bool counter_interrupt = true;
data->top_callback = cfg->callback;
data->top_user_data = cfg->user_data;
if (cfg->flags & COUNTER_TOP_CFG_DONT_RESET) {
counter_reset = false;
}
/* If top value specified is 0, then turn off the interrupt */
if (cfg->ticks == 0) {
counter_interrupt = false;
}
ctimer_match_config_t match_config = { .matchValue = cfg->ticks,
.enableCounterReset = counter_reset,
.enableCounterStop = false,
.outControl = kCTIMER_Output_NoAction,
.outPinInitState = false,
.enableInterrupt = counter_interrupt };
CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config);
return 0;
}
static uint32_t mcux_lpc_ctimer_get_pending_int(const struct device *dev)
@ -125,13 +169,6 @@ static uint32_t mcux_lpc_ctimer_get_pending_int(const struct device *dev)
return (CTIMER_GetStatusFlags(config->base) & 0xF) != 0;
}
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
{
const struct mcux_lpc_ctimer_config *config = dev->config;
return config->info.max_top_value;
}
static uint32_t mcux_lpc_ctimer_get_freq(const struct device *dev)
{
/*
@ -180,6 +217,10 @@ static void mcux_lpc_ctimer_isr(const struct device *dev)
alarm_callback(dev, chan, ticks, alarm_user_data);
}
}
if (((interrupt_stat & (0x01 << NUM_CHANNELS)) != 0) && data->top_callback) {
data->top_callback(dev, data->top_user_data);
}
}
static int mcux_lpc_ctimer_init(const struct device *dev)