99#include <zephyr/drivers/adc.h>
1010#include <zephyr/drivers/clock_control.h>
1111#include <zephyr/drivers/clock_control/clock_control_silabs.h>
12+ #include <zephyr/drivers/dma.h>
13+ #include <zephyr/drivers/dma/dma_silabs_ldma.h>
1214#include <zephyr/drivers/pinctrl.h>
1315#include <zephyr/logging/log.h>
1416#include <zephyr/pm/device.h>
@@ -45,6 +47,14 @@ LOG_MODULE_REGISTER(iadc, CONFIG_ADC_LOG_LEVEL);
4547#define IADC_PORT_MASK 0xF0
4648#define IADC_PIN_MASK 0x0F
4749
50+ struct iadc_dma_channel {
51+ const struct device * dma_dev ;
52+ struct dma_block_config blk_cfg ;
53+ struct dma_config dma_cfg ;
54+ int dma_channel ;
55+ bool enabled ;
56+ };
57+
4858struct iadc_chan_conf {
4959 sl_hal_iadc_analog_gain_t gain ;
5060 sl_hal_iadc_voltage_reference_t reference ;
@@ -60,6 +70,7 @@ struct iadc_data {
6070 const struct device * dev ;
6171 struct adc_context ctx ;
6272 struct iadc_chan_conf chan_conf [SL_HAL_IADC_CHANNEL_ID_MAX ];
73+ struct iadc_dma_channel dma ;
6374 uint8_t adc_config_count ; /* Number of ADC configs created (max 2) */
6475 uint32_t clock_rate ;
6576 uint32_t channels ;
@@ -119,6 +130,104 @@ static void iadc_configure_scan_table_entry(sl_hal_iadc_scan_table_entry_t *entr
119130 };
120131}
121132
133+ #ifdef CONFIG_ADC_SILABS_IADC_DMA
134+ static int iadc_dma_init (const struct device * dev )
135+ {
136+ const struct iadc_config * config = dev -> config ;
137+ struct iadc_data * data = dev -> data ;
138+ struct iadc_dma_channel * dma = & data -> dma ;
139+
140+ if (!dma -> dma_dev ) {
141+ return 0 ;
142+ }
143+
144+ if (!device_is_ready (dma -> dma_dev )) {
145+ LOG_ERR ("DMA device not ready" );
146+ return - ENODEV ;
147+ }
148+
149+ dma -> dma_channel = dma_request_channel (dma -> dma_dev , NULL );
150+ if (dma -> dma_channel < 0 ) {
151+ LOG_ERR ("Failed to request DMA channel" );
152+ return - ENODEV ;
153+ }
154+
155+ memset (& dma -> blk_cfg , 0 , sizeof (dma -> blk_cfg ));
156+ dma -> blk_cfg .source_address = (uintptr_t )& (config -> base )-> SCANFIFODATA ;
157+ dma -> blk_cfg .source_addr_adj = DMA_ADDR_ADJ_NO_CHANGE ;
158+ dma -> blk_cfg .dest_addr_adj = DMA_ADDR_ADJ_INCREMENT ;
159+ dma -> dma_cfg .complete_callback_en = 1 ;
160+ dma -> dma_cfg .channel_priority = 3 ;
161+ dma -> dma_cfg .channel_direction = PERIPHERAL_TO_MEMORY ;
162+ dma -> dma_cfg .head_block = & dma -> blk_cfg ;
163+ dma -> dma_cfg .user_data = data ;
164+
165+ return 0 ;
166+ }
167+
168+ static int iadc_dma_start (const struct device * dev )
169+ {
170+ struct iadc_data * data = dev -> data ;
171+ struct iadc_dma_channel * dma = & data -> dma ;
172+ int ret ;
173+
174+ if (!dma -> dma_dev ) {
175+ return - ENODEV ;
176+ }
177+
178+ if (dma -> enabled ) {
179+ return - EBUSY ;
180+ }
181+
182+ ret = dma_config (dma -> dma_dev , dma -> dma_channel , & dma -> dma_cfg );
183+ if (ret ) {
184+ LOG_ERR ("DMA config error: %d" , ret );
185+ return ret ;
186+ }
187+
188+ dma -> enabled = true;
189+
190+ ret = dma_start (dma -> dma_dev , dma -> dma_channel );
191+ if (ret ) {
192+ LOG_ERR ("DMA start error: %d" , ret );
193+ dma -> enabled = false;
194+ return ret ;
195+ }
196+
197+ return 0 ;
198+ }
199+
200+ static void iadc_dma_stop (const struct device * dev )
201+ {
202+ struct iadc_data * data = dev -> data ;
203+ struct iadc_dma_channel * dma = & data -> dma ;
204+
205+ if (!dma -> enabled ) {
206+ return ;
207+ }
208+
209+ dma_stop (dma -> dma_dev , dma -> dma_channel );
210+
211+ dma -> enabled = false;
212+ }
213+
214+ static void iadc_dma_cb (const struct device * dma_dev , void * user_data , uint32_t channel , int status )
215+ {
216+ struct iadc_data * data = user_data ;
217+ const struct device * dev = data -> dev ;
218+
219+ if (status < 0 ) {
220+ LOG_ERR ("DMA transfer error: %d" , status );
221+ adc_context_complete (& data -> ctx , status );
222+ return ;
223+ }
224+
225+ iadc_dma_stop (dev );
226+
227+ adc_context_on_sampling_done (& data -> ctx , dev );
228+ }
229+ #endif /* CONFIG_ADC_SILABS_IADC_DMA */
230+
122231/* Oversampling and resolution are common for both ADC configs
123232 * because they are not configurable per channel inside a ADC
124233 * sequence and are common for a sequence.
@@ -149,8 +258,28 @@ static int iadc_set_config(const struct device *dev)
149258 uint32_t channels ;
150259 int res ;
151260
261+ if (data -> dma .dma_dev ) {
262+ scan_init .data_valid_level = _IADC_SCANFIFOCFG_DVL_VALID1 ;
263+ /* Only needed to wake up DMA if EM is 2/3 */
264+ scan_init .fifo_dma_wakeup = true;
265+ }
266+
152267 data -> adc_config_count = 0 ;
153268
269+ if (data -> dma .dma_dev ) {
270+ if (data -> alignment == _IADC_SCANFIFOCFG_ALIGNMENT_RIGHT20 ) {
271+ data -> dma .dma_cfg .source_data_size = 4 ;
272+ data -> dma .dma_cfg .dest_data_size = 4 ;
273+ data -> dma .dma_cfg .source_burst_length = 4 ;
274+ data -> dma .dma_cfg .dest_burst_length = 4 ;
275+ } else {
276+ data -> dma .dma_cfg .source_data_size = 2 ;
277+ data -> dma .dma_cfg .dest_data_size = 2 ;
278+ data -> dma .dma_cfg .source_burst_length = 2 ;
279+ data -> dma .dma_cfg .dest_burst_length = 2 ;
280+ }
281+ }
282+
154283 channels = data -> channels ;
155284
156285 /*
@@ -340,6 +469,11 @@ static int start_read(const struct device *dev, const struct adc_sequence *seque
340469 data -> buffer = sequence -> buffer ;
341470 data -> active_channels = channel_count ;
342471
472+ if (data -> dma .dma_dev ) {
473+ data -> dma .blk_cfg .dest_address = (uintptr_t )data -> buffer ;
474+ data -> dma .blk_cfg .block_size = channel_count * data -> data_size ;
475+ }
476+
343477 data -> channels = sequence -> channels ;
344478
345479 res = iadc_set_config (data -> dev );
@@ -357,9 +491,19 @@ static int start_read(const struct device *dev, const struct adc_sequence *seque
357491static void iadc_start_scan (const struct device * dev )
358492{
359493 const struct iadc_config * config = dev -> config ;
494+ __maybe_unused struct iadc_data * data = dev -> data ;
360495 IADC_TypeDef * iadc = (IADC_TypeDef * )config -> base ;
361496
497+ #ifdef CONFIG_ADC_SILABS_IADC_DMA
498+ if (data -> dma .dma_dev ) {
499+ data -> dma .blk_cfg .dest_address = (uintptr_t )data -> buffer ;
500+ iadc_dma_start (dev );
501+ } else {
502+ sl_hal_iadc_enable_interrupts (iadc , IADC_IEN_SCANTABLEDONE );
503+ }
504+ #else
362505 sl_hal_iadc_enable_interrupts (iadc , IADC_IEN_SCANTABLEDONE );
506+ #endif
363507
364508 sl_hal_iadc_start_scan (iadc );
365509}
@@ -569,6 +713,13 @@ static int iadc_init(const struct device *dev)
569713 return ret ;
570714 }
571715
716+ #ifdef CONFIG_ADC_SILABS_IADC_DMA
717+ ret = iadc_dma_init (dev );
718+ if (ret < 0 ) {
719+ data -> dma .dma_dev = NULL ;
720+ }
721+ #endif
722+
572723 config -> irq_cfg_func ();
573724
574725 adc_context_unlock_unconditionally (& data -> ctx );
@@ -585,6 +736,17 @@ static DEVICE_API(adc, iadc_api) = {
585736 .ref_internal = SL_HAL_IADC_DEFAULT_VREF ,
586737};
587738
739+ #ifdef CONFIG_ADC_SILABS_IADC_DMA
740+ #define IADC_DMA_CHANNEL_INIT (n ) \
741+ .dma.dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR(n)), \
742+ .dma.dma_cfg.dma_slot = SILABS_LDMA_REQSEL_TO_SLOT(DT_INST_DMAS_CELL_BY_IDX(n, 0, slot)), \
743+ .dma.dma_cfg.dma_callback = iadc_dma_cb,
744+ #define IADC_DMA_CHANNEL (n ) \
745+ COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), (IADC_DMA_CHANNEL_INIT(n)), ())
746+ #else
747+ #define IADC_DMA_CHANNEL (n )
748+ #endif
749+
588750#define IADC_INIT (n ) \
589751 PINCTRL_DT_INST_DEFINE(n); \
590752 PM_DEVICE_DT_INST_DEFINE(n, iadc_pm_action); \
@@ -603,6 +765,7 @@ static DEVICE_API(adc, iadc_api) = {
603765 ADC_CONTEXT_INIT_TIMER(iadc_data_##n, ctx), \
604766 ADC_CONTEXT_INIT_LOCK(iadc_data_##n, ctx), \
605767 ADC_CONTEXT_INIT_SYNC(iadc_data_##n, ctx), \
768+ IADC_DMA_CHANNEL(n) \
606769 }; \
607770 \
608771 static void iadc_config_func_##n(void) \
0 commit comments