Skip to content

Commit cfe7a58

Browse files
bogdanovskartben
authored andcommitted
drivers: counter: Add support for cc23x0 LGPT
Add support for LGPT0, LGPT1, LGPT2 and LGPT3 to cc23x0 SoC. Signed-off-by: Stoyan Bogdanov <[email protected]>
1 parent fc56305 commit cfe7a58

File tree

5 files changed

+340
-0
lines changed

5 files changed

+340
-0
lines changed

drivers/counter/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,4 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_REALTEK_RTS5912 counter_realtek_
6060
zephyr_library_sources_ifdef(CONFIG_COUNTER_NEORV32_GPTMR counter_neorv32_gptmr.c)
6161
zephyr_library_sources_ifdef(CONFIG_COUNTER_WUT_MAX32 counter_max32_wut.c)
6262
zephyr_library_sources_ifdef(CONFIG_COUNTER_CC23X0_RTC counter_cc23x0_rtc.c)
63+
zephyr_library_sources_ifdef(CONFIG_COUNTER_CC23X0_LGPT counter_cc23x0_lgpt.c)

drivers/counter/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,6 @@ source "drivers/counter/Kconfig.max32_wut"
118118

119119
source "drivers/counter/Kconfig.cc23x0_rtc"
120120

121+
source "drivers/counter/Kconfig.cc23x0_lgpt"
122+
121123
endif # COUNTER

drivers/counter/Kconfig.cc23x0_lgpt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2024 BayLibre, SAS
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config COUNTER_CC23X0_LGPT
5+
bool "CC23x0 Counter driver based on the LGPT Timer"
6+
default y
7+
depends on DT_HAS_TI_CC23X0_LGPT_ENABLED
8+
help
9+
Enable counter driver based on LGPT timer for cc23x0

