1 /*
2 * Copyright 2024 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_sdadc.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13 /* Component ID definition, used by tools. */
14 #ifndef FSL_COMPONENT_ID
15 #define FSL_COMPONENT_ID "platform.drivers.sdadc"
16 #endif
17
18 /*******************************************************************************
19 * Prototypes
20 ******************************************************************************/
21
22 /*******************************************************************************
23 * Variables
24 ******************************************************************************/
25 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
26 /*! @brief Pointers to SDADC bases for each instance. */
27 #if defined(SDADC_BASE_PTRS_NS)
28 static SDADC_Type *s_sdadcBases_ns[] = SDADC_BASE_PTRS_NS;
29 #endif /* SDADC_BASE_PTRS_NS */
30 static SDADC_Type *s_sdadcBases[] = SDADC_BASE_PTRS;
31
32 /*! @brief Pointers to SDADC clocks for each instance. */
33 static const clock_ip_name_t s_sdadcClocks[] = SDADC_CLOCKS;
34 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
35
36 /*! @brief SDADC reset array for each instance. */
37 #if defined(SDADC_RSTS)
38 static const reset_ip_name_t s_sdadcResets[] = SDADC_RSTS;
39 #endif /* SDADC_RSTS */
40
41 static char sdadcChannelModeRecord = 'D'; /* Record the conversion mode used by the SDADC channel
42 in the initialization state, by default, it is set to 'D',
43 which means only differential mode is executed. */
44 /*******************************************************************************
45 * Code
46 ******************************************************************************/
47 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
48 /*!
49 * brief This function is used to get the SDADC instance.
50 *
51 * param base SDADC peripheral base address.
52 *
53 * return SDADC instance.
54 */
SDADC_GetInstance(SDADC_Type * base)55 static uint32_t SDADC_GetInstance(SDADC_Type *base)
56 {
57 uint32_t instance = 0U;
58 uint8_t sdadcBaseSize = ARRAY_SIZE(s_sdadcBases);
59 SDADC_Type **sdadcBaseAddress = s_sdadcBases;
60
61 #if defined(SDADC_BASE_PTRS_NS)
62 if (0U == ((uint32_t)base & 0x10000000U))
63 {
64 /* Input instance is in the non-secure area. */
65 sdadcBaseSize = ARRAY_SIZE(s_sdadcBases_ns);
66 sdadcBaseAddress = s_sdadcBases_ns;
67 }
68 #endif /* SDADC_BASE_PTRS_NS */
69
70 /* Find the instance index from base address mappings. */
71 for (; instance < sdadcBaseSize; ++instance)
72 {
73 if (sdadcBaseAddress[instance] == base)
74 {
75 break;
76 }
77 }
78
79 assert(instance < sdadcBaseSize);
80
81 return instance;
82 }
83 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
84
85 /*!
86 * brief This function is used to get available predefined configurations for the SDADC initialization.
87 *
88 * param config Pointer to the SDADC configuration structure, please refer to @ref sdadc_config_t for details.
89 */
SDADC_GetDefaultConfig(sdadc_config_t * config)90 void SDADC_GetDefaultConfig(sdadc_config_t *config)
91 {
92 assert(config != NULL);
93
94 config->channelCount = 0U;
95 config->channelConfig = NULL;
96 }
97
98 /*!
99 * brief This function is used to initialize the SDADC.
100 *
101 * param base SDADC peripheral base address.
102 * param config Pointer to the SDADC configuration structure, please refer to @ref sdadc_config_t for details.
103 */
SDADC_Init(SDADC_Type * base,const sdadc_config_t * config)104 void SDADC_Init(SDADC_Type *base, const sdadc_config_t *config)
105 {
106 assert(config != NULL);
107
108 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
109 /* Enable the clock for the SDADC instance. */
110 (void)CLOCK_EnableClock(s_sdadcClocks[SDADC_GetInstance(base)]);
111 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
112
113 #if defined(SDADC_RSTS)
114 /* Release the SDADC reset. */
115 RESET_ReleasePeripheralReset(s_sdadcResets[SDADC_GetInstance(base)]);
116 #endif /* SDADC_RSTS */
117
118 sdadc_channel_config_t *channelConfig = config->channelConfig;
119
120 for (uint8_t index = 0U; index < config->channelCount; ++index)
121 {
122 SDADC_ConfigureChannelMode(base, channelConfig->number, channelConfig->mode);
123
124 if (kSDADC_SingleEnd_Mode == channelConfig->mode)
125 {
126 sdadcChannelModeRecord = 'S'; /* If there is a single-end mode conversion, mark it as 'S'. */
127
128 /*! Configure DAC compensation. */
129 SDADC_ControlDacCompensationEnable(base, channelConfig->number, channelConfig->type,
130 channelConfig->enableDacCompensation);
131 /*! Configure DC Loop. */
132 SDADC_ControlModulatorDcLoopEnable(base, channelConfig->number, channelConfig->type,
133 channelConfig->enableDCLoop);
134 }
135 else
136 {
137 /*! Disable DAC compensation. */
138 SDADC_ControlDacCompensationEnable(base, channelConfig->number, channelConfig->type, false);
139 /*! Disable DC Loop. */
140 SDADC_ControlModulatorDcLoopEnable(base, channelConfig->number, channelConfig->type, false);
141 }
142
143 /*! Decimator DC Filter configuration. */
144 SDADC_ControlDecimatorDcFilterEnable(base, channelConfig->number, channelConfig->type,
145 channelConfig->enableDcFilter);
146 /*! Decimator output signal invert configuration. */
147 SDADC_ControlDecimatorOutputInvertEnable(base, channelConfig->number, channelConfig->type,
148 channelConfig->enablePolarityInvert);
149
150 /*! Configure channel volume (gain). */
151 SDADC_ConfigureDecimatorVolume(base, channelConfig->number, channelConfig->type, channelConfig->volume);
152 /*! Configure decimator sample rate. */
153 SDADC_ConfigureDecimatorSampleRate(base, channelConfig->number, channelConfig->type, channelConfig->samplerate);
154 /*! Configure FIFO watermark. */
155 SDADC_ConfigureFifoWatermark(base, channelConfig->number, channelConfig->type, channelConfig->watermark);
156
157 channelConfig += 1U;
158 }
159 }
160
161 /*!
162 * brief This function is used to power up the ADC in the initialization state.
163 *
164 * param base SDADC peripheral base address.
165 * param config Pointer to the SDADC configuration structure, please refer to @ref sdadc_config_t for details.
166 * param clock Core clock frequency with Hz.
167 */
SDADC_DoInitPowerUp(SDADC_Type * base,sdadc_config_t * config,uint32_t clock)168 void SDADC_DoInitPowerUp(SDADC_Type *base, sdadc_config_t *config, uint32_t clock)
169 {
170 /*! Enable reference power, set the reference mode to fast charge mode at the beginning, delay 1ms waiting for the
171 reference power up then set the reference mode to retain mode (when there is only differential mode executing)
172 or set to the low noise mode (when there is a single-end mode executing).
173 */
174 SDADC_ControlReferencePowerEnable(base, true);
175 SDADC_ConfigureReferenceMode(base, kSDADC_RefFastChargeMode);
176 SDK_DelayAtLeastUs(1000U, clock);
177
178 if ('S' == sdadcChannelModeRecord) /* If only single end mode enabled, entry low noise mode to reduce noise. */
179 {
180 SDADC_ConfigureReferenceMode(base, kSDADC_RefLowNoiseMode);
181 }
182 else /* If there is no single end mode enabled, entry retain mode to save power. */
183 {
184 SDADC_ConfigureReferenceMode(base, kSDADC_RefRetainMode);
185 }
186
187 /*! Enable LDO power and set LDO drive capability. */
188 SDADC_ControlLdoPowerEnable(base, true);
189 if (config->channelCount <= 1U)
190 {
191 SDADC_ConfigureLdoDriveCapability(base, kSDADC_LdoLowPower);
192 }
193 else
194 {
195 SDADC_ConfigureLdoDriveCapability(base, kSDADC_LdoHighPower);
196 }
197
198 /*! Enable conversion channel's modulator power. */
199 for (uint8_t index = 0U; index < config->channelCount; ++index)
200 {
201 SDADC_ControlModulatorPowerEnable(base, (config->channelConfig + index)->number,
202 (config->channelConfig + index)->type, true);
203 }
204
205 /*! Reset the SDADC channel P-Side or/and N-Side 15us to avoid saturation behavior. */
206 for (uint8_t index = 0U; index < config->channelCount; ++index)
207 {
208 SDADC_ControlModulatorReset(base, (config->channelConfig + index)->number,
209 (config->channelConfig + index)->type, true);
210 }
211
212 SDK_DelayAtLeastUs(50U, clock);
213
214 for (uint8_t index = 0U; index < config->channelCount; ++index)
215 {
216 SDADC_ControlModulatorReset(base, (config->channelConfig + index)->number,
217 (config->channelConfig + index)->type, false);
218 }
219 }
220
221 /*!
222 * brief This function is used to de-initialize the SDADC.
223 *
224 * param base SDADC peripheral base address.
225 */
SDADC_Deinit(SDADC_Type * base,const sdadc_config_t * config)226 void SDADC_Deinit(SDADC_Type *base, const sdadc_config_t *config)
227 {
228 /*! Disable SDADC channels power. */
229 for (uint8_t index = 0U; index < config->channelCount; ++index)
230 {
231 SDADC_ControlModulatorPowerEnable(base, (config->channelConfig + index)->number,
232 (config->channelConfig + index)->type, false);
233 }
234
235 base->ADC_CTL_0 &= (~(SDADC_ADC_CTL_0_ADCP_POWER_ENABLE_MASK | SDADC_ADC_CTL_0_ADCN_POWER_ENABLE_MASK));
236 /*! Disable the LDO power. */
237 SDADC_ControlLdoPowerEnable(base, false);
238 /*! Disable the reference power. */
239 SDADC_ControlReferencePowerEnable(base, false);
240
241 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
242 /*! Disable the clock gate. */
243 CLOCK_DisableClock(s_sdadcClocks[SDADC_GetInstance(base)]);
244 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
245
246 #if defined(SDADC_RSTS)
247 RESET_PeripheralReset(s_sdadcResets[SDADC_GetInstance(base)]);
248 #endif /* SDADC_RSTS */
249 }
250
251 /*!
252 * brief This function is used to copy specific conversion channels' data from FIFO to buffer.
253 *
254 * note This function will copy all 16 entries in the specified FIFO.
255 *
256 * param base SDADC peripheral base address.
257 * param group Indicates which group of channels data to obtain.
258 * param count Indicates how many channels in the specified group.
259 * param buffer The buffer which stores conversion data.
260 */
SDADC_CopyConvChannelFifoToBuffer(SDADC_Type * base,sdadc_channel_group * group,uint8_t count,void * buffer)261 void SDADC_CopyConvChannelFifoToBuffer(SDADC_Type *base, sdadc_channel_group *group, uint8_t count, void *buffer)
262 {
263 uint32_t *dataAddr = (uint32_t *)buffer;
264
265 for (uint8_t fifoItemIndex = 0U; fifoItemIndex < SDADC_FIFO_DEPTH; fifoItemIndex++)
266 {
267 for (uint8_t fifoIndex = 0; fifoIndex < count; fifoIndex++)
268 {
269 *dataAddr = SDADC_GetConvChannelFifoRawData(base, (group + fifoIndex)->number, (group + fifoIndex)->type);
270 dataAddr = (uint32_t *)((uint32_t)dataAddr + SDADC_FIFO_WIDTH);
271 }
272 }
273 }
274