@@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(adc_cc23x0, CONFIG_ADC_LOG_LEVEL);
14
14
#include <zephyr/drivers/dma.h>
15
15
#include <zephyr/drivers/pinctrl.h>
16
16
#include <zephyr/irq.h>
17
+ #include <zephyr/pm/device.h>
18
+ #include <zephyr/pm/device_runtime.h>
19
+ #include <zephyr/pm/policy.h>
17
20
#include <zephyr/sys/util.h>
18
21
19
22
#include <driverlib/adc.h>
@@ -72,8 +75,27 @@ struct adc_cc23x0_data {
72
75
uint8_t ch_count ;
73
76
uint8_t mem_index ;
74
77
uint16_t * buffer ;
78
+ #ifdef CONFIG_PM_DEVICE
79
+ bool configured ;
80
+ #endif
75
81
};
76
82
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
+
77
99
static void adc_context_start_sampling (struct adc_context * ctx )
78
100
{
79
101
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)
102
124
103
125
int ret ;
104
126
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
+
105
133
ret = dma_config (cfg -> dma_dev , cfg -> dma_channel , & dma_cfg );
106
134
if (ret ) {
107
135
LOG_ERR ("Failed to configure DMA (%d)" , ret );
@@ -115,6 +143,8 @@ static void adc_context_start_sampling(struct adc_context *ctx)
115
143
data -> mem_index = 0 ;
116
144
#endif
117
145
146
+ adc_cc23x0_pm_policy_state_lock_get ();
147
+
118
148
ADCManualTrigger ();
119
149
}
120
150
@@ -136,6 +166,9 @@ static void adc_cc23x0_isr(const struct device *dev)
136
166
#endif
137
167
138
168
#ifdef CONFIG_ADC_CC23X0_DMA_DRIVEN
169
+ const struct adc_cc23x0_config * cfg = dev -> config ;
170
+ int ret ;
171
+
139
172
/*
140
173
* In DMA mode, do not compensate for the ADC internal gain with
141
174
* ADCAdjustValueForGain() function. To perform this compensation,
@@ -144,6 +177,14 @@ static void adc_cc23x0_isr(const struct device *dev)
144
177
*/
145
178
ADCClearInterrupt (ADC_INT_DMADONE );
146
179
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 ();
147
188
adc_context_on_sampling_done (& data -> ctx , dev );
148
189
#else
149
190
/*
@@ -174,6 +215,7 @@ static void adc_cc23x0_isr(const struct device *dev)
174
215
/* Trigger next conversion */
175
216
ADCManualTrigger ();
176
217
} else {
218
+ adc_cc23x0_pm_policy_state_lock_put ();
177
219
adc_context_on_sampling_done (& data -> ctx , dev );
178
220
}
179
221
#endif
@@ -462,6 +504,10 @@ static int adc_cc23x0_channel_setup(const struct device *dev,
462
504
return - EINVAL ;
463
505
}
464
506
507
+ #ifdef CONFIG_PM_DEVICE
508
+ data -> configured = true;
509
+ #endif
510
+
465
511
return 0 ;
466
512
}
467
513
@@ -490,13 +536,47 @@ static int adc_cc23x0_init(const struct device *dev)
490
536
if (!device_is_ready (cfg -> dma_dev )) {
491
537
return - ENODEV ;
492
538
}
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
+ }
493
545
#endif
494
546
495
547
adc_context_unlock_unconditionally (& data -> ctx );
496
548
497
549
return 0 ;
498
550
}
499
551
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
+
500
580
static DEVICE_API (adc , adc_cc23x0_driver_api ) = {
501
581
.channel_setup = adc_cc23x0_channel_setup ,
502
582
.read = adc_cc23x0_read ,
@@ -517,6 +597,7 @@ static DEVICE_API(adc, adc_cc23x0_driver_api) = {
517
597
518
598
#define CC23X0_ADC_INIT (n ) \
519
599
PINCTRL_DT_INST_DEFINE(n); \
600
+ PM_DEVICE_DT_INST_DEFINE(n, adc_cc23x0_pm_action); \
520
601
\
521
602
static void adc_cc23x0_cfg_func_##n(void) \
522
603
{ \
@@ -542,7 +623,7 @@ static DEVICE_API(adc, adc_cc23x0_driver_api) = {
542
623
\
543
624
DEVICE_DT_INST_DEFINE(n, \
544
625
&adc_cc23x0_init, \
545
- NULL, \
626
+ PM_DEVICE_DT_INST_GET(n), \
546
627
&adc_cc23x0_data_##n, \
547
628
&adc_cc23x0_config_##n, \
548
629
POST_KERNEL, \
0 commit comments