drivers/counter/counter_cc23x0_lgpt.c

Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/*
2+
* Copyright (c) 2024 BayLibre, SAS
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ti_cc23x0_lgpt
8+
9+
#include <zephyr/device.h>
10+
#include <zephyr/drivers/counter.h>
11+
#include <zephyr/spinlock.h>
12+
#include <zephyr/kernel.h>
13+
#include <zephyr/drivers/clock_control.h>
14+
#include <zephyr/logging/log.h>
15+
16+
#include <driverlib/clkctl.h>
17+
#include <inc/hw_lgpt.h>
18+
#include <inc/hw_lgpt1.h>
19+
#include <inc/hw_lgpt3.h>
20+
#include <inc/hw_types.h>
21+
#include <inc/hw_evtsvt.h>
22+
#include <inc/hw_memmap.h>
23+
24+
LOG_MODULE_REGISTER(counter_cc23x0_lgpt, CONFIG_COUNTER_LOG_LEVEL);
25+
26+
static void counter_cc23x0_lgpt_isr(const struct device *dev);
27+
28+
struct counter_cc23x0_lgpt_config {
29+
struct counter_config_info counter_info;
30+
uint32_t base;
31+
uint32_t prescale;
32+
};
33+
34+
struct counter_cc23x0_lgpt_data {
35+
struct counter_alarm_cfg alarm_cfg[3];
36+
struct counter_top_cfg target_cfg;
37+
};
38+
39+
static int counter_cc23x0_lgpt_get_value(const struct device *dev, uint32_t *ticks)
40+
{
41+
const struct counter_cc23x0_lgpt_config *config = dev->config;
42+
43+
*ticks = HWREG(config->base + LGPT_O_CNTR);
44+
45+
return 0;
46+
}
47+
48+
static void counter_cc23x0_lgpt_isr(const struct device *dev)
49+
{
50+
const struct counter_cc23x0_lgpt_config *config = dev->config;
51+
const struct counter_cc23x0_lgpt_data *data = dev->data;
52+
uint32_t reg_ris = HWREG(config->base + LGPT_O_RIS);
53+
uint32_t reg_mis = HWREG(config->base + LGPT_O_MIS);
54+
uint32_t isr = reg_ris & reg_mis;
55+
56+
HWREG(config->base + LGPT_O_ICLR) |= reg_mis;
57+
HWREG(config->base + LGPT_O_IMCLR) |= reg_mis;
58+
59+
LOG_DBG("\nISR -> LGPT[%x] RIS[%x] MIS[%x] ISR[%x]\n", config->base, reg_ris, reg_mis, isr);
60+
61+
if (isr & LGPT_RIS_TGT) {
62+
LOG_DBG("LGPT_RIS_TGT\n");
63+
if (data->target_cfg.callback) {
64+
data->target_cfg.callback(dev, data->target_cfg.user_data);
65+
}
66+
}
67+
if (isr & LGPT_RIS_ZERO) {
68+
LOG_DBG("LGPT_RIS_ZERO\n");
69+
}
70+
if (isr & LGPT_RIS_DBLTRANS) {
71+
LOG_DBG("LGPT_RIS_DBLTRANS\n");
72+
}
73+
if (isr & LGPT_RIS_CNTRCHNG) {
74+
LOG_DBG("LGPT_RIS_CNTRCHNG\n");
75+
}
76+
if (isr & LGPT_RIS_DIRCHNG) {
77+
LOG_DBG("LGPT_RIS_DIRCHNG\n");
78+
}
79+
if (isr & LGPT_RIS_IDX) {
80+
LOG_DBG("LGPT_RIS_IDX\n");
81+
}
82+
if (isr & LGPT_RIS_FAULT) {
83+
LOG_DBG("LGPT_RIS_FAULT\n");
84+
}
85+
if (isr & LGPT_RIS_C0CC) {
86+
LOG_DBG("LGPT_RIS_C0CC\n");
87+
if (data->alarm_cfg[0].callback) {
88+
data->alarm_cfg[0].callback(dev, 0, HWREG(config->base + LGPT_O_CNTR),
89+
data->alarm_cfg[0].user_data);
90+
}
91+
}
92+
if (isr & LGPT_RIS_C1CC) {
93+
LOG_DBG("LGPT_RIS_C1CC\n");
94+
if (data->alarm_cfg[1].callback) {
95+
data->alarm_cfg[1].callback(dev, 1, HWREG(config->base + LGPT_O_CNTR),
96+
data->alarm_cfg[1].user_data);
97+
}
98+
}
99+
if (isr & LGPT_RIS_C2CC) {
100+
LOG_DBG("LGPT_RIS_C2CC\n");
101+
if (data->alarm_cfg[2].callback) {
102+
data->alarm_cfg[2].callback(dev, 2, HWREG(config->base + LGPT_O_CNTR),
103+
data->alarm_cfg[2].user_data);
104+
}
105+
}
106+
}
107+
108+
static uint32_t counter_cc23x0_lgpt_get_freq(const struct device *dev)
109+
{
110+
const struct counter_cc23x0_lgpt_config *config = dev->config;
111+
112+
return (DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) / config->prescale);
113+
}
114+
115+
static int counter_cc23x0_lgpt_set_alarm(const struct device *dev, uint8_t chan_id,
116+
const struct counter_alarm_cfg *alarm_cfg)
117+
{
118+
const struct counter_cc23x0_lgpt_config *config = dev->config;
119+
struct counter_cc23x0_lgpt_data *data = dev->data;
120+
121+
if (alarm_cfg->ticks > config->counter_info.max_top_value) {
122+
LOG_ERR("Ticks out of range\n");
123+
return -EINVAL;
124+
}
125+
126+
if (chan_id == 0) {
127+
HWREG(config->base + LGPT_O_IMASK) |= 0x100;
128+
HWREG(config->base + LGPT_O_C0CC) = alarm_cfg->ticks;
129+
HWREG(config->base + LGPT_O_C0CFG) = 0x9D;
130+
} else if (chan_id == 1) {
131+
HWREG(config->base + LGPT_O_IMASK) |= 0x200;
132+
HWREG(config->base + LGPT_O_C1CC) = alarm_cfg->ticks;
133+
HWREG(config->base + LGPT_O_C1CFG) = 0x9D;
134+
} else if (chan_id == 2) {
135+
HWREG(config->base + LGPT_O_IMASK) |= 0x400;
136+
HWREG(config->base + LGPT_O_C2CC) = alarm_cfg->ticks;
137+
HWREG(config->base + LGPT_O_C2CFG) = 0x9D;
138+
} else {
139+
LOG_ERR("Invalid chan ID\n");
140+
return -ENOTSUP;
141+
}
142+
143+
data->alarm_cfg[chan_id].flags = 0;
144+
data->alarm_cfg[chan_id].ticks = alarm_cfg->ticks;
145+
data->alarm_cfg[chan_id].callback = alarm_cfg->callback;
146+
data->alarm_cfg[chan_id].user_data = alarm_cfg->user_data;
147+
148+
return 0;
149+
}
150+
151+
static int counter_cc23x0_lgpt_cancel_alarm(const struct device *dev, uint8_t chan_id)
152+
{
153+
const struct counter_cc23x0_lgpt_config *config = dev->config;
154+
struct counter_cc23x0_lgpt_data *data = dev->data;
155+
156+
if (chan_id == 0) {
157+
HWREG(config->base + LGPT_O_IMCLR) |= 0x100;
158+
HWREG(config->base + LGPT_O_C0CC) = 0x0;
159+
HWREG(config->base + LGPT_O_C0CFG) = 0x0;
160+
} else if (chan_id == 1) {
161+
HWREG(config->base + LGPT_O_IMCLR) |= 0x200;
162+
HWREG(config->base + LGPT_O_C1CC) = 0;
163+
HWREG(config->base + LGPT_O_C1CFG) = 0;
164+
} else if (chan_id == 2) {
165+
HWREG(config->base + LGPT_O_IMCLR) |= 0x400;
166+
HWREG(config->base + LGPT_O_C2CC) = 0;
167+
HWREG(config->base + LGPT_O_C2CFG) = 0;
168+
} else {
169+
LOG_ERR("Invalid chan ID\n");
170+
return -ENOTSUP;
171+
}
172+
173+
data->alarm_cfg[chan_id].flags = 0;
174+
data->alarm_cfg[chan_id].ticks = 0;
175+
data->alarm_cfg[chan_id].callback = NULL;
176+
data->alarm_cfg[chan_id].user_data = NULL;
177+
178+
return 0;
179+
}
180+
181+
static uint32_t counter_cc23x0_lgpt_get_top_value(const struct device *dev)
182+
{
183+
const struct counter_cc23x0_lgpt_config *config = dev->config;
184+
185+
return HWREG(config->base + LGPT_O_TGT);
186+
}
187+
188+
static int counter_cc23x0_lgpt_set_top_value(const struct device *dev,
189+
const struct counter_top_cfg *cfg)
190+
{
191+
const struct counter_cc23x0_lgpt_config *config = dev->config;
192+
struct counter_cc23x0_lgpt_data *data = dev->data;
193+
int ret = 0;
194+
195+
/* If not running set new top value */
196+
if (HWREG(config->base + LGPT_O_STARTCFG) == 0) {
197+
HWREG(config->base + LGPT_O_TGT) = config->counter_info.max_top_value;
198+
199+
HWREG(config->base + LGPT_O_IMASK) |= 0x001;
200+
HWREG(config->base + LGPT_O_TGT) = cfg->ticks;
201+
202+
data->target_cfg.flags = 0;
203+
data->target_cfg.ticks = cfg->ticks;
204+
data->target_cfg.callback = cfg->callback;
205+
data->target_cfg.user_data = cfg->user_data;
206+
} else {
207+
ret = -EBUSY;
208+
}
209+
210+
return ret;
211+
}
212+
213+
static uint32_t counter_cc23x0_lgpt_get_pending_int(const struct device *dev)
214+
{
215+
const struct counter_cc23x0_lgpt_config *config = dev->config;
216+
217+
return HWREG(config->base + LGPT_O_RIS) & HWREG(config->base + LGPT_O_MIS) ? 1 : 0;
218+
}
219+
220+
static int counter_cc23x0_lgpt_start(const struct device *dev)
221+
{
222+
const struct counter_cc23x0_lgpt_config *config = dev->config;
223+
224+
LOG_DBG("[START] LGPT base[%x]\n", config->base);
225+
226+
HWREG(config->base + LGPT_O_CTL) = LGPT_CTL_MODE_UP_PER;
227+
228+
/* Set to 1 to start timer */
229+
HWREG(config->base + LGPT_O_STARTCFG) = 0x1;
230+
231+
return 0;
232+
}
233+
234+
static int counter_cc23x0_lgpt_stop(const struct device *dev)
235+
{
236+
const struct counter_cc23x0_lgpt_config *config = dev->config;
237+
238+
LOG_DBG("[STOP] LGPT base[%x]\n", config->base);
239+
240+
/* Set to 0 to stop timer */
241+
HWREG(config->base + LGPT_O_STARTCFG) = 0x0;
242+
243+
return 0;
244+
}
245+
246+
static const struct counter_driver_api cc23x0_lgpt_api = {
247+
.start = counter_cc23x0_lgpt_start,
248+
.stop = counter_cc23x0_lgpt_stop,
249+
.get_value = counter_cc23x0_lgpt_get_value,
250+
.set_alarm = counter_cc23x0_lgpt_set_alarm,
251+
.cancel_alarm = counter_cc23x0_lgpt_cancel_alarm,
252+
.get_top_value = counter_cc23x0_lgpt_get_top_value,
253+
.set_top_value = counter_cc23x0_lgpt_set_top_value,
254+
.get_pending_int = counter_cc23x0_lgpt_get_pending_int,
255+
.get_freq = counter_cc23x0_lgpt_get_freq,
256+
};
257+
258+
#define LGPT_CLK_PRESCALE(pres) ((pres + 1) << 8)
259+
260+
#define LGPT_CC23X0_INIT_FUNC(inst) \
261+
static int counter_cc23x0_lgpt_init##inst(const struct device *dev) \
262+
{ \
263+
const struct counter_cc23x0_lgpt_config *config = dev->config; \
264+
\
265+
CLKCTLEnable(CLKCTL_BASE, CLKCTL_LGPT##inst); \
266+
\
267+
IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \
268+
counter_cc23x0_lgpt_isr, DEVICE_DT_INST_GET(inst), 0); \
269+
\
270+
irq_enable(DT_INST_IRQN(inst)); \
271+
\
272+
HWREG(config->base + LGPT_O_TGT) = config->counter_info.max_top_value; \
273+
\
274+
HWREG(config->base + LGPT_O_PRECFG) = LGPT_CLK_PRESCALE(config->prescale); \
275+
\
276+
HWREG(EVTSVT_BASE + EVTSVT_O_LGPTSYNCSEL) = EVTSVT_LGPTSYNCSEL_PUBID_SYSTIM0; \
277+
\
278+
return 0; \
279+
}
280+
281+
#define CC23X0_LGPT_INIT(inst) \
282+
\
283+
LGPT_CC23X0_INIT_FUNC(inst); \
284+
\
285+
static const struct counter_cc23x0_lgpt_config cc23x0_lgpt_config_##inst = { \
286+
.counter_info = \
287+
{ \
288+
.max_top_value = DT_INST_PROP(inst, max_top_value), \
289+
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
290+
.channels = 3, \
291+
}, \
292+
.base = DT_INST_REG_ADDR(inst), \
293+
.prescale = DT_INST_PROP(inst, clk_prescale), \
294+
}; \
295+
\
296+
static struct counter_cc23x0_lgpt_data cc23x0_lgpt_data_##inst; \
297+
\
298+
DEVICE_DT_INST_DEFINE(inst, &counter_cc23x0_lgpt_init##inst, NULL, \
299+
&cc23x0_lgpt_data_##inst, &cc23x0_lgpt_config_##inst, POST_KERNEL, \
300+
CONFIG_COUNTER_INIT_PRIORITY, &cc23x0_lgpt_api);
301+
302+
DT_INST_FOREACH_STATUS_OKAY(CC23X0_LGPT_INIT);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) Copyright (c) 2024 BayLibre, SAS
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: CC23x0 LGPT counter driver
5+
6+
properties:
7+
freq:
8+
type: int
9+
description: clock frequency (only used for external clock sources)
10+
11+
interrupts:
12+
required: true
13+
14+
clk-prescale:
15+
type: int
16+
required: true
17+
description: Counter clock prescale
18+
19+
max-top-value:
20+
type: int
21+
required: true
22+
description: Max allowed value for counter
23+
24+
compatible: "ti,cc23x0-lgpt"
25+
26+
include: base.yaml

0 commit comments

Comments
 (0)