Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions boards/ti/sk_am62/sk_am62_am6254_a53.dts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
zephyr,sram = &ddr0;
};

aliases {
rtc = &counter_rtc0;
};

cpus {
cpu@0 {
status = "okay";
Expand Down Expand Up @@ -103,3 +107,11 @@
ti,fails-without-test-cd;
status = "disabled";
};

&main_rtc0 {
status = "okay";
};

&counter_rtc0 {
status = "okay";
};
1 change: 1 addition & 0 deletions drivers/counter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,4 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_WUT_MAX32 counter_max32_wu
zephyr_library_sources_ifdef(CONFIG_COUNTER_CC23X0_RTC counter_cc23x0_rtc.c)
zephyr_library_sources_ifdef(CONFIG_COUNTER_CC23X0_LGPT counter_cc23x0_lgpt.c)
zephyr_library_sources_ifdef(CONFIG_COUNTER_MSPM0_TIMER counter_mspm0_timer.c)
zephyr_library_sources_ifdef(CONFIG_COUNTER_TI_K3_RTC counter_k3_rtc.c)
16 changes: 16 additions & 0 deletions drivers/counter/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ config COUNTER_SHELL
help
Enable Shell Commands for Counter and Timer

config COUNTER_64BITS_FREQ
bool
help
Select this option if the counter driver should use 64-bits for frequency.
This is typically set by drivers that have frequencies greater than
4,294,967,295 Hz.

config COUNTER_64BITS_TICKS
bool
help
Select this option if the counter driver should use 64-bits for ticks.
This is typically set by drivers that require extended
tick ranges beyond the 32-bit limit.

module = COUNTER
module-str = counter
source "subsys/logging/Kconfig.template.log_config"
Expand Down Expand Up @@ -132,4 +146,6 @@ source "drivers/counter/Kconfig.cc23x0_lgpt"

source "drivers/counter/Kconfig.mspm0"

source "drivers/counter/Kconfig.k3_rtc_counter"

endif # COUNTER
2 changes: 2 additions & 0 deletions drivers/counter/Kconfig.ace
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@
config ACE_V1X_ART_COUNTER
bool "DSP ART Wall Clock for ACE V1X"
depends on DT_HAS_INTEL_ACE_ART_COUNTER_ENABLED
select COUNTER_64BITS_TICKS
default y
help
DSP ART Wall Clock used by ACE V1X.

config ACE_V1X_RTC_COUNTER
bool "DSP RTC Wall Clock for ACE V1X"
depends on DT_HAS_INTEL_ACE_RTC_COUNTER_ENABLED
select COUNTER_64BITS_TICKS
default y
help
DSP RTC Wall Clock used by ACE V1X.
1 change: 1 addition & 0 deletions drivers/counter/Kconfig.cc23x0_rtc
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ config COUNTER_CC23X0_RTC
default y
depends on DT_HAS_TI_CC23X0_RTC_ENABLED
depends on CC23X0_SYSTIM_TIMER
select COUNTER_64BITS_TICKS
help
Enable counter driver based on RTC timer for cc23x0
1 change: 1 addition & 0 deletions drivers/counter/Kconfig.esp32_tmr
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config COUNTER_TMR_ESP32
bool "ESP32 Counter Driver based on GP-Timers"
default y
depends on DT_HAS_ESPRESSIF_ESP32_COUNTER_ENABLED
select COUNTER_64BITS_TICKS
help
Enables the Counter driver API based on Espressif's General
Purpose Timers for ESP32 series devices.
9 changes: 9 additions & 0 deletions drivers/counter/Kconfig.k3_rtc_counter
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Texas Instruments Inc.
# SPDX-License-Identifier: Apache-2.0

config COUNTER_TI_K3_RTC
bool "RTC Counter Driver for TI K3 SoCs"
default y
depends on DT_HAS_TI_K3_RTC_COUNTER_ENABLED
help
Enable the RTC driver for TI K3 SoCs.
1 change: 1 addition & 0 deletions drivers/counter/Kconfig.stm32_rtc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ config COUNTER_RTC_STM32_SAVE_VALUE_BETWEEN_RESETS
config COUNTER_RTC_STM32_SUBSECONDS
bool "Use the subseconds as a basic tick."
depends on !SOC_SERIES_STM32F1X
select COUNTER_64BITS_TICKS
help
Use the subseconds as the basic time tick. It increases resolution
of the counter. The frequency of the time is RTC Source Clock divided
Expand Down
122 changes: 100 additions & 22 deletions drivers/counter/counter_esp32_tmr.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ typedef bool (*timer_isr_t)(void *);

struct counter_esp32_top_data {
counter_top_callback_t callback;
uint32_t ticks;
uint64_t ticks;
void *user_data;
bool auto_reload;
uint32_t guard_period;
uint64_t guard_period;
};

struct counter_esp32_config {
Expand All @@ -45,9 +45,10 @@ struct counter_esp32_config {
};

struct counter_esp32_data {
struct counter_alarm_cfg alarm_cfg;
struct counter_alarm_cfg_64 alarm_cfg;
counter_alarm_callback_t alarm_callback_32;
struct counter_esp32_top_data top_data;
uint32_t ticks;
uint64_t ticks;
uint32_t clock_src_hz;
timer_hal_context_t hal_ctx;
};
Expand Down Expand Up @@ -140,18 +141,18 @@ static int counter_esp32_get_value_64(const struct device *dev, uint64_t *ticks)
return 0;
}

static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
static int counter_esp32_set_alarm_64(const struct device *dev, uint8_t chan_id,
const struct counter_alarm_cfg_64 *alarm_cfg)
{
ARG_UNUSED(chan_id);
struct counter_esp32_data *data = dev->data;
bool absolute = alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE;
uint32_t ticks = alarm_cfg->ticks;
uint32_t top = data->top_data.ticks;
uint32_t max_rel_val = data->top_data.ticks;
uint64_t ticks = alarm_cfg->ticks;
uint64_t top = data->top_data.ticks;
uint64_t max_rel_val = data->top_data.ticks;
uint64_t now;
uint64_t target;
uint32_t diff;
uint64_t diff;
int err = 0;
bool irq_on_late = 0;

Expand All @@ -177,7 +178,7 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,

timer_ll_set_alarm_value(data->hal_ctx.dev, data->hal_ctx.timer_id, target);

diff = (alarm_cfg->ticks - (uint32_t)now);
diff = (alarm_cfg->ticks - now);
if (diff > max_rel_val) {
if (absolute) {
err = -ETIME;
Expand Down Expand Up @@ -216,21 +217,22 @@ static int counter_esp32_cancel_alarm(const struct device *dev, uint8_t chan_id)
return 0;
}

static int counter_esp32_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg)
static int counter_esp32_set_top_value_64(const struct device *dev,
const struct counter_top_cfg_64 *cfg)
{
const struct counter_esp32_config *config = dev->config;
struct counter_esp32_data *data = dev->data;
uint32_t now;
uint64_t now;

if (data->alarm_cfg.callback) {
return -EBUSY;
}

if (cfg->ticks > config->counter_info.max_top_value) {
if (cfg->ticks > config->counter_info.max_top_value_64) {
return -ENOTSUP;
}

counter_esp32_get_value(dev, &now);
counter_esp32_get_value_64(dev, &now);

if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) {
timer_hal_set_counter_value(&data->hal_ctx, 0);
Expand Down Expand Up @@ -267,7 +269,7 @@ static uint32_t counter_esp32_get_pending_int(const struct device *dev)
return timer_ll_get_intr_status(data->hal_ctx.dev);
}

static uint32_t counter_esp32_get_top_value(const struct device *dev)
static uint64_t counter_esp32_get_top_value_64(const struct device *dev)
{
struct counter_esp32_data *data = dev->data;

Expand All @@ -291,7 +293,7 @@ static int counter_esp32_reset(const struct device *dev)
return 0;
}

static uint32_t counter_esp32_get_guard_period(const struct device *dev, uint32_t flags)
static uint64_t counter_esp32_get_guard_period_64(const struct device *dev, uint32_t flags)
{
struct counter_esp32_data *data = dev->data;

Expand All @@ -300,7 +302,8 @@ static uint32_t counter_esp32_get_guard_period(const struct device *dev, uint32_
return data->top_data.guard_period;
}

static int counter_esp32_set_guard_period(const struct device *dev, uint32_t ticks, uint32_t flags)
static int counter_esp32_set_guard_period_64(const struct device *dev, uint64_t ticks,
uint32_t flags)
{
struct counter_esp32_data *data = dev->data;

Expand All @@ -314,31 +317,106 @@ static int counter_esp32_set_guard_period(const struct device *dev, uint32_t tic
return 0;
}

static int counter_esp32_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg)
{
struct counter_top_cfg_64 alarm_cfg_64 = {
.callback = cfg->callback,
.ticks = (uint64_t)cfg->ticks,
.user_data = cfg->user_data,
.flags = cfg->flags,
};

return counter_esp32_set_top_value_64(dev, &alarm_cfg_64);
}

static void counter_esp32_callback_32_trampoline(const struct device *dev,
uint8_t chan_id,
uint64_t ticks,
void *user_data)
{
struct counter_esp32_data *data = dev->data;

/* Safely call the original 32-bit callback */
data->alarm_callback_32(dev, chan_id, (uint32_t)ticks, user_data);
}

static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id,
const struct counter_alarm_cfg *alarm_cfg)
{
struct counter_esp32_data *data = dev->data;
struct counter_alarm_cfg_64 alarm_cfg_64 = {
.callback = counter_esp32_callback_32_trampoline,
.ticks = (uint64_t)alarm_cfg->ticks,
.user_data = alarm_cfg->user_data,
.flags = alarm_cfg->flags,
};

/* use trampoline function to handle the function pointer type difference */
data->alarm_callback_32 = alarm_cfg->callback;

return counter_esp32_set_alarm_64(dev, chan_id, &alarm_cfg_64);
}

static uint32_t counter_esp32_get_top_value(const struct device *dev)
{
struct counter_esp32_data *data = dev->data;

return (uint32_t)data->top_data.ticks;
}

static uint32_t counter_esp32_get_guard_period(const struct device *dev, uint32_t flags)
{
struct counter_esp32_data *data = dev->data;

ARG_UNUSED(flags);

return (uint32_t)data->top_data.guard_period;
}

static int counter_esp32_set_guard_period(const struct device *dev, uint32_t ticks, uint32_t flags)
{
struct counter_esp32_data *data = dev->data;

ARG_UNUSED(flags);

if (ticks > data->top_data.ticks) {
return -EINVAL;
}

data->top_data.guard_period = (uint64_t)ticks;
return 0;
}

static DEVICE_API(counter, counter_api) = {
.start = counter_esp32_start,
.stop = counter_esp32_stop,
.get_value = counter_esp32_get_value,
.reset = counter_esp32_reset,
.get_value_64 = counter_esp32_get_value_64,
.set_alarm = counter_esp32_set_alarm,
.set_alarm_64 = counter_esp32_set_alarm_64,
.cancel_alarm = counter_esp32_cancel_alarm,
.set_top_value = counter_esp32_set_top_value,
.set_top_value_64 = counter_esp32_set_top_value_64,
.get_pending_int = counter_esp32_get_pending_int,
.get_top_value = counter_esp32_get_top_value,
.get_top_value_64 = counter_esp32_get_top_value_64,
.get_freq = counter_esp32_get_freq,
.get_guard_period = counter_esp32_get_guard_period,
.get_guard_period_64 = counter_esp32_get_guard_period_64,
.set_guard_period = counter_esp32_set_guard_period,
.set_guard_period_64 = counter_esp32_set_guard_period_64,
};

static void counter_esp32_isr(void *arg)
{
const struct device *dev = (const struct device *)arg;
struct counter_esp32_data *data = dev->data;
counter_alarm_callback_t cb = data->alarm_cfg.callback;
counter_alarm_callback_64_t cb = data->alarm_cfg.callback;
void *cb_data = data->alarm_cfg.user_data;
uint32_t now;
uint64_t now;

counter_esp32_get_value(dev, &now);
counter_esp32_get_value_64(dev, &now);

if (cb) {
timer_ll_enable_intr(data->hal_ctx.dev,
Expand Down Expand Up @@ -374,7 +452,7 @@ static void counter_esp32_isr(void *arg)
static struct counter_esp32_data counter_data_##idx; \
\
static const struct counter_esp32_config counter_config_##idx = { \
.counter_info = {.max_top_value = UINT32_MAX, \
.counter_info = {.max_top_value_64 = UINT64_MAX, \
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
.channels = 1}, \
.config = \
Expand Down
2 changes: 2 additions & 0 deletions drivers/counter/counter_handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static inline int z_vrfy_counter_get_value(const struct device *dev,
}
#include <zephyr/syscalls/counter_get_value_mrsh.c>

#ifdef CONFIG_COUNTER_64BITS_TICKS
static inline int z_vrfy_counter_get_value_64(const struct device *dev,
uint64_t *ticks)
{
Expand All @@ -81,6 +82,7 @@ static inline int z_vrfy_counter_get_value_64(const struct device *dev,
return z_impl_counter_get_value_64((const struct device *)dev, ticks);
}
#include <zephyr/syscalls/counter_get_value_64_mrsh.c>
#endif /* CONFIG_COUNTER_64BITS_TICKS */

static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev,
uint8_t chan_id,
Expand Down
Loading
Loading