Skip to content

Commit aeb856e

Browse files
committed
drivers: counter: cc23x0: Add power management to LGPT
Add PM support for LGPT0, LGPT1, LGPT2 and LGPT3 to cc23x0 SoC. Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
1 parent fdd02c5 commit aeb856e

File tree

1 file changed

+99
-41
lines changed

1 file changed

+99
-41
lines changed

drivers/counter/counter_cc23x0_lgpt.c

Lines changed: 99 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <zephyr/kernel.h>
1313
#include <zephyr/drivers/clock_control.h>
1414
#include <zephyr/logging/log.h>
15+
#include <zephyr/pm/device.h>
16+
#include <zephyr/pm/policy.h>
1517

1618
#include <driverlib/clkctl.h>
1719
#include <inc/hw_lgpt.h>
@@ -23,11 +25,14 @@
2325

2426
LOG_MODULE_REGISTER(counter_cc23x0_lgpt, CONFIG_COUNTER_LOG_LEVEL);
2527

28+
#define LGPT_CLK_PRESCALE(pres) (((pres) + 1) << 8)
29+
2630
static void counter_cc23x0_lgpt_isr(const struct device *dev);
2731

2832
struct counter_cc23x0_lgpt_config {
2933
struct counter_config_info counter_info;
3034
uint32_t base;
35+
uint32_t clk_idx;
3136
uint32_t prescale;
3237
};
3338

@@ -36,6 +41,22 @@ struct counter_cc23x0_lgpt_data {
3641
struct counter_top_cfg target_cfg;
3742
};
3843

44+
static inline void lgpt_cc23x0_pm_policy_state_lock_get(void)
45+
{
46+
#ifdef CONFIG_PM_DEVICE
47+
pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
48+
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
49+
#endif
50+
}
51+
52+
static inline void lgpt_cc23x0_pm_policy_state_lock_put(void)
53+
{
54+
#ifdef CONFIG_PM_DEVICE
55+
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
56+
pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
57+
#endif
58+
}
59+
3960
static int counter_cc23x0_lgpt_get_value(const struct device *dev, uint32_t *ticks)
4061
{
4162
const struct counter_cc23x0_lgpt_config *config = dev->config;
@@ -221,6 +242,8 @@ static int counter_cc23x0_lgpt_start(const struct device *dev)
221242
{
222243
const struct counter_cc23x0_lgpt_config *config = dev->config;
223244

245+
lgpt_cc23x0_pm_policy_state_lock_get();
246+
224247
LOG_DBG("[START] LGPT base[%x]\n", config->base);
225248

226249
HWREG(config->base + LGPT_O_CTL) = LGPT_CTL_MODE_UP_PER;
@@ -240,9 +263,41 @@ static int counter_cc23x0_lgpt_stop(const struct device *dev)
240263
/* Set to 0 to stop timer */
241264
HWREG(config->base + LGPT_O_STARTCFG) = 0x0;
242265

266+
lgpt_cc23x0_pm_policy_state_lock_put();
267+
243268
return 0;
244269
}
245270

271+
static void counter_cc23x0_lgpt_init_common(const struct device *dev)
272+
{
273+
const struct counter_cc23x0_lgpt_config *config = dev->config;
274+
275+
HWREG(config->base + LGPT_O_TGT) = config->counter_info.max_top_value;
276+
HWREG(config->base + LGPT_O_PRECFG) = LGPT_CLK_PRESCALE(config->prescale);
277+
HWREG(EVTSVT_BASE + EVTSVT_O_LGPTSYNCSEL) = EVTSVT_LGPTSYNCSEL_PUBID_SYSTIM0;
278+
}
279+
280+
#ifdef CONFIG_PM_DEVICE
281+
282+
static int lgpt_cc23x0_pm_action(const struct device *dev, enum pm_device_action action)
283+
{
284+
const struct counter_cc23x0_lgpt_config *config = dev->config;
285+
286+
switch (action) {
287+
case PM_DEVICE_ACTION_SUSPEND:
288+
CLKCTLDisable(CLKCTL_BASE, config->clk_idx);
289+
return 0;
290+
case PM_DEVICE_ACTION_RESUME:
291+
CLKCTLEnable(CLKCTL_BASE, config->clk_idx);
292+
counter_cc23x0_lgpt_init_common(dev);
293+
return 0;
294+
default:
295+
return -ENOTSUP;
296+
}
297+
}
298+
299+
#endif /* CONFIG_PM_DEVICE */
300+
246301
static DEVICE_API(counter, cc23x0_lgpt_api) = {
247302
.start = counter_cc23x0_lgpt_start,
248303
.stop = counter_cc23x0_lgpt_stop,
@@ -255,48 +310,51 @@ static DEVICE_API(counter, cc23x0_lgpt_api) = {
255310
.get_freq = counter_cc23x0_lgpt_get_freq,
256311
};
257312

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; \
313+
#define LGPT_CC23X0_INIT_FUNC(inst) \
314+
static int counter_cc23x0_lgpt_init##inst(const struct device *dev) \
315+
{ \
316+
const struct counter_cc23x0_lgpt_config *config = dev->config; \
317+
\
318+
CLKCTLEnable(CLKCTL_BASE, config->clk_idx); \
319+
\
320+
IRQ_CONNECT(DT_INST_IRQN(inst), \
321+
DT_INST_IRQ(inst, priority), \
322+
counter_cc23x0_lgpt_isr, \
323+
DEVICE_DT_INST_GET(inst), \
324+
0); \
325+
\
326+
irq_enable(DT_INST_IRQN(inst)); \
327+
\
328+
counter_cc23x0_lgpt_init_common(dev); \
329+
\
330+
return 0; \
279331
}
280332

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);
333+
#define CC23X0_LGPT_INIT(inst) \
334+
\
335+
LGPT_CC23X0_INIT_FUNC(inst); \
336+
PM_DEVICE_DT_INST_DEFINE(inst, lgpt_cc23x0_pm_action); \
337+
\
338+
static const struct counter_cc23x0_lgpt_config cc23x0_lgpt_config_##inst = { \
339+
.counter_info = { \
340+
.max_top_value = DT_INST_PROP(inst, max_top_value), \
341+
.flags = COUNTER_CONFIG_INFO_COUNT_UP, \
342+
.channels = 3, \
343+
}, \
344+
.base = DT_INST_REG_ADDR(inst), \
345+
.clk_idx = CLKCTL_LGPT##inst, \
346+
.prescale = DT_INST_PROP(inst, clk_prescale), \
347+
}; \
348+
\
349+
static struct counter_cc23x0_lgpt_data cc23x0_lgpt_data_##inst; \
350+
\
351+
DEVICE_DT_INST_DEFINE(inst, \
352+
&counter_cc23x0_lgpt_init##inst, \
353+
PM_DEVICE_DT_INST_GET(inst), \
354+
&cc23x0_lgpt_data_##inst, \
355+
&cc23x0_lgpt_config_##inst, \
356+
POST_KERNEL, \
357+
CONFIG_COUNTER_INIT_PRIORITY, \
358+
&cc23x0_lgpt_api);
301359

302360
DT_INST_FOREACH_STATUS_OKAY(CC23X0_LGPT_INIT);

0 commit comments

Comments
 (0)