Skip to content

Commit 9bc3ee6

Browse files
msobkowskicarlescufi
authored andcommitted
drivers: counter: Add Ambiq counter driver
This commit adds Ambiq counter driver for Apollo4p SoCs. Signed-off-by: Mateusz Sierszulski <[email protected]> Signed-off-by: Maciej Sobkowski <[email protected]>
1 parent 04a7fcf commit 9bc3ee6

File tree

7 files changed

+227
-1
lines changed

7 files changed

+227
-1
lines changed

drivers/counter/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ zephyr_library()
1111

1212
zephyr_library_sources_ifdef(CONFIG_TIMER_TMR_CMSDK_APB timer_tmr_cmsdk_apb.c)
1313
zephyr_library_sources_ifdef(CONFIG_TIMER_DTMR_CMSDK_APB timer_dtmr_cmsdk_apb.c)
14+
zephyr_library_sources_ifdef(CONFIG_COUNTER_AMBIQ counter_ambiq_timer.c)
1415
zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_RTCC counter_gecko_rtcc.c)
1516
zephyr_library_sources_ifdef(CONFIG_COUNTER_GECKO_STIMER counter_gecko_stimer.c)
1617
zephyr_library_sources_ifdef(CONFIG_COUNTER_IMX_EPIT counter_imx_epit.c)

drivers/counter/Kconfig

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ module = COUNTER
2020
module-str = counter
2121
source "subsys/logging/Kconfig.template.log_config"
2222

23+
source "drivers/counter/Kconfig.ambiq"
24+
2325
source "drivers/counter/Kconfig.gecko"
2426

2527
source "drivers/counter/Kconfig.tmr_cmsdk_apb"

drivers/counter/Kconfig.ambiq

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
#
3+
# Copyright (c) 2023 Antmicro <www.antmicro.com>
4+
5+
6+
config COUNTER_AMBIQ
7+
bool "Ambiq Counter Driver"
8+
default y
9+
depends on DT_HAS_AMBIQ_COUNTER_ENABLED
10+
select AMBIQ_HAL
11+
select AMBIQ_HAL_USE_TIMER
12+
help
13+
Enables the Counter driver for Ambiq devices.

