drivers: counter: Update CTimer to fix alarm setting
1. Make sure the relative alarm value is set correctly 2. Add a Kconfig to give user the option of reserving a CTimer channel for implementing the set_top_value function Signed-off-by: Mahesh Mahadevan <mahesh.mahadevan@nxp.com>
This commit is contained in:
parent
06cd8abde1
commit
649bb3bb44
2 changed files with 35 additions and 2 deletions
|
@ -8,3 +8,11 @@ config COUNTER_MCUX_CTIMER
|
|||
depends on HAS_MCUX_CTIMER
|
||||
help
|
||||
Enable support for MCUX CTIMER driver.
|
||||
|
||||
config COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
bool "reserve a ctimer channel to set the top value"
|
||||
default y
|
||||
depends on COUNTER_MCUX_CTIMER
|
||||
help
|
||||
This reserves a CTimer channel to set the top value. Without
|
||||
this the set top value can be set only to the max counter value.
|
||||
|
|
|
@ -12,8 +12,12 @@
|
|||
#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
|
||||
LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL);
|
||||
|
||||
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
/* One of the CTimer channels is reserved to implement set_top_value API */
|
||||
#define NUM_CHANNELS 3
|
||||
#else
|
||||
#define NUM_CHANNELS 4
|
||||
#endif
|
||||
|
||||
struct mcux_lpc_ctimer_channel_data {
|
||||
counter_alarm_callback_t alarm_callback;
|
||||
|
@ -70,6 +74,8 @@ static int mcux_lpc_ctimer_get_value(const struct device *dev, uint32_t *ticks)
|
|||
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
|
||||
{
|
||||
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||
|
||||
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
CTIMER_Type *base = config->base;
|
||||
|
||||
/* Return the top value if it has been set, else return the max top value */
|
||||
|
@ -78,6 +84,9 @@ static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
|
|||
} else {
|
||||
return config->info.max_top_value;
|
||||
}
|
||||
#else
|
||||
return config->info.max_top_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
|
||||
|
@ -85,11 +94,11 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
|
|||
{
|
||||
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||
|
||||
uint32_t ticks = alarm_cfg->ticks;
|
||||
uint32_t current = mcux_lpc_ctimer_read(config->base);
|
||||
uint32_t top = mcux_lpc_ctimer_get_top_value(dev);
|
||||
|
||||
if (alarm_cfg->ticks > mcux_lpc_ctimer_get_top_value(dev)) {
|
||||
if (alarm_cfg->ticks > top) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -100,6 +109,9 @@ static int mcux_lpc_ctimer_set_alarm(const struct device *dev, uint8_t chan_id,
|
|||
|
||||
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
|
||||
ticks += current;
|
||||
if (ticks > top) {
|
||||
ticks %= top;
|
||||
}
|
||||
}
|
||||
|
||||
data->channels[chan_id].alarm_callback = alarm_cfg->callback;
|
||||
|
@ -136,6 +148,15 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
|
|||
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||
|
||||
#ifndef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
/* Only allow max value when we do not reserve a ctimer channel for setting top value */
|
||||
if (cfg->ticks != config->info.max_top_value) {
|
||||
LOG_ERR("Wrap can only be set to 0x%x",
|
||||
config->info.max_top_value);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
data->top_callback = cfg->callback;
|
||||
data->top_user_data = cfg->user_data;
|
||||
|
||||
|
@ -148,6 +169,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
|
|||
return -ETIME;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
ctimer_match_config_t match_config = { .matchValue = cfg->ticks,
|
||||
.enableCounterReset = true,
|
||||
.enableCounterStop = false,
|
||||
|
@ -156,6 +178,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
|
|||
.enableInterrupt = true };
|
||||
|
||||
CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -216,9 +239,11 @@ static void mcux_lpc_ctimer_isr(const struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||
if (((interrupt_stat & (0x01 << NUM_CHANNELS)) != 0) && data->top_callback) {
|
||||
data->top_callback(dev, data->top_user_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int mcux_lpc_ctimer_init(const struct device *dev)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue