11/*
2- * Copyright (c) 2017-2018, NXP
2+ * Copyright (c) 2017-2018, 2020, NXP
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
88
99#include <errno.h>
1010#include <drivers/adc.h>
11+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
12+ #include <drivers/dma.h>
13+ #include <fsl_sim.h>
14+ #endif
15+
1116#include <fsl_adc16.h>
1217
1318#define LOG_LEVEL CONFIG_ADC_LOG_LEVEL
@@ -19,19 +24,82 @@ LOG_MODULE_REGISTER(adc_mcux_adc16);
1924
2025struct mcux_adc16_config {
2126 ADC_Type * base ;
27+ #ifndef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
2228 void (* irq_config_func )(const struct device * dev );
29+ #endif
30+ uint32_t clk_source ; /* ADC clock source selection */
31+ uint32_t long_sample ; /* ADC long sample mode selection */
32+ uint32_t hw_trigger_src ; /* ADC hardware trigger source */
33+ /* defined in SIM module SOPT7 */
34+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
35+ uint32_t dma_slot ; /* ADC DMA MUX slot */
36+ #endif
37+ uint32_t trg_offset ;
38+ uint32_t trg_bits ;
39+ uint32_t alt_offset ;
40+ uint32_t alt_bits ;
41+ bool periodic_trigger ; /* ADC enable periodic trigger */
2342 bool channel_mux_b ;
43+ bool high_speed ; /* ADC enable high speed mode*/
44+ bool continuous_convert ; /* ADC enable continuous convert*/
2445};
2546
47+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
48+ struct adc_edma_config {
49+ int32_t state ;
50+ uint32_t dma_channel ;
51+ void (* irq_call_back )(void );
52+ struct dma_config dma_cfg ;
53+ struct dma_block_config dma_block ;
54+ };
55+ #endif
56+
2657struct mcux_adc16_data {
2758 const struct device * dev ;
2859 struct adc_context ctx ;
60+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
61+ const struct device * dev_dma ;
62+ struct adc_edma_config adc_dma_config ;
63+ #endif
2964 uint16_t * buffer ;
3065 uint16_t * repeat_buffer ;
3166 uint32_t channels ;
3267 uint8_t channel_id ;
3368};
3469
70+ #define DEV_CFG (dev ) ((const struct mcux_adc16_config *const)dev->config)
71+ #define DEV_DATA (dev ) ((struct mcux_adc16_data *)dev->data)
72+ #define DEV_BASE (dev ) ((ADC_Type *)DEV_CFG(dev)->base)
73+
74+ #ifdef CONFIG_ADC_MCUX_ADC16_HW_TRIGGER
75+ #define SIM_SOPT7_ADCSET (x , shifts , mask ) \
76+ (((uint32_t)(((uint32_t)(x)) << shifts)) & mask)
77+ #endif
78+
79+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
80+ static void adc_dma_callback (const struct device * dma_dev , void * callback_arg ,
81+ uint32_t channel , int error_code )
82+ {
83+ struct device * dev = (struct device * )callback_arg ;
84+ struct mcux_adc16_data * data = DEV_DATA (dev );
85+
86+ LOG_DBG ("DMA done" );
87+ adc_context_on_sampling_done (& data -> ctx , dev );
88+ }
89+ #endif
90+
91+ #ifdef CONFIG_ADC_MCUX_ADC16_HW_TRIGGER
92+ static void adc_hw_trigger_enable (const struct device * dev )
93+ {
94+ const struct mcux_adc16_config * config = dev -> config ;
95+
96+ /* enable ADC trigger channel */
97+ SIM -> SOPT7 |= SIM_SOPT7_ADCSET (config -> hw_trigger_src ,
98+ config -> trg_offset , config -> trg_bits ) |
99+ SIM_SOPT7_ADCSET (1 , config -> alt_offset , config -> alt_bits );
100+ }
101+ #endif
102+
35103static int mcux_adc16_channel_setup (const struct device * dev ,
36104 const struct adc_channel_cfg * channel_cfg )
37105{
@@ -62,6 +130,10 @@ static int mcux_adc16_channel_setup(const struct device *dev,
62130 return - EINVAL ;
63131 }
64132
133+ #ifdef CONFIG_ADC_MCUX_ADC16_HW_TRIGGER
134+ adc_hw_trigger_enable (dev );
135+ #endif
136+
65137 return 0 ;
66138}
67139
@@ -89,7 +161,8 @@ static int start_read(const struct device *dev,
89161 case 13 :
90162 resolution = kADC16_Resolution12or13Bit ;
91163 break ;
92- #if defined(FSL_FEATURE_ADC16_MAX_RESOLUTION ) && (FSL_FEATURE_ADC16_MAX_RESOLUTION >= 16U )
164+ #if defined(FSL_FEATURE_ADC16_MAX_RESOLUTION ) && \
165+ (FSL_FEATURE_ADC16_MAX_RESOLUTION >= 16U )
93166 case 16 :
94167 resolution = kADC16_Resolution16Bit ;
95168 break ;
@@ -130,6 +203,9 @@ static int start_read(const struct device *dev,
130203 adc_context_start_read (& data -> ctx , sequence );
131204
132205 error = adc_context_wait_for_completion (& data -> ctx );
206+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
207+ dma_stop (data -> dev_dma , data -> adc_dma_config .dma_channel );
208+ #endif
133209 return error ;
134210}
135211
@@ -180,6 +256,11 @@ static void mcux_adc16_start_channel(const struct device *dev)
180256 channel_config .enableInterruptOnConversionCompleted = true;
181257 channel_config .channelNumber = data -> channel_id ;
182258 ADC16_SetChannelConfig (config -> base , channel_group , & channel_config );
259+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
260+ LOG_DBG ("Starting EDMA" );
261+ dma_start (data -> dev_dma , data -> adc_dma_config .dma_channel );
262+ #endif
263+ LOG_DBG ("Starting channel done" );
183264}
184265
185266static void adc_context_start_sampling (struct adc_context * ctx )
@@ -190,6 +271,17 @@ static void adc_context_start_sampling(struct adc_context *ctx)
190271 data -> channels = ctx -> sequence .channels ;
191272 data -> repeat_buffer = data -> buffer ;
192273
274+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
275+ LOG_DBG ("config dma" );
276+ data -> buffer = ctx -> sequence .buffer ;
277+ data -> adc_dma_config .dma_block .block_size = ctx -> sequence .buffer_size ;
278+ data -> adc_dma_config .dma_block .dest_address = (uint32_t )data -> buffer ;
279+ data -> adc_dma_config .dma_cfg .head_block =
280+ & (data -> adc_dma_config .dma_block );
281+ dma_config (data -> dev_dma , data -> adc_dma_config .dma_channel ,
282+ & data -> adc_dma_config .dma_cfg );
283+ #endif
284+
193285 mcux_adc16_start_channel (data -> dev );
194286}
195287
@@ -204,6 +296,7 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx,
204296 }
205297}
206298
299+ #ifndef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
207300static void mcux_adc16_isr (const struct device * dev )
208301{
209302 const struct mcux_adc16_config * config = dev -> config ;
@@ -213,8 +306,8 @@ static void mcux_adc16_isr(const struct device *dev)
213306 uint16_t result ;
214307
215308 result = ADC16_GetChannelConversionValue (base , channel_group );
216- LOG_DBG ("Finished channel %d. Result is 0x%04x" ,
217- data -> channel_id , result );
309+ LOG_DBG ("Finished channel %d. Result is 0x%04x" , data -> channel_id ,
310+ result );
218311
219312 * data -> buffer ++ = result ;
220313 data -> channels &= ~BIT (data -> channel_id );
@@ -225,6 +318,7 @@ static void mcux_adc16_isr(const struct device *dev)
225318 adc_context_on_sampling_done (& data -> ctx , dev );
226319 }
227320}
321+ #endif
228322
229323static int mcux_adc16_init (const struct device * dev )
230324{
@@ -233,8 +327,17 @@ static int mcux_adc16_init(const struct device *dev)
233327 ADC_Type * base = config -> base ;
234328 adc16_config_t adc_config ;
235329
330+ LOG_DBG ("init adc" );
236331 ADC16_GetDefaultConfig (& adc_config );
237332
333+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
334+ adc_config .clockSource = (adc16_clock_source_t )config -> clk_source ;
335+ adc_config .longSampleMode =
336+ (adc16_long_sample_mode_t )config -> long_sample ;
337+ adc_config .enableHighSpeed = config -> high_speed ;
338+ adc_config .enableContinuousConversion = config -> continuous_convert ;
339+ #endif
340+
238341#if CONFIG_ADC_MCUX_ADC16_VREF_DEFAULT
239342 adc_config .referenceVoltageSource = kADC16_ReferenceVoltageSourceVref ;
240343#else /* CONFIG_ADC_MCUX_ADC16_VREF_ALTERNATE */
@@ -260,11 +363,60 @@ static int mcux_adc16_init(const struct device *dev)
260363 if (config -> channel_mux_b ) {
261364 ADC16_SetChannelMuxMode (base , kADC16_ChannelMuxB );
262365 }
263- ADC16_EnableHardwareTrigger (base , false);
264366
265- config -> irq_config_func (dev );
367+ if (IS_ENABLED (CONFIG_ADC_MCUX_ADC16_HW_TRIGGER )) {
368+ ADC16_EnableHardwareTrigger (base , true);
369+ } else {
370+ ADC16_EnableHardwareTrigger (base , false);
371+ }
372+
266373 data -> dev = dev ;
267374
375+ /* dma related init */
376+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
377+ /* Enable DMA. */
378+ ADC16_EnableDMA (base , true);
379+
380+ data -> adc_dma_config .dma_cfg .block_count = 1U ;
381+ data -> adc_dma_config .dma_cfg .dma_slot = config -> dma_slot ;
382+ data -> adc_dma_config .dma_cfg .channel_direction = PERIPHERAL_TO_MEMORY ;
383+ data -> adc_dma_config .dma_cfg .source_burst_length = 4U ;
384+ data -> adc_dma_config .dma_cfg .dest_burst_length = 4U ;
385+ data -> adc_dma_config .dma_cfg .channel_priority = 0U ;
386+ data -> adc_dma_config .dma_cfg .dma_callback = adc_dma_callback ;
387+ data -> adc_dma_config .dma_cfg .user_data = (void * )dev ;
388+
389+ data -> adc_dma_config .dma_cfg .source_data_size = 4U ;
390+ data -> adc_dma_config .dma_cfg .dest_data_size = 4U ;
391+ data -> adc_dma_config .dma_block .source_address = (uint32_t )& base -> R [0 ];
392+
393+
394+ if (data -> dev_dma == NULL || !device_is_ready (data -> dev_dma )) {
395+ LOG_ERR ("dma binding fail" );
396+ return - EINVAL ;
397+ }
398+
399+ if (config -> periodic_trigger ) {
400+ enum dma_channel_filter adc_filter = DMA_CHANNEL_PERIODIC ;
401+
402+ data -> adc_dma_config .dma_channel =
403+ dma_request_channel (data -> dev_dma , (void * )& adc_filter );
404+ } else {
405+ enum dma_channel_filter adc_filter = DMA_CHANNEL_NORMAL ;
406+
407+ data -> adc_dma_config .dma_channel =
408+ dma_request_channel (data -> dev_dma , (void * )& adc_filter );
409+ }
410+ if (data -> adc_dma_config .dma_channel == - EINVAL ) {
411+ LOG_ERR ("can not allocate dma channel" );
412+ return - EINVAL ;
413+ }
414+ LOG_DBG ("dma allocated channel %d" , data -> adc_dma_config .dma_channel );
415+ #else
416+ config -> irq_config_func (dev );
417+ #endif
418+ LOG_INF ("adc init done" );
419+
268420 adc_context_unlock_unconditionally (& data -> ctx );
269421
270422 return 0 ;
@@ -278,26 +430,66 @@ static const struct adc_driver_api mcux_adc16_driver_api = {
278430#endif
279431};
280432
281- #define ACD16_MCUX_INIT (n ) \
282- static void mcux_adc16_config_func_##n(const struct device *dev); \
283- \
433+ #ifdef CONFIG_ADC_MCUX_ADC16_ENABLE_EDMA
434+ #define ACD16_MCUX_INIT (n ) \
284435 static const struct mcux_adc16_config mcux_adc16_config_##n = { \
285436 .base = (ADC_Type *)DT_INST_REG_ADDR(n), \
286- .irq_config_func = mcux_adc16_config_func_##n, \
287437 .channel_mux_b = DT_INST_PROP(n, channel_mux_b), \
438+ .clk_source = DT_INST_PROP_OR(n, clk_source, 0), \
439+ .long_sample = DT_INST_PROP_OR(n, long_sample, 0), \
440+ .high_speed = DT_INST_PROP(n, high_speed), \
441+ .periodic_trigger = DT_INST_PROP(n, periodic_trigger), \
442+ .continuous_convert = \
443+ DT_INST_PROP(n, continuous_convert), \
444+ .hw_trigger_src = \
445+ DT_INST_PROP_OR(n, hw_trigger_src, 0), \
446+ .dma_slot = DT_INST_DMAS_CELL_BY_IDX(n, 0, source), \
447+ .trg_offset = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, offset), \
448+ .trg_bits = DT_INST_CLOCKS_CELL_BY_IDX(n, 0, bits), \
449+ .alt_offset = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, offset), \
450+ .alt_bits = DT_INST_CLOCKS_CELL_BY_IDX(n, 1, bits), \
288451 }; \
289452 \
290453 static struct mcux_adc16_data mcux_adc16_data_##n = { \
291454 ADC_CONTEXT_INIT_TIMER(mcux_adc16_data_##n, ctx), \
292455 ADC_CONTEXT_INIT_LOCK(mcux_adc16_data_##n, ctx), \
293456 ADC_CONTEXT_INIT_SYNC(mcux_adc16_data_##n, ctx), \
457+ .dev_dma = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, adc##n)), \
458+ }; \
459+ \
460+ DEVICE_DT_INST_DEFINE(n, &mcux_adc16_init, \
461+ NULL, \
462+ &mcux_adc16_data_##n, \
463+ &mcux_adc16_config_##n, \
464+ POST_KERNEL, \
465+ CONFIG_ADC_MCUX_ADC16_INIT_PRIORITY, \
466+ &mcux_adc16_driver_api);
467+ #else
468+ #define ACD16_MCUX_INIT (n ) \
469+ static void mcux_adc16_config_func_##n(const struct device *dev); \
470+ static const struct mcux_adc16_config mcux_adc16_config_##n = { \
471+ .base = (ADC_Type *)DT_INST_REG_ADDR(n), \
472+ .irq_config_func = mcux_adc16_config_func_##n, \
473+ .channel_mux_b = DT_INST_PROP(n, channel_mux_b), \
474+ .clk_source = DT_INST_PROP_OR(n, clk_source, 0), \
475+ .long_sample = DT_INST_PROP_OR(n, long_sample, 0), \
476+ .high_speed = DT_INST_PROP(n, high_speed), \
477+ .continuous_convert = \
478+ DT_INST_PROP(n, continuous_convert), \
479+ }; \
480+ static struct mcux_adc16_data mcux_adc16_data_##n = { \
481+ ADC_CONTEXT_INIT_TIMER(mcux_adc16_data_##n, ctx), \
482+ ADC_CONTEXT_INIT_LOCK(mcux_adc16_data_##n, ctx), \
483+ ADC_CONTEXT_INIT_SYNC(mcux_adc16_data_##n, ctx), \
294484 }; \
295485 \
296- DEVICE_DT_INST_DEFINE(n, &mcux_adc16_init, \
297- NULL, &mcux_adc16_data_##n, \
298- &mcux_adc16_config_##n, POST_KERNEL, \
299- CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
300- &mcux_adc16_driver_api); \
486+ DEVICE_DT_INST_DEFINE(n, &mcux_adc16_init, \
487+ NULL, \
488+ &mcux_adc16_data_##n, \
489+ &mcux_adc16_config_##n, \
490+ POST_KERNEL, \
491+ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
492+ &mcux_adc16_driver_api); \
301493 \
302494 static void mcux_adc16_config_func_##n(const struct device *dev) \
303495 { \
@@ -307,5 +499,6 @@ static const struct adc_driver_api mcux_adc16_driver_api = {
307499 \
308500 irq_enable(DT_INST_IRQN(n)); \
309501 }
502+ #endif
310503
311504DT_INST_FOREACH_STATUS_OKAY (ACD16_MCUX_INIT )
0 commit comments