From 5a5c1ae76dbcc566e7875222838a1715d1c7b9fb Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Fri, 22 Apr 2022 10:19:45 -0500 Subject: [PATCH] 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 --- drivers/counter/counter_mcux_ctimer.c | 63 ++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/counter/counter_mcux_ctimer.c b/drivers/counter/counter_mcux_ctimer.c index 86164436604..3fbc5a6bb21 100644 --- a/drivers/counter/counter_mcux_ctimer.c +++ b/drivers/counter/counter_mcux_ctimer.c @@ -12,7 +12,8 @@ #include 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)