drivers/counter/counter_ambiq_timer.c

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/*
2+
* Copyright (c) 2023 Antmicro <www.antmicro.com>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ambiq_counter
8+
9+
#include <zephyr/drivers/counter.h>
10+
#include <zephyr/spinlock.h>
11+
#include <zephyr/kernel.h>
12+
#include <zephyr/device.h>
13+
#include <zephyr/logging/log.h>
14+
/* ambiq-sdk includes */
15+
#include <am_mcu_apollo.h>
16+
17+
LOG_MODULE_REGISTER(ambiq_counter, CONFIG_COUNTER_LOG_LEVEL);
18+
19+
static void counter_ambiq_isr(void *arg);
20+
21+
#define TIMER_IRQ (DT_INST_IRQN(0))
22+
23+
struct counter_ambiq_config {
24+
struct counter_config_info counter_info;
25+
};
26+
27+
struct counter_ambiq_data {
28+
counter_alarm_callback_t callback;
29+
void *user_data;
30+
};
31+
32+
static struct k_spinlock lock;
33+
34+
static int counter_ambiq_init(const struct device *dev)
35+
{
36+
am_hal_timer_config_t tc;
37+
38+
k_spinlock_key_t key = k_spin_lock(&lock);
39+
40+
am_hal_timer_default_config_set(&tc);
41+
tc.eInputClock = AM_HAL_TIMER_CLOCK_HFRC_DIV16;
42+
tc.eFunction = AM_HAL_TIMER_FN_UPCOUNT;
43+
tc.ui32PatternLimit = 0;
44+
45+
am_hal_timer_config(0, &tc);
46+
am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1));
47+
48+
k_spin_unlock(&lock, key);
49+
50+
NVIC_ClearPendingIRQ(TIMER_IRQ);
51+
IRQ_CONNECT(TIMER_IRQ, 0, counter_ambiq_isr, DEVICE_DT_INST_GET(0), 0);
52+
irq_enable(TIMER_IRQ);
53+
54+
return 0;
55+
}
56+
57+
static int counter_ambiq_start(const struct device *dev)
58+
{
59+
k_spinlock_key_t key = k_spin_lock(&lock);
60+
61+
am_hal_timer_start(0);
62+
63+
k_spin_unlock(&lock, key);
64+
65+
return 0;
66+
}
67+
68+
static int counter_ambiq_stop(const struct device *dev)
69+
{
70+
k_spinlock_key_t key = k_spin_lock(&lock);
71+
72+
am_hal_timer_stop(0);
73+
74+
k_spin_unlock(&lock, key);
75+
76+
return 0;
77+
}
78+
79+
static int counter_ambiq_get_value(const struct device *dev, uint32_t *ticks)
80+
{
81+
k_spinlock_key_t key = k_spin_lock(&lock);
82+
83+
*ticks = am_hal_timer_read(0);
84+
85+
k_spin_unlock(&lock, key);
86+
87+
return 0;
88+
}
89+
90+
static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id,
91+
const struct counter_alarm_cfg *alarm_cfg)
92+
{
93+
ARG_UNUSED(chan_id);
94+
struct counter_ambiq_data *data = dev->data;
95+
uint32_t now;
96+
97+
counter_ambiq_get_value(dev, &now);
98+
99+
k_spinlock_key_t key = k_spin_lock(&lock);
100+
101+
if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) {
102+
am_hal_timer_compare1_set(0, now + alarm_cfg->ticks);
103+
} else {
104+
am_hal_timer_compare1_set(0, alarm_cfg->ticks);
105+
}
106+
107+
data->user_data = alarm_cfg->user_data;
108+
data->callback = alarm_cfg->callback;
109+
110+
k_spin_unlock(&lock, key);
111+
112+
return 0;
113+
}
114+
115+
static int counter_ambiq_cancel_alarm(const struct device *dev, uint8_t chan_id)
116+
{
117+
ARG_UNUSED(chan_id);
118+
119+
k_spinlock_key_t key = k_spin_lock(&lock);
120+
121+
am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1));
122+
k_spin_unlock(&lock, key);
123+
124+
return 0;
125+
}
126+
127+
static int counter_ambiq_set_top_value(const struct device *dev, const struct counter_top_cfg *cfg)
128+
{
129+
const struct counter_ambiq_config *config = dev->config;
130+
131+
if (cfg->ticks != config->counter_info.max_top_value) {
132+
return -ENOTSUP;
133+
} else {
134+
return 0;
135+
}
136+
}
137+
138+
static uint32_t counter_ambiq_get_pending_int(const struct device *dev)
139+
{
140+
return 0;
141+
}
142+
143+
static uint32_t counter_ambiq_get_top_value(const struct device *dev)
144+
{
145+
const struct counter_ambiq_config *config = dev->config;
146+
147+
return config->counter_info.max_top_value;
148+
}
149+
150+
static const struct counter_driver_api counter_api = {
151+
.start = counter_ambiq_start,
152+
.stop = counter_ambiq_stop,
153+
.get_value = counter_ambiq_get_value,
154+
.set_alarm = counter_ambiq_set_alarm,
155+
.cancel_alarm = counter_ambiq_cancel_alarm,
156+
.set_top_value = counter_ambiq_set_top_value,
157+
.get_pending_int = counter_ambiq_get_pending_int,
158+
.get_top_value = counter_ambiq_get_top_value,
159+
};
160+
161+
static void counter_ambiq_isr(void *arg)
162+
{
163+
const struct device *dev = (const struct device *)arg;
164+
struct counter_ambiq_data *data = dev->data;
165+
uint32_t now = 0;
166+
167+
am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1));
168+
counter_ambiq_get_value(dev, &now);
169+
170+
if (data->callback) {
171+
data->callback(dev, 0, now, data->user_data);
172+
}
173+
}
174+
175+
#define AMBIQ_COUNTER_INIT(idx) \
176+
\
177+
static struct counter_ambiq_data counter_data_##idx; \
178+
\
179+
static const struct counter_ambiq_config counter_config_##idx = { \
180+
.counter_info = {.max_top_value = UINT32_MAX, \
181+
.freq = 6000000, \
182+
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
183+
.channels = 1}, \
184+
}; \
185+
\
186+
DEVICE_DT_INST_DEFINE(idx, counter_ambiq_init, NULL, &counter_data_##idx, \
187+
&counter_config_##idx, PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \
188+
&counter_api);
189+
190+
DT_INST_FOREACH_STATUS_OKAY(AMBIQ_COUNTER_INIT);
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright (c) 2023 Antmicro <www.antmicro.com>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: Ambiq Timer/Counter
5+
6+
compatible: "ambiq,counter"
7+
8+
include: base.yaml
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
interrupts:
15+
required: true

modules/hal_ambiq/Kconfig

+5
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,9 @@ config AMBIQ_HAL_USE_STIMER
2020
help
2121
Use the STIMER driver from Ambiq HAL
2222

23+
config AMBIQ_HAL_USE_TIMER
24+
bool
25+
help
26+
Use the TIMER driver from Ambiq HAL
27+
2328
endif # AMBIQ_HAL

west.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ manifest:
142142
groups:
143143
- hal
144144
- name: hal_ambiq
145-
revision: c8203b6fc752e51fb3cb1e98441f392cc4493623
145+
revision: 5079b0096479a5630b91d38a891c2db1693faa2a
146146
path: modules/hal/ambiq
147147
groups:
148148
- hal

0 commit comments

Comments
 (0)