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