1 /*
2 * Copyright (C) 2017-2024 Alibaba Group Holding Limited
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 /******************************************************************************
20 * @file wj_adc.c
21 * @brief CSI Source File for ADC Driver
22 * @version V1.0
23 * @date 2020-03-05
24 ******************************************************************************/
25
26 #include <string.h>
27
28 #include <drv/adc.h>
29 #include <drv/irq.h>
30 #include <drv/tick.h>
31
wj_adc_irqhandler(void * args)32 static void wj_adc_irqhandler(void *args)
33 {
34
35 ///< TODO:获取ADC中断的状态
36 ///< TODO:清除ADC中断
37 ///< TODO:根据ADC的中断状态处理中断
38
39 }
40
wj_adc_dma_event_cb(csi_dma_ch_t * dma,csi_dma_event_t event,void * arg)41 void wj_adc_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg)
42 {
43 csi_adc_t *adc;
44
45 adc = (csi_adc_t *)dma->parent;
46
47 if (event == DMA_EVENT_TRANSFER_DONE) {
48 ///< 关闭DMA通道
49 csi_dma_ch_stop(dma);
50 adc->num = 0U;
51 adc->state.readable = 1U;
52
53 if (adc->callback) {
54 soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U);
55 ///< 执行ADC DMA传输完成的用户回调函数
56 adc->callback(adc, ADC_EVENT_CONVERT_COMPLETE, adc->arg);
57 }
58 }
59 }
60
wj_adc_start_intr(csi_adc_t * adc)61 static csi_error_t wj_adc_start_intr(csi_adc_t *adc)
62 {
63
64 ///< 使能ADC的中断控制器中对应的中断
65 csi_irq_enable((uint32_t)adc->dev.irq_num);
66 ///< TODO:使能ADC的中断
67
68 ///< TODO:打开ADC控制器
69 return CSI_OK;
70 }
71
wj_adc_start_dma(csi_adc_t * adc)72 static csi_error_t wj_adc_start_dma(csi_adc_t *adc)
73 {
74 csi_dma_ch_config_t config;
75
76 config.src_inc = DMA_ADDR_CONSTANT;
77 config.dst_inc = DMA_ADDR_INC;
78 config.src_tw = DMA_DATA_WIDTH_32_BITS;
79 config.dst_tw = DMA_DATA_WIDTH_32_BITS;
80
81 config.group_len = 4U;
82 config.trans_dir = DMA_PERH2MEM;
83 config.handshake = 81U;
84 ///< 配置ADC的DMA通道
85 csi_dma_ch_config(adc->dma, &config);
86 ///< 禁止中断控制器对应的中断
87 csi_irq_disable((uint32_t)adc->dev.irq_num);
88 soc_dcache_clean_invalid_range((unsigned long)adc->data, adc->num * 4U);
89
90 ///< TODO:调用csi_dma_ch_start接口打开ADC的DMA通道
91 ///< TODO:打开ADC
92 return CSI_OK;
93 }
94
wj_adc_stop_intr(csi_adc_t * adc)95 static csi_error_t wj_adc_stop_intr(csi_adc_t *adc)
96 {
97 csi_error_t ret = CSI_OK;
98
99 ///< TODO:关闭ADC的中断
100
101 ///< TODO:关闭ADC
102
103 return ret;
104 }
105
wj_adc_stop_dma(csi_adc_t * adc)106 static csi_error_t wj_adc_stop_dma(csi_adc_t *adc)
107 {
108 csi_error_t ret = CSI_OK;
109
110 ///< TODO:关闭ADC
111
112 return ret;
113 }
114
csi_adc_init(csi_adc_t * adc,uint32_t idx)115 csi_error_t csi_adc_init(csi_adc_t *adc, uint32_t idx)
116 {
117 CSI_PARAM_CHK(adc, CSI_ERROR);
118 csi_error_t ret = CSI_OK;
119
120 adc->priv = 0U;
121
122 ///< 获取中断号、基地址等相关信息
123 if (target_get(DEV_WJ_ADC_TAG, idx, &adc->dev) != CSI_OK) {
124 ret = CSI_ERROR;
125 } else {
126
127 adc->state.writeable = 1U;
128 adc->state.readable = 1U;
129 adc->state.error = 0U;
130 adc->callback = NULL;
131 adc->arg = NULL;
132 adc->data = NULL;
133 adc->dma = NULL;
134 adc->start = NULL;
135 adc->stop = NULL;
136
137 ///< TODO:关闭ADC控制器
138 ///< TODO:打开ADC控制器
139
140 }
141
142 return ret;
143 }
144
csi_adc_uninit(csi_adc_t * adc)145 void csi_adc_uninit(csi_adc_t *adc)
146 {
147 CSI_PARAM_CHK_NORETVAL(adc);
148
149 ///< TODO:关闭ADC所有的通道
150 ///< TODO:关闭ADC控制器
151 }
152
csi_adc_set_buffer(csi_adc_t * adc,uint32_t * data,uint32_t num)153 csi_error_t csi_adc_set_buffer(csi_adc_t *adc, uint32_t *data, uint32_t num)
154 {
155 csi_error_t ret = CSI_OK;
156 CSI_PARAM_CHK(adc, CSI_ERROR);
157 CSI_PARAM_CHK(data, CSI_ERROR);
158 CSI_PARAM_CHK(num, CSI_ERROR);
159
160 if (num == 0U) {
161 ret = CSI_ERROR;
162 } else {
163 adc->data = data;
164 adc->num = num;
165 ret = CSI_OK;
166 }
167
168 return ret;
169 }
170
csi_adc_start(csi_adc_t * adc)171 csi_error_t csi_adc_start(csi_adc_t *adc)
172 {
173 CSI_PARAM_CHK(adc, CSI_ERROR);
174
175 csi_error_t ret = CSI_OK;
176
177 if (adc->state.readable == 0U) {
178 ret = CSI_BUSY;
179 return ret;
180 }
181
182 if (adc->state.writeable == 0U) {
183 ret = CSI_BUSY;
184 return ret;
185 }
186
187 ///< TODO:打开ADC控制器
188
189 return ret;
190 }
191
csi_adc_stop(csi_adc_t * adc)192 csi_error_t csi_adc_stop(csi_adc_t *adc)
193 {
194 CSI_PARAM_CHK(adc, CSI_ERROR);
195
196 csi_error_t ret = CSI_OK;
197
198 ///< TODO:关闭ADC
199
200 adc->state.readable = 1U;
201 adc->state.writeable = 1U;
202 adc->data = NULL;
203 adc->num = 0U;
204
205 return ret;
206 }
207
csi_adc_channel_enable(csi_adc_t * adc,uint8_t ch_id,bool is_enable)208 csi_error_t csi_adc_channel_enable(csi_adc_t *adc, uint8_t ch_id, bool is_enable)
209 {
210 CSI_PARAM_CHK(adc, CSI_ERROR);
211 csi_error_t ret = CSI_OK;
212
213 if (is_enable) {
214 ///< TODO:选择ADC的通道
215 } else {
216 ///< TODO:关闭指定的ADC通道
217 }
218
219 return ret;
220 }
221
csi_adc_channel_sampling_time(csi_adc_t * adc,uint8_t ch_id,uint16_t clock_num)222 csi_error_t csi_adc_channel_sampling_time(csi_adc_t *adc, uint8_t ch_id, uint16_t clock_num)
223 {
224 CSI_PARAM_CHK(adc, CSI_ERROR);
225 return CSI_UNSUPPORTED;
226 }
227
csi_adc_sampling_time(csi_adc_t * adc,uint16_t clock_num)228 csi_error_t csi_adc_sampling_time(csi_adc_t *adc, uint16_t clock_num)
229 {
230 CSI_PARAM_CHK(adc, CSI_ERROR);
231
232 csi_error_t ret = CSI_OK;
233
234 ///< TODO:设置ADC的采样时间
235
236 return ret;
237 }
238
239
csi_adc_freq_div(csi_adc_t * adc,uint32_t div)240 uint32_t csi_adc_freq_div(csi_adc_t *adc, uint32_t div)
241 {
242 CSI_PARAM_CHK(adc, CSI_ERROR);
243 uint32_t ret = 0;
244
245 ///< TODO:设置ADC的分频
246 ///< TODO:获取ADC分频后使用的频率ret,需要用户自己获取ret
247
248 return ret;
249 }
250
csi_adc_read(csi_adc_t * adc)251 int32_t csi_adc_read(csi_adc_t *adc)
252 {
253 CSI_PARAM_CHK(adc, CSI_ERROR);
254
255 int32_t ret = CSI_OK;
256
257 ///< TODO:在一定时间内ADC读数据的标志位不为0,否则超时退出
258 ///< TODO:读数据寄存器获取ADC转换的数据到ret
259
260 return ret;
261 }
262
csi_adc_get_state(csi_adc_t * adc,csi_state_t * state)263 csi_error_t csi_adc_get_state(csi_adc_t *adc, csi_state_t *state)
264 {
265 CSI_PARAM_CHK(adc, CSI_ERROR);
266 *state = adc->state;
267 return CSI_OK;
268 }
269
csi_adc_get_freq(csi_adc_t * adc)270 uint32_t csi_adc_get_freq(csi_adc_t *adc)
271 {
272 CSI_PARAM_CHK(adc, 0U);
273 uint32_t freq = 0U;
274
275 ///< TODO:获取ADC的分频div
276 ///< TODO:获取ADC分频后使用的频率freq
277
278 return freq;
279
280 }
281
csi_adc_attach_callback(csi_adc_t * adc,void * callback,void * arg)282 csi_error_t csi_adc_attach_callback(csi_adc_t *adc, void *callback, void *arg)
283 {
284 CSI_PARAM_CHK(adc, CSI_ERROR);
285 CSI_PARAM_CHK(callback, CSI_ERROR);
286
287 adc->callback = callback;
288 adc->arg = arg;
289 adc->start = wj_adc_start_intr;
290 adc->stop = wj_adc_stop_intr;
291
292 ///< 注册ADC的中断服务函数,使能中断控制器对应的中断
293 csi_irq_attach((uint32_t)adc->dev.irq_num, &wj_adc_irqhandler, &adc->dev);
294 csi_irq_enable((uint32_t)adc->dev.irq_num);
295 return CSI_OK;
296
297 }
298
csi_adc_detach_callback(csi_adc_t * adc)299 void csi_adc_detach_callback(csi_adc_t *adc)
300 {
301 CSI_PARAM_CHK_NORETVAL(adc);
302
303 adc->callback = NULL;
304 adc->arg = NULL;
305 adc->start = NULL;
306 adc->stop = NULL;
307
308 ///< 禁止中断控制器对应的中断
309 csi_irq_disable((uint32_t)adc->dev.irq_num);
310 }
311
csi_adc_start_async(csi_adc_t * adc)312 csi_error_t csi_adc_start_async(csi_adc_t *adc)
313 {
314 CSI_PARAM_CHK(adc, CSI_ERROR);
315
316 csi_error_t ret = CSI_OK;
317
318 if ((adc->data == NULL) || (adc->num == 0U)) {
319 ret = CSI_ERROR;
320 return ret;
321 }
322
323 /* rx buffer not full */
324 if (adc->state.readable == 0U) {
325 ret = CSI_BUSY;
326 return ret;
327 }
328
329 /* last conversion existed */
330 if (adc->state.writeable == 0U) {
331 ret = CSI_ERROR;
332 return ret;
333 }
334
335 if (adc->start) {
336 ///< 执行ADC中断或者DMA传输完成中断回调函数
337 adc->start(adc);
338 }
339 return ret;
340 }
341
csi_adc_stop_async(csi_adc_t * adc)342 csi_error_t csi_adc_stop_async(csi_adc_t *adc)
343 {
344 CSI_PARAM_CHK(adc, CSI_ERROR);
345
346 csi_error_t ret = CSI_OK;
347
348 if (adc->stop) {
349 adc->stop(adc);
350 adc->state.readable = 1U;
351 adc->state.writeable = 1U;
352 adc->data = NULL;
353 adc->num = 0U;
354 } else {
355 ret = CSI_ERROR;
356 }
357
358 return ret;
359 }
360
csi_adc_continue_mode(csi_adc_t * adc,bool is_enable)361 csi_error_t csi_adc_continue_mode(csi_adc_t *adc, bool is_enable)
362 {
363 CSI_PARAM_CHK(adc, CSI_ERROR);
364
365 if (is_enable) {
366 ///< TODO:设置ADC为continue模式
367 } else {
368 ///< TODO:设置ADC为single模式
369 }
370
371 ///< TODO:打开ADC的等待模式
372 return CSI_OK;
373 }
374
csi_adc_link_dma(csi_adc_t * adc,csi_dma_ch_t * dma)375 csi_error_t csi_adc_link_dma(csi_adc_t *adc, csi_dma_ch_t *dma)
376 {
377 CSI_PARAM_CHK(adc, CSI_ERROR);
378
379 csi_error_t ret = CSI_OK;
380
381 if (dma != NULL) {
382 dma->parent = adc;
383 ///< 申请DMA通道
384 ret = csi_dma_ch_alloc(dma, -1, -1);
385
386 if (ret == CSI_OK) {
387 ///< ADC DMA模式传输完成中断服务函数的注册
388 csi_dma_ch_attach_callback(dma, wj_adc_dma_event_cb, NULL);
389 adc->dma = dma;
390 adc->start = wj_adc_start_dma;
391 adc->stop = wj_adc_stop_dma;
392 } else {
393 dma->parent = NULL;
394 }
395 } else {
396 if (adc->dma) {
397 ///< 释放DMA通道,注销ADC DMA模式传输完成中断服务函数
398 csi_dma_ch_free(adc->dma);
399 csi_dma_ch_detach_callback(adc->dma);
400 adc->dma = NULL;
401 }
402
403 if (adc->callback != NULL) {
404 adc->start = wj_adc_start_intr;
405 adc->stop = wj_adc_stop_intr;
406 } else {
407 adc->start = NULL;
408 adc->stop = NULL;
409 }
410 }
411 return ret;
412 }
413
414 #ifdef CONFIG_PM
dw_adc_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)415 csi_error_t dw_adc_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
416 {
417 CSI_PARAM_CHK(dev, CSI_ERROR);
418
419 csi_error_t ret = CSI_OK;
420 csi_pm_dev_t *pm_dev = &dev->pm_dev;
421 wj_adc_regs_t *adc_base = (wj_adc_regs_t *)dev->reg_base;
422
423 switch (action) {
424 case PM_DEV_SUSPEND:
425 ///< TODO:恢复ADC寄存器
426 break;
427
428 case PM_DEV_RESUME:
429 ///< TODO:保存ADC寄存器
430 break;
431
432 default:
433 ret = CSI_ERROR;
434 break;
435 }
436
437 return ret;
438 }
439
csi_adc_enable_pm(csi_adc_t * adc)440 csi_error_t csi_adc_enable_pm(csi_adc_t *adc)
441 {
442 ///< TODO:注册ADC低功耗处理函数dw_adc_pm_action
443 }
444
csi_adc_disable_pm(csi_adc_t * adc)445 void csi_adc_disable_pm(csi_adc_t *adc)
446 {
447 csi_pm_dev_unregister(&adc->dev);
448 }
449 #endif
450
451