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     dw_spi.c
21  * @brief
22  * @version
23  * @date     2020-02-11
24  ******************************************************************************/
25 
26 #include <string.h>
27 
28 #include <drv/spi.h>
29 #include <drv/irq.h>
30 #include <drv/tick.h>
31 #include <drv/porting.h>
32 
33 ///< TODO:SPI_CTRLR0_TMOD_Msk需要根据实际情况进行设置
34 #define SPI_CTRLR0_TMOD_Msk  3U << 8U ///< 设置SPI模式的寄存器对应的位的掩码
35 ///< TODO:SPI_CTRLR0_TMOD_RX和SPI_CTRLR0_TMOD_TX需要根据实际情况进行设置
36 #define SPI_CTRLR0_TMOD_RX   2U << 8U ///< SPI发送模式
37 #define SPI_CTRLR0_TMOD_TX   1U << 8U ///< SPI发送模式
38 
39 static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size);
40 static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size);
41 static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t num);
42 
dw_spi_irqhandler(void * args)43 static void dw_spi_irqhandler(void *args)
44 {
45 
46     ///< TODO:获取SPI中断的状态
47 
48     ///< TODO:根据SPI中断的状态进行接收数据的处理,在接收完成后关闭中断;调用用户回调函数
49 
50     ///< TODO:根据SPI中断的状态进行关闭中断,发送数据的处理;调用用户回调函数
51 
52     ///< TODO:根据SPI中断的状态进行异常中断的处理,并清除中断,调用用户回调函数
53 
54 }
55 
dw_spi_dma_event_cb(csi_dma_ch_t * dma,csi_dma_event_t event,void * arg)56 static void dw_spi_dma_event_cb(csi_dma_ch_t *dma, csi_dma_event_t event, void *arg)
57 {
58     csi_spi_t *spi = (csi_spi_t *)dma->parent;
59     uint32_t mode = 0U;
60 
61     ///< TODO:获取SPI传输数据的模式mode:发送模式/接收模式/发送&接收模式
62 
63     if (event == DMA_EVENT_TRANSFER_DONE) {
64         /* process end of transmit */
65         if ((spi->tx_dma != NULL) && (spi->tx_dma->ch_id == dma->ch_id)) {
66             ///< 关闭DMA通道
67             csi_dma_ch_stop(dma);
68 
69             ///< TODO:关闭DMA发送使能
70 
71             ///< TODO:如果SPI的BUSY在一定时间内处于空闲状态下
72                 spi->state.writeable = 1U;
73                 spi->tx_size = 0U;
74 
75                 if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_TX) {
76                     ///< TODO:设置发送FIFO的触发级别为0
77 
78                     if (spi->callback) {
79                         ///< 调用用户回调函数
80                         spi->callback(spi, SPI_EVENT_SEND_COMPLETE, spi->arg);
81                     }
82                 } else {
83                     if (spi->state.readable == 1U) {
84                         ///< 调用用户回调函数
85                         spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg);
86                     }
87                 }
88         } else if ((spi->rx_dma != NULL) && (spi->rx_dma->ch_id == dma->ch_id)) {
89             ///< 关闭DMA通道
90             ///< TODO:关闭SPI接收DMA
91             ///< TODO:设置接收FIFO的触发级别为0
92             ///< TODO:设置接收数据的大小为0
93 
94             spi->state.readable = 1U;
95             spi->rx_size = 0U;
96 
97             if ((mode & SPI_CTRLR0_TMOD_Msk) == SPI_CTRLR0_TMOD_RX) {
98                 if (spi->callback) {
99                     ///< 调用用户回调函数
100                     spi->callback(spi, SPI_EVENT_RECEIVE_COMPLETE, spi->arg);
101                 }
102             } else {
103                 if (spi->state.writeable == 1U) {
104                     ///< 调用用户回调函数
105                     spi->callback(spi, SPI_EVENT_SEND_RECEIVE_COMPLETE, spi->arg);
106                 }
107             }
108         }
109     }
110 }
111 
csi_spi_init(csi_spi_t * spi,uint32_t idx)112 csi_error_t csi_spi_init(csi_spi_t *spi, uint32_t idx)
113 {
114     CSI_PARAM_CHK(spi, CSI_ERROR);
115 
116     csi_error_t ret = CSI_OK;
117 
118     ///< 获取中断号、基地址等相关信息
119     if (target_get(DEV_DW_SPI_TAG, idx, &spi->dev) != CSI_OK) {
120         ret = CSI_ERROR;
121     } else {
122         spi->state.writeable = 1U;
123         spi->state.readable  = 1U;
124         spi->state.error     = 0U;
125         spi->send            = NULL;
126         spi->receive         = NULL;
127         spi->send_receive    = NULL;
128         spi->rx_dma          = NULL;
129         spi->tx_dma          = NULL;
130         spi->rx_data         = NULL;
131         spi->tx_data         = NULL;
132         spi->callback        = NULL;
133         spi->arg             = NULL;
134         spi->priv            = 0;
135 
136         ///< TODO:关闭SPI所有的中断
137         ///< TODO:关闭SPI
138 
139     }
140 
141     return ret;
142 }
143 
csi_spi_uninit(csi_spi_t * spi)144 void csi_spi_uninit(csi_spi_t *spi)
145 {
146     CSI_PARAM_CHK_NORETVAL(spi);
147 
148     ///< TODO:复位SPI使用到的寄存器
149 
150     ///< 禁止中断控制器对应的中断,注销中断服务函数
151     csi_irq_disable((uint32_t)spi->dev.irq_num);
152     csi_irq_detach((uint32_t)spi->dev.irq_num);
153 }
154 
csi_spi_attach_callback(csi_spi_t * spi,void * callback,void * arg)155 csi_error_t csi_spi_attach_callback(csi_spi_t *spi, void *callback, void *arg)
156 {
157     CSI_PARAM_CHK(spi, CSI_ERROR);
158     CSI_PARAM_CHK(callback, CSI_ERROR);
159 
160     ///< 注册用户回调函数
161     spi->callback     = callback;
162     spi->arg          = arg;
163     spi->send         = NULL;
164     spi->receive      = NULL;
165     spi->send_receive = NULL;
166 
167     return CSI_OK;
168 }
169 
170 
csi_spi_detach_callback(csi_spi_t * spi)171 void csi_spi_detach_callback(csi_spi_t *spi)
172 {
173     CSI_PARAM_CHK_NORETVAL(spi);
174 
175     ///< 注销用户回调函数
176     spi->callback     = NULL;
177     spi->arg          = NULL;
178     spi->send         = NULL;
179     spi->receive      = NULL;
180     spi->send_receive = NULL;
181 }
182 
183 
csi_spi_mode(csi_spi_t * spi,csi_spi_mode_t mode)184 csi_error_t csi_spi_mode(csi_spi_t *spi, csi_spi_mode_t mode)
185 {
186     CSI_PARAM_CHK(spi, CSI_ERROR);
187 
188     csi_error_t   ret = CSI_OK;
189 
190     switch (mode) {
191         case SPI_MASTER:
192             ///< TODO:设置SPI为主机模式
193             break;
194 
195         case SPI_SLAVE:
196             ///< TODO:设置SPI为从机模式
197             break;
198 
199         default:
200             ret = CSI_ERROR;
201             break;
202     }
203 
204     return ret;
205 }
206 
csi_spi_cp_format(csi_spi_t * spi,csi_spi_cp_format_t format)207 csi_error_t csi_spi_cp_format(csi_spi_t *spi, csi_spi_cp_format_t format)
208 {
209     CSI_PARAM_CHK(spi, CSI_ERROR);
210 
211     csi_error_t   ret = CSI_OK;
212 
213     switch (format) {
214         case SPI_FORMAT_CPOL0_CPHA0:
215             ///< TODO:设置SPI时钟的极性
216             ///< TODO:设置SPI时钟的相位
217             break;
218 
219         case SPI_FORMAT_CPOL0_CPHA1:
220             ///< TODO:设置SPI时钟的极性
221             ///< TODO:设置SPI时钟的相位
222             break;
223 
224         case SPI_FORMAT_CPOL1_CPHA0:
225             ///< TODO:设置SPI时钟的极性
226             ///< TODO:设置SPI时钟的相位
227             break;
228 
229         case SPI_FORMAT_CPOL1_CPHA1:
230             ///< TODO:设置SPI时钟的极性
231             ///< TODO:设置SPI时钟的相位
232             break;
233 
234         default:
235             ret = CSI_ERROR;
236             break;
237     }
238 
239     return ret;
240 }
241 
csi_spi_baud(csi_spi_t * spi,uint32_t baud)242 uint32_t csi_spi_baud(csi_spi_t *spi, uint32_t baud)
243 {
244     CSI_PARAM_CHK(spi,  CSI_ERROR);
245     CSI_PARAM_CHK(baud, CSI_ERROR);
246 
247     uint32_t freq = 0U;
248 
249     ///< TODO:根据SPI工作频率设置传输频率(baud)
250     ///< TODO:获取SPI时钟的分频div
251     ///< TODO:根据分频div获取SPI实际传输的频率
252 
253     return freq;
254 
255 }
256 
csi_spi_frame_len(csi_spi_t * spi,csi_spi_frame_len_t length)257 csi_error_t csi_spi_frame_len(csi_spi_t *spi, csi_spi_frame_len_t length)
258 {
259     CSI_PARAM_CHK(spi, CSI_ERROR);
260 
261     csi_error_t ret = CSI_OK;
262 
263     if ((length < SPI_FRAME_LEN_4) || (length > SPI_FRAME_LEN_16)) {
264         ret = CSI_ERROR;
265     } else {
266         ///< TODO:设置SPI数据帧的大小
267     }
268 
269     return ret;
270 }
271 
csi_spi_send(csi_spi_t * spi,const void * data,uint32_t size,uint32_t timeout)272 int32_t csi_spi_send(csi_spi_t *spi, const void *data, uint32_t size, uint32_t timeout)
273 {
274     CSI_PARAM_CHK(spi,  CSI_ERROR);
275     CSI_PARAM_CHK(data, CSI_ERROR);
276     CSI_PARAM_CHK(size, CSI_ERROR);
277 
278     int32_t  ret   = CSI_OK;
279 
280     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
281         ret = CSI_BUSY;
282         return ret;
283     }
284 
285     spi->state.writeable = 0U;
286 
287     ///< TODO:关闭SPI
288     ///< TODO:设置SPI为发送模式
289     ///< TODO:设置SPI发送FIFO的阈值
290     ///< TODO:打开SPI
291 
292 
293     ///< TODO:轮询发送数据,超时则超时退出
294     ///< TODO:发送完成后在一定时间内判断发送FIFO是否为空,空则退出,不空则超时退出
295     ///< TODO:发送完成后在一定时间内判断SPI BUSY是否为0,0则退出,不为0则超时退出
296 
297     spi->state.writeable = 1U;
298 
299     return ret;
300 }
301 
csi_spi_send_async(csi_spi_t * spi,const void * data,uint32_t size)302 csi_error_t csi_spi_send_async(csi_spi_t *spi, const void *data, uint32_t size)
303 {
304     CSI_PARAM_CHK(spi,  CSI_ERROR);
305     CSI_PARAM_CHK(data, CSI_ERROR);
306     CSI_PARAM_CHK(size, CSI_ERROR);
307 
308     csi_error_t ret = CSI_OK;
309 
310     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
311         ret = CSI_BUSY;
312     }
313 
314     if ((ret == CSI_OK) && (spi->callback != NULL)) {
315         if (spi->send) {
316             spi->state.writeable = 0U;
317             ///< TODO:调用spi->send发送数据
318         } else {
319             spi->state.writeable = 0U;
320             ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
321             csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
322             csi_irq_enable((uint32_t)spi->dev.irq_num);
323             ///< TODO:调用dw_spi_send_intr中断模式发送数据
324         }
325     } else {
326         ret = CSI_ERROR;
327     }
328 
329     return ret;
330 }
331 
dw_spi_send_intr(csi_spi_t * spi,const void * data,uint32_t size)332 static csi_error_t dw_spi_send_intr(csi_spi_t *spi, const void *data, uint32_t size)
333 {
334     csi_error_t ret = CSI_OK;
335     spi->tx_data = (uint8_t *)data;
336 
337     ///< TODO:关闭SPI
338     ///< TODO:设置SPI为发送模式
339     ///< TODO:设置SPI发送FIFO的阈值
340     ///< TODO:打开SPI
341     ///< TODO:打开SPI发送FIFO空中断
342 
343     return ret;
344 }
345 
dw_spi_send_dma(csi_spi_t * spi,const void * data,uint32_t size)346 static csi_error_t dw_spi_send_dma(csi_spi_t *spi, const void *data, uint32_t size)
347 {
348     CSI_PARAM_CHK(spi,  CSI_ERROR);
349     CSI_PARAM_CHK(data, CSI_ERROR);
350     CSI_PARAM_CHK(size, CSI_ERROR);
351 
352     csi_dma_ch_config_t config;
353     csi_dma_ch_t        *dma_ch;
354     csi_error_t         ret = CSI_OK;
355 
356     dma_ch   = (csi_dma_ch_t *)spi->tx_dma;
357     spi->tx_data = (uint8_t *)data;
358     memset(&config, 0, sizeof(csi_dma_ch_config_t));
359 
360     ///< TODO:配置DMA的config.src_tw和config.dst_tw
361     config.src_inc = DMA_ADDR_INC;
362     config.dst_inc = DMA_ADDR_CONSTANT;
363     config.trans_dir = DMA_MEM2PERH;
364     ///< TODO:配置SPI的硬件握手号config.handshake
365 
366     ///< 配置DMA通道
367     csi_dma_ch_config(dma_ch, &config);
368 
369     ///< TODO:关闭SPI
370     ///< TODO:设置SPI为发送模式
371     ///< TODO:使能SPI发送DMA
372 
373     soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size);
374     ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道
375 
376     ///< TODO:打开SPI
377 
378     return ret;
379 }
380 
csi_spi_receive(csi_spi_t * spi,void * data,uint32_t size,uint32_t timeout)381 int32_t csi_spi_receive(csi_spi_t *spi, void *data, uint32_t size, uint32_t timeout)
382 {
383     CSI_PARAM_CHK(spi,  CSI_ERROR);
384     CSI_PARAM_CHK(data, CSI_ERROR);
385     CSI_PARAM_CHK(size, CSI_ERROR);
386 
387     int32_t  ret = CSI_OK;
388 
389     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
390         ret = CSI_BUSY;
391         return ret;
392     }
393 
394     spi->state.readable = 0U;
395     spi->rx_data = (uint8_t *)data;
396 
397     ///< 关闭SPI
398     ///< 设置SPI为接收模式
399     ///< 设置SPI接收数据的大小
400     ///< 打开SPI
401 
402     ///< TODO:轮询接收数据,超时则超时退出
403     ///< TODO:接收完成后再一定时间内判断SPI BUSY是否为0,为0则退出,不为0则超时退出
404 
405     spi->state.readable = 1U;
406 
407     return ret;
408 }
409 
410 
csi_spi_receive_async(csi_spi_t * spi,void * data,uint32_t size)411 csi_error_t csi_spi_receive_async(csi_spi_t *spi, void *data, uint32_t size)
412 {
413     CSI_PARAM_CHK(spi, CSI_ERROR);
414     CSI_PARAM_CHK(data, CSI_ERROR);
415     CSI_PARAM_CHK(size, CSI_ERROR);
416 
417     csi_error_t ret = CSI_OK;
418 
419     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
420         ret = CSI_BUSY;
421     } else {
422 
423         if ((ret == CSI_OK) && (spi->callback != NULL)) {
424             if (spi->receive) {
425                 spi->state.readable = 0U;
426                 ret = spi->receive(spi, data, size);
427             } else {
428                 spi->state.readable = 0U;
429                 ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
430                 csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
431                 csi_irq_enable((uint32_t)spi->dev.irq_num);
432                 ///< 调用dw_spi_receive_intr中断模式接收数据
433                 ret = dw_spi_receive_intr(spi, data, size);
434             }
435         } else {
436             ret = CSI_ERROR;
437         }
438     }
439 
440     return ret;
441 }
442 
dw_spi_receive_intr(csi_spi_t * spi,void * data,uint32_t size)443 static csi_error_t dw_spi_receive_intr(csi_spi_t *spi, void *data, uint32_t size)
444 {
445     csi_error_t ret = CSI_OK;
446 
447     spi->rx_data = (uint8_t *)data;
448 
449     ///< TODO:关闭SPI
450     ///< TODO:设置SPI为接收模式
451     ///< TODO:设置SPI接收数据的大小
452     ///< TODO:设置SPI接收FIFO的阈值
453     ///< TODO:打开SPI
454     ///< TODO:打开SPI接收FIFO满中断
455 
456     ///< TODO:如果SPI工作在主机模式下
457         ///< TODO:写SPI数据寄存器为0
458 
459     return ret;
460 }
461 
dw_spi_receive_dma(csi_spi_t * spi,void * data,uint32_t size)462 static csi_error_t dw_spi_receive_dma(csi_spi_t *spi, void *data, uint32_t size)
463 {
464     csi_dma_ch_config_t config;
465     csi_dma_ch_t        *dma_ch;
466     csi_error_t         ret = CSI_OK;
467 
468     dma_ch   = (csi_dma_ch_t *)spi->rx_dma;
469     spi->rx_data = (uint8_t *)data;
470     memset(&config, 0, sizeof(csi_dma_ch_config_t));
471 
472     ///< TODO:配置DMA的config.src_tw和config.dst_tw
473     config.src_inc = DMA_ADDR_CONSTANT;
474     config.dst_inc = DMA_ADDR_INC;
475     config.trans_dir = DMA_PERH2MEM;
476     ///< TODO:配置SPI的硬件握手号config.handshake
477 
478     ///< 配置DMA通道
479     csi_dma_ch_config(dma_ch, &config);
480 
481     ///< TODO:关闭SPI
482     ///< TODO:设置SPI为接收模式
483     ///< TODO:设置SPI接收数据的大小
484     ///< TODO:设置SPI接收FIFO的触发级别
485     ///< TODO:使能SPI接收DMA
486 
487     soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size);
488     ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道
489 
490     ///< TODO:打开SPI
491 
492     ///< TODO:如果SPI工作在主机模式下
493         ///< TODO:写SPI数据寄存器为0
494 
495     return ret;
496 }
497 
csi_spi_send_receive(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size,uint32_t timeout)498 int32_t csi_spi_send_receive(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size, uint32_t timeout)
499 {
500     CSI_PARAM_CHK(spi,      CSI_ERROR);
501     CSI_PARAM_CHK(data_out, CSI_ERROR);
502     CSI_PARAM_CHK(data_in,  CSI_ERROR);
503     CSI_PARAM_CHK(size,     CSI_ERROR);
504 
505     int32_t  ret   = CSI_OK;
506 
507     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
508         ret = CSI_BUSY;
509         return ret;
510     }
511 
512     spi->state.writeable = 0U;
513     spi->state.readable  = 0U;
514 
515     ///< TODO:关闭SPI
516     ///< TODO:设置SPI为发送和接收模式
517     ///< TODO:设置SPI发送FIFO的阈值
518     ///< TODO:设置SPI接收FIFO的阈值
519     ///< TODO:打开SPI
520 
521     ///< TODO:轮询发送数据
522     ///< TODO:轮询接收数据
523     ///< TODO:超时退出
524     ///< TODO:在一定时间内判断SPI的BUSY是否为0,为0退出,否则超时退出
525 
526     spi->state.writeable = 1U;
527     spi->state.readable  = 1U;
528 
529     return ret;
530 }
531 
532 
csi_spi_send_receive_async(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)533 csi_error_t csi_spi_send_receive_async(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
534 {
535     CSI_PARAM_CHK(spi, CSI_ERROR);
536     CSI_PARAM_CHK(data_out, CSI_ERROR);
537     CSI_PARAM_CHK(data_in, CSI_ERROR);
538     CSI_PARAM_CHK(size, CSI_ERROR);
539 
540     csi_error_t ret = CSI_OK;
541 
542     if ((spi->state.writeable == 0U) || (spi->state.readable == 0U)) {
543         ret = CSI_BUSY;
544     }
545 
546     if ((ret == CSI_OK) && (spi->callback != NULL)) {
547         if (spi->send_receive) {
548             spi->state.readable  = 0U;
549             spi->state.writeable = 0U;
550             ret = spi->send_receive(spi, data_out, data_in, size);
551         } else {
552             spi->state.readable  = 0U;
553             spi->state.writeable = 0U;
554             ///< 注册SPI的中断服务函数,使能中断控制器对应的中断
555             csi_irq_attach((uint32_t)spi->dev.irq_num, &dw_spi_irqhandler, &spi->dev);
556             csi_irq_enable((uint32_t)spi->dev.irq_num);
557             ///< 调用dw_spi_send_receive_intr中断模式发送接收数据
558             ret = dw_spi_send_receive_intr(spi, data_out, data_in, size);
559         }
560     } else {
561         ret = CSI_ERROR;
562     }
563 
564     return ret;
565 }
566 
dw_spi_send_receive_intr(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)567 static csi_error_t dw_spi_send_receive_intr(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
568 {
569     csi_error_t ret = CSI_OK;
570 
571     spi->tx_data = (uint8_t *)data_out;
572     spi->rx_data = (uint8_t *)data_in;
573 
574     ///< TODO:关闭SPI
575     ///< TODO:设置SPI为发送接收模式
576     ///< TODO:设置接收数据的大小
577     ///< TODO:设置发送FIFO的阈值
578     ///< TODO:设置接收FIFO的阈值
579     ///< TODO:打开SPI
580     ///< TODO:打开SPI接收FIFO满中断
581     ///< TODO:打开SPI发送FIFO空中断
582 
583     return ret;
584 }
585 
dw_spi_send_receive_dma(csi_spi_t * spi,const void * data_out,void * data_in,uint32_t size)586 static csi_error_t dw_spi_send_receive_dma(csi_spi_t *spi, const void *data_out, void *data_in, uint32_t size)
587 {
588     csi_dma_ch_config_t config;
589     csi_dma_ch_t        *dma_ch;
590     csi_error_t         ret = CSI_OK;
591     spi->tx_data = (uint8_t *)data_out;
592     memset(&config, 0, sizeof(csi_dma_ch_config_t));
593 
594     ///< TODO:配置DMA的config.src_tw和config.dst_tw
595 
596     spi->rx_data = (uint8_t *)data_in;
597 
598     dma_ch   = (csi_dma_ch_t *)spi->tx_dma;
599     config.src_inc = DMA_ADDR_INC;
600     config.dst_inc = DMA_ADDR_CONSTANT;
601     config.trans_dir = DMA_MEM2PERH;
602     ///< TODO:配置SPI的硬件握手号config.handshake
603 
604     ///< 配置发送DMA通道
605     csi_dma_ch_config(dma_ch, &config);
606 
607     dma_ch   = (csi_dma_ch_t *)spi->rx_dma;
608     config.src_inc = DMA_ADDR_CONSTANT;
609     config.dst_inc = DMA_ADDR_INC;
610     config.trans_dir = DMA_PERH2MEM;
611     ///< TODO:配置SPI的硬件握手号config.handshake
612 
613     ///< 配置接收DMA通道
614     csi_dma_ch_config(dma_ch, &config);
615 
616     ///< TODO:关闭SPI
617     ///< TODO:设置SPI为发送接收模式
618     ///< TODO:设置SPI接收数据的大小
619     ///< TODO:设置SPI接收数据FIFO的触发级别
620     ///< TODO:使能SPI接收DMA
621     ///< TODO:使能SPI发送DMA
622 
623     ///< 打开发送接收的DMA通道
624 
625     soc_dcache_clean_invalid_range((unsigned long)spi->tx_data, size);
626     soc_dcache_clean_invalid_range((unsigned long)spi->rx_data, size);
627     ///< TODO:调用csi_dma_ch_start打开SPI接收数据的DMA通道
628     ///< TODO:调用csi_dma_ch_start打开SPI发送数据的DMA通道
629 
630     ///< TODO:打开SPI
631     return ret;
632 }
633 
csi_spi_get_state(csi_spi_t * spi,csi_state_t * state)634 csi_error_t csi_spi_get_state(csi_spi_t *spi, csi_state_t *state)
635 {
636     CSI_PARAM_CHK(spi, CSI_ERROR);
637     CSI_PARAM_CHK(state, CSI_ERROR);
638 
639     *state = spi->state;
640     return CSI_OK;
641 }
642 
csi_spi_link_dma(csi_spi_t * spi,csi_dma_ch_t * tx_dma,csi_dma_ch_t * rx_dma)643 csi_error_t csi_spi_link_dma(csi_spi_t *spi, csi_dma_ch_t *tx_dma, csi_dma_ch_t *rx_dma)
644 {
645     CSI_PARAM_CHK(spi, CSI_ERROR);
646 
647     csi_error_t ret = CSI_OK;
648 
649     if (tx_dma != NULL) {
650         tx_dma->parent = spi;
651         ///< 申请DMA通道
652         ret = csi_dma_ch_alloc(tx_dma, -1, -1);
653 
654         if (ret == CSI_OK) {
655             ///< 注册DMA传输完成中断回调服务函数
656             csi_dma_ch_attach_callback(tx_dma, dw_spi_dma_event_cb, NULL);
657             spi->tx_dma = tx_dma;
658             spi->send = dw_spi_send_dma;
659         } else {
660             tx_dma->parent = NULL;
661         }
662     } else {
663         if (spi->tx_dma) {
664             ///< 注销DMA传输完成中断回调服务函数,释放DMA通道
665             csi_dma_ch_detach_callback(spi->tx_dma);
666             csi_dma_ch_free(spi->tx_dma);
667             spi->tx_dma = NULL;
668         }
669 
670         spi->send = NULL;
671     }
672 
673     if (ret == CSI_OK) {
674         if (rx_dma != NULL) {
675             rx_dma->parent = spi;
676             ///< 申请DMA通道
677             ret = csi_dma_ch_alloc(rx_dma, -1, -1);
678 
679             if (ret == CSI_OK) {
680                 ///< 注册DMA传输完成中断回调服务函数
681                 csi_dma_ch_attach_callback(rx_dma, dw_spi_dma_event_cb, NULL);
682                 spi->rx_dma = rx_dma;
683                 ///< 调用DMA接收函数开启DMA的接收
684                 spi->receive = dw_spi_receive_dma;
685             } else {
686                 rx_dma->parent = NULL;
687             }
688         } else {
689             if (spi->rx_dma) {
690                 ///< 注销DMA传输完成中断回调服务函数,释放DMA通道
691                 csi_dma_ch_detach_callback(spi->rx_dma);
692                 csi_dma_ch_free(spi->rx_dma);
693                 spi->rx_dma = NULL;
694             }
695 
696             spi->receive = NULL;
697         }
698     }
699 
700 
701     if (ret == CSI_OK) {
702         if ((tx_dma != NULL) && (rx_dma != NULL)) {
703             ///< 调用DMA发送接收函数开启DMA的发送接收
704             spi->send_receive =  dw_spi_send_receive_dma;
705         } else {
706             spi->send_receive = NULL;
707         }
708     }
709 
710     return ret;
711 }
712 
csi_spi_select_slave(csi_spi_t * spi,uint32_t slave_num)713 void csi_spi_select_slave(csi_spi_t *spi, uint32_t slave_num)
714 {
715     CSI_PARAM_CHK_NORETVAL(spi);
716 
717     ///< TODO:使能SPI的从机
718 }
719 
720 #ifdef CONFIG_PM
dw_spi_pm_action(csi_dev_t * dev,csi_pm_dev_action_t action)721 csi_error_t dw_spi_pm_action(csi_dev_t *dev, csi_pm_dev_action_t action)
722 {
723     CSI_PARAM_CHK(dev, CSI_ERROR);
724 
725     csi_error_t ret = CSI_OK;
726     csi_pm_dev_t *pm_dev = &dev->pm_dev;
727 
728     switch (action) {
729         case PM_DEV_SUSPEND:
730             ///< TODO:恢复SPI寄存器
731             break;
732 
733         case PM_DEV_RESUME:
734             ///< TODO:保存SPI寄存器
735             break;
736 
737         default:
738             ret = CSI_ERROR;
739             break;
740     }
741 
742     return ret;
743 }
744 
csi_spi_enable_pm(csi_spi_t * spi)745 csi_error_t csi_spi_enable_pm(csi_spi_t *spi)
746 {
747     ///< TODO:注册WDT低功耗处理函数dw_spi_pm_action
748 }
749 
csi_spi_disable_pm(csi_spi_t * spi)750 void csi_spi_disable_pm(csi_spi_t *spi)
751 {
752     csi_pm_dev_unregister(&spi->dev);
753 }
754 #endif
755