Skip to content

Commit 8c0863d

Browse files
committed
drivers: adc: cc23x0: Add power management
Add PM support to cc23x0 ADC module. Signed-off-by: Julien Panis <jpanis@baylibre.com>
1 parent ad4c3e3 commit 8c0863d

File tree

1 file changed

+82
-1
lines changed

1 file changed

+82
-1
lines changed

drivers/adc/adc_cc23x0.c

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(adc_cc23x0, CONFIG_ADC_LOG_LEVEL);
1414
#include <zephyr/drivers/dma.h>
1515
#include <zephyr/drivers/pinctrl.h>
1616
#include <zephyr/irq.h>
17+
#include <zephyr/pm/device.h>
18+
#include <zephyr/pm/device_runtime.h>
19+
#include <zephyr/pm/policy.h>
1720
#include <zephyr/sys/util.h>
1821

1922
#include <driverlib/adc.h>
@@ -72,8 +75,27 @@ struct adc_cc23x0_data {
7275
uint8_t ch_count;
7376
uint8_t mem_index;
7477
uint16_t *buffer;
78+
#ifdef CONFIG_PM_DEVICE
79+
bool configured;
80+
#endif
7581
};
7682

83+
static inline void adc_cc23x0_pm_policy_state_lock_get(void)
84+
{
85+
#ifdef CONFIG_PM_DEVICE
86+
pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
87+
pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
88+
#endif
89+
}
90+
91+
static inline void adc_cc23x0_pm_policy_state_lock_put(void)
92+
{
93+
#ifdef CONFIG_PM_DEVICE
94+
pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES);
95+
pm_policy_state_lock_put(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES);
96+
#endif
97+
}
98+
7799
static void adc_context_start_sampling(struct adc_context *ctx)
78100
{
79101
struct adc_cc23x0_data *data = CONTAINER_OF(ctx, struct adc_cc23x0_data, ctx);
@@ -102,6 +124,12 @@ static void adc_context_start_sampling(struct adc_context *ctx)
102124

103125
int ret;
104126

127+
ret = pm_device_runtime_get(cfg->dma_dev);
128+
if (ret) {
129+
LOG_ERR("Failed to resume DMA (%d)", ret);
130+
return;
131+
}
132+
105133
ret = dma_config(cfg->dma_dev, cfg->dma_channel, &dma_cfg);
106134
if (ret) {
107135
LOG_ERR("Failed to configure DMA (%d)", ret);
@@ -115,6 +143,8 @@ static void adc_context_start_sampling(struct adc_context *ctx)
115143
data->mem_index = 0;
116144
#endif
117145

146+
adc_cc23x0_pm_policy_state_lock_get();
147+
118148
ADCManualTrigger();
119149
}
120150

@@ -136,6 +166,9 @@ static void adc_cc23x0_isr(const struct device *dev)
136166
#endif
137167

138168
#ifdef CONFIG_ADC_CC23X0_DMA_DRIVEN
169+
const struct adc_cc23x0_config *cfg = dev->config;
170+
int ret;
171+
139172
/*
140173
* In DMA mode, do not compensate for the ADC internal gain with
141174
* ADCAdjustValueForGain() function. To perform this compensation,
@@ -144,6 +177,14 @@ static void adc_cc23x0_isr(const struct device *dev)
144177
*/
145178
ADCClearInterrupt(ADC_INT_DMADONE);
146179
LOG_DBG("DMA done");
180+
181+
ret = pm_device_runtime_put(cfg->dma_dev);
182+
if (ret) {
183+
LOG_ERR("Failed to suspend DMA (%d)", ret);
184+
return;
185+
}
186+
187+
adc_cc23x0_pm_policy_state_lock_put();
147188
adc_context_on_sampling_done(&data->ctx, dev);
148189
#else
149190
/*
@@ -174,6 +215,7 @@ static void adc_cc23x0_isr(const struct device *dev)
174215
/* Trigger next conversion */
175216
ADCManualTrigger();
176217
} else {
218+
adc_cc23x0_pm_policy_state_lock_put();
177219
adc_context_on_sampling_done(&data->ctx, dev);
178220
}
179221
#endif
@@ -462,6 +504,10 @@ static int adc_cc23x0_channel_setup(const struct device *dev,
462504
return -EINVAL;
463505
}
464506

507+
#ifdef CONFIG_PM_DEVICE
508+
data->configured = true;
509+
#endif
510+
465511
return 0;
466512
}
467513

@@ -490,13 +536,47 @@ static int adc_cc23x0_init(const struct device *dev)
490536
if (!device_is_ready(cfg->dma_dev)) {
491537
return -ENODEV;
492538
}
539+
540+
ret = pm_device_runtime_enable(cfg->dma_dev);
541+
if (ret) {
542+
LOG_ERR("Failed to enable DMA runtime PM");
543+
return ret;
544+
}
493545
#endif
494546

495547
adc_context_unlock_unconditionally(&data->ctx);
496548

497549
return 0;
498550
}
499551

552+
#ifdef CONFIG_PM_DEVICE
553+
554+
static int adc_cc23x0_pm_action(const struct device *dev, enum pm_device_action action)
555+
{
556+
struct adc_cc23x0_data *data = dev->data;
557+
558+
switch (action) {
559+
case PM_DEVICE_ACTION_SUSPEND:
560+
CLKCTLDisable(CLKCTL_BASE, CLKCTL_ADC0);
561+
return 0;
562+
case PM_DEVICE_ACTION_RESUME:
563+
CLKCTLEnable(CLKCTL_BASE, CLKCTL_ADC0);
564+
ADCEnableInterrupt(ADC_CC23X0_INT_MASK);
565+
566+
/* Restore context if needed */
567+
if (data->configured) {
568+
ADCSetSampleDuration(adc_cc23x0_clkdiv_to_field(data->clk_div),
569+
data->clk_cycles);
570+
}
571+
572+
return 0;
573+
default:
574+
return -ENOTSUP;
575+
}
576+
}
577+
578+
#endif /* CONFIG_PM_DEVICE */
579+
500580
static DEVICE_API(adc, adc_cc23x0_driver_api) = {
501581
.channel_setup = adc_cc23x0_channel_setup,
502582
.read = adc_cc23x0_read,
@@ -517,6 +597,7 @@ static DEVICE_API(adc, adc_cc23x0_driver_api) = {
517597

518598
#define CC23X0_ADC_INIT(n) \
519599
PINCTRL_DT_INST_DEFINE(n); \
600+
PM_DEVICE_DT_INST_DEFINE(n, adc_cc23x0_pm_action); \
520601
\
521602
static void adc_cc23x0_cfg_func_##n(void) \
522603
{ \
@@ -542,7 +623,7 @@ static DEVICE_API(adc, adc_cc23x0_driver_api) = {
542623
\
543624
DEVICE_DT_INST_DEFINE(n, \
544625
&adc_cc23x0_init, \
545-
NULL, \
626+
PM_DEVICE_DT_INST_GET(n), \
546627
&adc_cc23x0_data_##n, \
547628
&adc_cc23x0_config_##n, \
548629
POST_KERNEL, \

0 commit comments

Comments
 (0)