diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index 2cff7c5f51e0..e8c53ec4d1bf 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -10,6 +10,14 @@ menuconfig COUNTER if COUNTER +config COUNTER_CAPTURE + bool "Counter capture" + help + Enable support for counter capture. This is a feature that allows + hardware timestamping of external events as well as a software + interrupt on the event. This feature is not supported by all + counter drivers. + config COUNTER_INIT_PRIORITY int "Counter init priority" default 60 diff --git a/drivers/counter/Kconfig.stm32_timer b/drivers/counter/Kconfig.stm32_timer index a4539911f091..d26360775c64 100644 --- a/drivers/counter/Kconfig.stm32_timer +++ b/drivers/counter/Kconfig.stm32_timer @@ -7,5 +7,6 @@ config COUNTER_TIMER_STM32 depends on DT_HAS_ST_STM32_COUNTER_ENABLED select USE_STM32_LL_TIM select RESET + select PINCTRL if COUNTER_CAPTURE help Enable the counter driver for STM32 family of processors. diff --git a/drivers/counter/counter_ite_it8xxx2.c b/drivers/counter/counter_ite_it8xxx2.c index cbd34a605ffb..a038c38068a9 100644 --- a/drivers/counter/counter_ite_it8xxx2.c +++ b/drivers/counter/counter_ite_it8xxx2.c @@ -275,7 +275,7 @@ static int counter_it8xxx2_init(const struct device *dev) const struct counter_it8xxx2_config *config = dev->config; LOG_DBG("max top value = 0x%08x", config->info.max_top_value); - LOG_DBG("frequency = %d", config->info.freq); + LOG_DBG("frequency = %llu", config->info.freq); LOG_DBG("channels = %d", config->info.channels); /* set the top value of top timer */ diff --git a/drivers/counter/counter_ll_stm32_timer.c b/drivers/counter/counter_ll_stm32_timer.c index c7a6216ac664..f8a0b428b9ec 100644 --- a/drivers/counter/counter_ll_stm32_timer.c +++ b/drivers/counter/counter_ll_stm32_timer.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,12 @@ static uint32_t(*const get_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *) = { LL_TIM_OC_GetCompareCH3, LL_TIM_OC_GetCompareCH4, }; #endif +#ifdef CONFIG_COUNTER_CAPTURE +static uint32_t (*const get_timer_capture[TIMER_MAX_CH])(const TIM_TypeDef *) = { + LL_TIM_IC_GetCaptureCH1, LL_TIM_IC_GetCaptureCH2, + LL_TIM_IC_GetCaptureCH3, LL_TIM_IC_GetCaptureCH4, +}; +#endif /* CONFIG_COUNTER_CAPTURE */ /** Channel to interrupt enable function mapping. */ static void(*const enable_it[TIMER_MAX_CH])(TIM_TypeDef *) = { LL_TIM_EnableIT_CC1, LL_TIM_EnableIT_CC2, @@ -96,6 +103,9 @@ struct counter_stm32_data { struct counter_stm32_ch_data { counter_alarm_callback_t callback; +#ifdef CONFIG_COUNTER_CAPTURE + counter_capture_cb_t capture; +#endif /* CONFIG_COUNTER_CAPTURE */ void *user_data; }; @@ -109,6 +119,9 @@ struct counter_stm32_config { uint32_t irqn; /* Reset controller device configuration */ const struct reset_dt_spec reset; +#ifdef CONFIG_COUNTER_CAPTURE + const struct pinctrl_dev_config *pcfg; +#endif /* CONFIG_COUNTER_CAPTURE */ LOG_INSTANCE_PTR_DECLARE(log); }; @@ -497,6 +510,14 @@ static int counter_stm32_init_timer(const struct device *dev) /* config/enable IRQ */ cfg->irq_config_func(dev); +#ifdef CONFIG_COUNTER_CAPTURE + r = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (r < 0) { + LOG_ERR("%s: Counter Capture pinctrl setup failed (%d)", dev->name, r); + return r; + } +#endif /* CONFIG_COUNTER_CAPTURE */ + /* initialize timer */ LL_TIM_StructInit(&init); @@ -540,6 +561,26 @@ static uint32_t counter_stm32_get_freq(const struct device *dev) return data->freq; } +static int counter_stm32_reset_timer(const struct device *dev) +{ + const struct counter_stm32_config *config = dev->config; + TIM_TypeDef *timer = config->timer; + + LL_TIM_SetCounter(timer, 0); + + return 0; +} + +static int counter_stm32_set_value(const struct device *dev, uint32_t ticks) +{ + const struct counter_stm32_config *config = dev->config; + TIM_TypeDef *timer = config->timer; + + LL_TIM_SetCounter(timer, ticks); + + return 0; +} + static void counter_stm32_top_irq_handle(const struct device *dev) { struct counter_stm32_data *data = dev->data; @@ -550,28 +591,119 @@ static void counter_stm32_top_irq_handle(const struct device *dev) cb(dev, data->top_user_data); } -static void counter_stm32_alarm_irq_handle(const struct device *dev, uint32_t id) +static void counter_stm32_irq_handle(const struct device *dev, uint32_t id) { const struct counter_stm32_config *config = dev->config; struct counter_stm32_data *data = dev->data; TIM_TypeDef *timer = config->timer; struct counter_stm32_ch_data *chdata; - counter_alarm_callback_t cb; atomic_and(&data->cc_int_pending, ~BIT(id)); - disable_it[id](timer); chdata = &config->ch_data[id]; - cb = chdata->callback; - chdata->callback = NULL; +#ifdef CONFIG_COUNTER_CAPTURE + /* With Counter Capture, we need to check which mode it was configured for */ + if (LL_TIM_IC_GetActiveInput(timer, LL_TIM_CHANNEL_CH1 << (4 * id)) == + LL_TIM_ACTIVEINPUT_DIRECTTI) { + counter_capture_cb_t cb; + + cb = chdata->capture; + + /* TODO: check overcapture flag, then print error? + * CC1OF is also set if at least two consecutive captures + * occurred whereas the flag was not cleared + */ + + if (cb) { + uint32_t cc_val = get_timer_capture[id](timer); + uint32_t pol = LL_TIM_IC_GetPolarity(timer, LL_TIM_CHANNEL_CH1 << (4*id)); + uint32_t flags = 0; + + /* translate stm32 flags to zephyr flags */ + if (pol == LL_TIM_IC_POLARITY_RISING) { + flags = COUNTER_CAPTURE_RISING_EDGE; + } else if (pol == LL_TIM_IC_POLARITY_FALLING) { + flags = COUNTER_CAPTURE_FALLING_EDGE; + } else if (pol == LL_TIM_IC_POLARITY_BOTHEDGE) { + flags = COUNTER_CAPTURE_BOTH_EDGES; + } + + cb(dev, id, flags, cc_val, chdata->user_data); + } + } else { +#endif + counter_alarm_callback_t cb; + /* Alarm is One-Shot, so disable the Interrupt */ + disable_it[id](timer); + + cb = chdata->callback; + chdata->callback = NULL; + + if (cb) { + uint32_t cc_val = get_timer_compare[id](timer); + + cb(dev, id, cc_val, chdata->user_data); + } +#ifdef CONFIG_COUNTER_CAPTURE + } +#endif +} +#ifdef CONFIG_COUNTER_CAPTURE +static int counter_stm32_capture_enable(const struct device *dev, uint8_t chan) +{ + const struct counter_stm32_config *config = dev->config; + TIM_TypeDef *timer = config->timer; + + LL_TIM_CC_EnableChannel(timer, LL_TIM_CHANNEL_CH1 << (4*chan)); - if (cb) { - uint32_t cc_val = get_timer_compare[id](timer); + return 0; +} + +static int counter_stm32_capture_disable(const struct device *dev, uint8_t chan) +{ + const struct counter_stm32_config *config = dev->config; + TIM_TypeDef *timer = config->timer; - cb(dev, id, cc_val, chdata->user_data); + LL_TIM_CC_DisableChannel(timer, LL_TIM_CHANNEL_CH1 << (4*chan)); + + return 0; +} + +static int counter_stm32_capture_callback_set(const struct device *dev, uint8_t chan, + uint32_t flags, counter_capture_cb_t cb, + void *user_data) +{ + const struct counter_stm32_config *config = dev->config; + struct counter_stm32_ch_data *chdata = &config->ch_data[chan]; + TIM_TypeDef *timer = config->timer; + uint32_t config_flags = LL_TIM_ACTIVEINPUT_DIRECTTI; + + chdata->capture = cb; + chdata->user_data = user_data; + + if ((flags & COUNTER_CAPTURE_BOTH_EDGES) == COUNTER_CAPTURE_BOTH_EDGES) { + config_flags |= LL_TIM_IC_POLARITY_BOTHEDGE; + } else if (flags & COUNTER_CAPTURE_FALLING_EDGE) { + config_flags |= LL_TIM_IC_POLARITY_FALLING; + } else if (flags & COUNTER_CAPTURE_RISING_EDGE) { + config_flags |= LL_TIM_IC_POLARITY_RISING; } + /* TODO: add 'vendor' config flags for filter, prescaler div */ + config_flags |= (LL_TIM_ICPSC_DIV1 | LL_TIM_IC_FILTER_FDIV1); + + /* Config is only writable when it is off */ + LL_TIM_CC_DisableChannel(timer, LL_TIM_CHANNEL_CH1 << (4*chan)); + + LL_TIM_IC_Config(timer, LL_TIM_CHANNEL_CH1 << (4*chan), config_flags); + + LL_TIM_CC_EnableChannel(timer, LL_TIM_CHANNEL_CH1 << (4*chan)); + /* enable interrupt */ + enable_it[chan](timer); + + return 0; } +#endif static DEVICE_API(counter, counter_stm32_driver_api) = { .start = counter_stm32_start, @@ -585,6 +717,13 @@ static DEVICE_API(counter, counter_stm32_driver_api) = { .get_guard_period = counter_stm32_get_guard_period, .set_guard_period = counter_stm32_set_guard_period, .get_freq = counter_stm32_get_freq, + .reset = counter_stm32_reset_timer, + .set_value = counter_stm32_set_value, +#ifdef CONFIG_COUNTER_CAPTURE + .capture_enable = counter_stm32_capture_enable, + .capture_disable = counter_stm32_capture_disable, + .capture_callback_set = counter_stm32_capture_callback_set, +#endif }; #define TIM_IRQ_HANDLE_CC(timx, cc) \ @@ -595,7 +734,7 @@ static DEVICE_API(counter, counter_stm32_driver_api) = { if (hw_irq) { \ LL_TIM_ClearFlag_CC##cc(timer); \ } \ - counter_stm32_alarm_irq_handle(dev, cc - 1U); \ + counter_stm32_irq_handle(dev, cc - 1U); \ } \ } while (0) @@ -638,6 +777,8 @@ void counter_stm32_irq_handler(const struct device *dev) BUILD_ASSERT(NUM_CH(TIM(idx)) <= TIMER_MAX_CH, \ "TIMER too many channels"); \ \ + IF_ENABLED(CONFIG_COUNTER_CAPTURE, \ + (PINCTRL_DT_INST_DEFINE(idx);)) \ static struct counter_stm32_data counter##idx##_data; \ static struct counter_stm32_ch_data counter##idx##_ch_data[TIMER_MAX_CH]; \ \ @@ -669,6 +810,8 @@ void counter_stm32_irq_handler(const struct device *dev) .irq_config_func = counter_##idx##_stm32_irq_config, \ .irqn = DT_IRQN(TIMER(idx)), \ .reset = RESET_DT_SPEC_GET(TIMER(idx)), \ + IF_ENABLED(CONFIG_COUNTER_CAPTURE, \ + (.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx),)) \ }; \ \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/counter/counter_mcux_gpt.c b/drivers/counter/counter_mcux_gpt.c index c0e714ea41dc..81ec115fd51c 100644 --- a/drivers/counter/counter_mcux_gpt.c +++ b/drivers/counter/counter_mcux_gpt.c @@ -199,7 +199,7 @@ static int mcux_gpt_init(const struct device *dev) /* Adjust divider to match expected freq */ if (clock_freq % config->info.freq) { - LOG_ERR("Cannot Adjust GPT freq to %u\n", config->info.freq); + LOG_ERR("Cannot Adjust GPT freq to %llu\n", config->info.freq); LOG_ERR("clock src is %u\n", clock_freq); return -EINVAL; } diff --git a/drivers/counter/counter_xlnx_axi_timer.c b/drivers/counter/counter_xlnx_axi_timer.c index 9cb837ec7349..1a8c1e3f9db3 100644 --- a/drivers/counter/counter_xlnx_axi_timer.c +++ b/drivers/counter/counter_xlnx_axi_timer.c @@ -294,7 +294,7 @@ static int xlnx_axi_timer_init(const struct device *dev) const struct xlnx_axi_timer_config *config = dev->config; LOG_DBG("max top value = 0x%08x", config->info.max_top_value); - LOG_DBG("frequency = %d", config->info.freq); + LOG_DBG("frequency = %llu", config->info.freq); LOG_DBG("channels = %d", config->info.channels); xlnx_axi_timer_write32(dev, config->info.max_top_value, TLR0_OFFSET); diff --git a/dts/bindings/counter/st,stm32-counter.yaml b/dts/bindings/counter/st,stm32-counter.yaml index 74ab8e220c59..cd5104a09417 100644 --- a/dts/bindings/counter/st,stm32-counter.yaml +++ b/dts/bindings/counter/st,stm32-counter.yaml @@ -5,4 +5,4 @@ description: STM32 counters compatible: "st,stm32-counter" -include: base.yaml +include: [base.yaml, pinctrl-device.yaml] diff --git a/include/zephyr/drivers/counter.h b/include/zephyr/drivers/counter.h index d929c0d8332a..71a37725d225 100644 --- a/include/zephyr/drivers/counter.h +++ b/include/zephyr/drivers/counter.h @@ -112,6 +112,35 @@ extern "C" { /**@} */ +/** + * @anchor COUNTER_CAPTURE_FLAGS + * @name Counter capture flags + * + * @brief Used by @ref counter_capture_callback_set. + * @{ + */ + +/** + * @brief Capture rising edge of an external input signal + */ + #define COUNTER_CAPTURE_RISING_EDGE BIT(0) + +/** + * @brief Capture falling edge of an external input signal + */ + #define COUNTER_CAPTURE_FALLING_EDGE BIT(1) + +/** + * @brief Capture both falling and rising edge of an external input signal + */ + #define COUNTER_CAPTURE_BOTH_EDGES (COUNTER_CAPTURE_FALLING_EDGE | COUNTER_CAPTURE_RISING_EDGE) + + /**@} */ + +typedef void (*counter_capture_cb_t)(const struct device *dev, uint8_t chan, + uint32_t flags, uint64_t ticks, + void *user_data); + /** @brief Alarm callback * * @param dev Pointer to the device structure for the driver instance. @@ -196,7 +225,7 @@ struct counter_config_info { /** * Frequency of the source clock if synchronous events are counted. */ - uint32_t freq; + uint64_t freq; /** * Flags (see @ref COUNTER_FLAGS). */ @@ -216,6 +245,10 @@ typedef int (*counter_api_get_value)(const struct device *dev, typedef int (*counter_api_get_value_64)(const struct device *dev, uint64_t *ticks); typedef int (*counter_api_reset)(const struct device *dev); +typedef int (*counter_api_set_value)(const struct device *dev, + uint32_t ticks); +typedef int (*counter_api_set_value_64)(const struct device *dev, + uint64_t ticks); typedef int (*counter_api_set_alarm)(const struct device *dev, uint8_t chan_id, const struct counter_alarm_cfg *alarm_cfg); @@ -231,6 +264,16 @@ typedef int (*counter_api_set_guard_period)(const struct device *dev, uint32_t ticks, uint32_t flags); typedef uint32_t (*counter_api_get_freq)(const struct device *dev); +typedef uint64_t (*counter_api_get_freq_64)(const struct device *dev); +typedef int (*counter_api_capture_callback_set)(const struct device *dev, + uint8_t chan, + uint32_t flags, + counter_capture_cb_t cb, + void *user_data); +typedef int (*counter_api_capture_enable)(const struct device *dev, + uint8_t chan); +typedef int (*counter_api_capture_disable)(const struct device *dev, + uint8_t chan); __subsystem struct counter_driver_api { counter_api_start start; @@ -238,6 +281,8 @@ __subsystem struct counter_driver_api { counter_api_get_value get_value; counter_api_get_value_64 get_value_64; counter_api_reset reset; + counter_api_set_value set_value; + counter_api_set_value_64 set_value_64; counter_api_set_alarm set_alarm; counter_api_cancel_alarm cancel_alarm; counter_api_set_top_value set_top_value; @@ -246,6 +291,12 @@ __subsystem struct counter_driver_api { counter_api_get_guard_period get_guard_period; counter_api_set_guard_period set_guard_period; counter_api_get_freq get_freq; + counter_api_get_freq get_freq_64; +#if defined(CONFIG_COUNTER_CAPTURE) || defined(__DOXYGEN__) + counter_api_capture_callback_set capture_callback_set; + counter_api_capture_enable capture_enable; + counter_api_capture_disable capture_disable; +#endif }; /** @@ -300,9 +351,112 @@ static inline uint32_t z_impl_counter_get_frequency(const struct device *dev) const struct counter_driver_api *api = (struct counter_driver_api *)dev->api; - return api->get_freq ? api->get_freq(dev) : config->freq; + if (config->freq) { + return config->freq > UINT32_MAX ? UINT32_MAX : (uint32_t)config->freq; + } else { + return api->get_freq(dev); + } } +/** + * @brief Function to get counter frequency in 64bits. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * + * @return Frequency of the counter in Hz, or zero if the counter does + * not have a fixed frequency. + */ +__syscall uint64_t counter_get_frequency_64(const struct device *dev); + +static inline uint64_t z_impl_counter_get_frequency_64(const struct device *dev) +{ + const struct counter_config_info *config = + (const struct counter_config_info *)dev->config; + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (config->freq) { + return config->freq; + } else { + return api->get_freq_64 ? api->get_freq_64(dev) : -ENOTSUP; + } +} + +#if defined(CONFIG_COUNTER_CAPTURE) || defined(__DOXYGEN__) +__syscall int counter_capture_callback_set(const struct device *dev, + uint8_t chan, + uint32_t flags, + counter_capture_cb_t cb, + void *user_data); + +static inline int z_impl_counter_capture_callback_set(const struct device *dev, + uint8_t chan, + uint32_t flags, + counter_capture_cb_t cb, + void *user_data) +{ + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (!api->capture_callback_set) { + return -ENOTSUP; + } + + return api->capture_callback_set(dev, chan, flags, cb, user_data); +} + +/** + * @brief Enable capture on a channel. + * + * @param dev Pointer to the device structure for the driver instance. + * @param chan Channel ID. + * + * @retval 0 If successful. + * @retval Negative error code on failure + */ +__syscall int counter_capture_enable(const struct device *dev, + uint8_t chan); + +static inline int z_impl_counter_capture_enable(const struct device *dev, + uint8_t chan) +{ + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (!api->capture_enable) { + return -ENOTSUP; + } + + return api->capture_enable(dev, chan); +} + +/** + * @brief Disable capture on a channel. + * + * @param dev Pointer to the device structure for the driver instance. + * @param chan Channel ID. + * + * @retval 0 If successful. + * @retval Negative error code on failure + */ +__syscall int counter_capture_disable(const struct device *dev, + uint8_t chan); + +static inline int z_impl_counter_capture_disable(const struct device *dev, + uint8_t chan) +{ + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (!api->capture_disable) { + return -ENOTSUP; + } + + return api->capture_disable(dev, chan); +} +#endif + + /** * @brief Function to convert microseconds to ticks. * @@ -314,13 +468,63 @@ static inline uint32_t z_impl_counter_get_frequency(const struct device *dev) __syscall uint32_t counter_us_to_ticks(const struct device *dev, uint64_t us); static inline uint32_t z_impl_counter_us_to_ticks(const struct device *dev, - uint64_t us) + uint64_t us) { uint64_t ticks = (us * z_impl_counter_get_frequency(dev)) / USEC_PER_SEC; return (ticks > (uint64_t)UINT32_MAX) ? UINT32_MAX : ticks; } +/** + * @brief Function to convert microseconds to ticks with 64 bits. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[in] us Microseconds. + * + * @return Converted ticks. + */ +__syscall uint64_t counter_us_to_ticks_64(const struct device *dev, uint64_t us); + +static inline uint64_t z_impl_counter_us_to_ticks_64(const struct device *dev, + uint64_t us) +{ + return (us * z_impl_counter_get_frequency(dev)) / USEC_PER_SEC; +} + +/** + * @brief Function to convert nanoseconds to ticks. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[in] ns Nanoseconds. + * + * @return Converted ticks. Ticks will be saturated if exceed 32 bits. + */ +__syscall uint32_t counter_ns_to_ticks(const struct device *dev, uint64_t ns); + +static inline uint32_t z_impl_counter_ns_to_ticks(const struct device *dev, + uint64_t ns) +{ + uint64_t ticks = (ns * z_impl_counter_get_frequency(dev)) / NSEC_PER_SEC; + + return (ticks > (uint64_t)UINT32_MAX) ? UINT32_MAX : ticks; +} + +/** + * @brief Function to convert nanoseconds to ticks with 64 bits. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[in] ns Nanoseconds. + * + * @return Converted ticks. + */ +__syscall uint64_t counter_ns_to_ticks_64(const struct device *dev, uint64_t ns); + +static inline uint64_t z_impl_counter_ns_to_ticks_64(const struct device *dev, + uint64_t ns) +{ + return (ns * z_impl_counter_get_frequency(dev)) / NSEC_PER_SEC; +} + /** * @brief Function to convert ticks to microseconds. * @@ -332,11 +536,43 @@ static inline uint32_t z_impl_counter_us_to_ticks(const struct device *dev, __syscall uint64_t counter_ticks_to_us(const struct device *dev, uint32_t ticks); static inline uint64_t z_impl_counter_ticks_to_us(const struct device *dev, - uint32_t ticks) + uint32_t ticks) { return ((uint64_t)ticks * USEC_PER_SEC) / z_impl_counter_get_frequency(dev); } +/** + * @brief Function to convert ticks to nanoseconds. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[in] ticks Ticks. + * + * @return Converted nanoseconds. + */ +__syscall uint64_t counter_ticks_to_ns(const struct device *dev, uint32_t ticks); + +static inline uint64_t z_impl_counter_ticks_to_ns(const struct device *dev, + uint32_t ticks) +{ + return ((uint64_t)ticks * NSEC_PER_SEC) / z_impl_counter_get_frequency(dev); +} + +/** + * @brief Function to convert ticks to nanoseconds. + * + * @param[in] dev Pointer to the device structure for the driver instance. + * @param[in] ticks Ticks. + * + * @return Converted nanoseconds. + */ +__syscall uint64_t counter_ticks_to_ns_64(const struct device *dev, uint64_t ticks); + +static inline uint64_t z_impl_counter_ticks_to_ns_64(const struct device *dev, + uint64_t ticks) +{ + return (ticks * NSEC_PER_SEC) / z_impl_counter_get_frequency(dev); +} + /** * @brief Function to retrieve maximum top value that can be set. * @@ -454,6 +690,52 @@ static inline int z_impl_counter_reset(const struct device *dev) return api->reset(dev); } +/** + * @brief Set current counter value. + * @param dev Pointer to the device structure for the driver instance. + * @param ticks Tick value to set + * + * @retval 0 If successful. + * @retval Negative error code on failure getting the counter value + */ +__syscall int counter_set_value(const struct device *dev, uint32_t ticks); + +static inline int z_impl_counter_set_value(const struct device *dev, + uint32_t ticks) +{ + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (!api->set_value) { + return -ENOSYS; + } + + return api->set_value(dev, ticks); +} + +/** + * @brief Set current counter 64-bit value. + * @param dev Pointer to the device structure for the driver instance. + * @param ticks Tick value to set + * + * @retval 0 If successful. + * @retval Negative error code on failure getting the counter value + */ +__syscall int counter_set_value_64(const struct device *dev, uint64_t ticks); + +static inline int z_impl_counter_set_value_64(const struct device *dev, + uint64_t ticks) +{ + const struct counter_driver_api *api = + (struct counter_driver_api *)dev->api; + + if (!api->set_value_64) { + return -ENOSYS; + } + + return api->set_value_64(dev, ticks); +} + /** * @brief Set a single shot alarm on a channel. *