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
|
depends on HAS_MCUX_CTIMER
|
||||||
help
|
help
|
||||||
Enable support for MCUX CTIMER driver.
|
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>
|
#include <zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h>
|
||||||
LOG_MODULE_REGISTER(mcux_ctimer, CONFIG_COUNTER_LOG_LEVEL);
|
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 */
|
/* One of the CTimer channels is reserved to implement set_top_value API */
|
||||||
#define NUM_CHANNELS 3
|
#define NUM_CHANNELS 3
|
||||||
|
#else
|
||||||
|
#define NUM_CHANNELS 4
|
||||||
|
#endif
|
||||||
|
|
||||||
struct mcux_lpc_ctimer_channel_data {
|
struct mcux_lpc_ctimer_channel_data {
|
||||||
counter_alarm_callback_t alarm_callback;
|
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)
|
static uint32_t mcux_lpc_ctimer_get_top_value(const struct device *dev)
|
||||||
{
|
{
|
||||||
const struct mcux_lpc_ctimer_config *config = dev->config;
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
|
|
||||||
|
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||||
CTIMER_Type *base = config->base;
|
CTIMER_Type *base = config->base;
|
||||||
|
|
||||||
/* Return the top value if it has been set, else return the max top value */
|
/* 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 {
|
} else {
|
||||||
return config->info.max_top_value;
|
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,
|
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;
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
struct mcux_lpc_ctimer_data *data = dev->data;
|
struct mcux_lpc_ctimer_data *data = dev->data;
|
||||||
|
|
||||||
uint32_t ticks = alarm_cfg->ticks;
|
uint32_t ticks = alarm_cfg->ticks;
|
||||||
uint32_t current = mcux_lpc_ctimer_read(config->base);
|
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;
|
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) {
|
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
|
||||||
ticks += current;
|
ticks += current;
|
||||||
|
if (ticks > top) {
|
||||||
|
ticks %= top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->channels[chan_id].alarm_callback = alarm_cfg->callback;
|
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;
|
const struct mcux_lpc_ctimer_config *config = dev->config;
|
||||||
struct mcux_lpc_ctimer_data *data = dev->data;
|
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_callback = cfg->callback;
|
||||||
data->top_user_data = cfg->user_data;
|
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;
|
return -ETIME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_COUNTER_MCUX_CTIMER_RESERVE_CHANNEL_FOR_SETTOP
|
||||||
ctimer_match_config_t match_config = { .matchValue = cfg->ticks,
|
ctimer_match_config_t match_config = { .matchValue = cfg->ticks,
|
||||||
.enableCounterReset = true,
|
.enableCounterReset = true,
|
||||||
.enableCounterStop = false,
|
.enableCounterStop = false,
|
||||||
|
@ -156,6 +178,7 @@ static int mcux_lpc_ctimer_set_top_value(const struct device *dev,
|
||||||
.enableInterrupt = true };
|
.enableInterrupt = true };
|
||||||
|
|
||||||
CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config);
|
CTIMER_SetupMatch(config->base, NUM_CHANNELS, &match_config);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
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) {
|
if (((interrupt_stat & (0x01 << NUM_CHANNELS)) != 0) && data->top_callback) {
|
||||||
data->top_callback(dev, data->top_user_data);
|
data->top_callback(dev, data->top_user_data);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mcux_lpc_ctimer_init(const struct device *dev)
|
static int mcux_lpc_ctimer_init(const struct device *dev)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue