1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /******************************************************************************
18  * @file     dw_spi.c
19  * @brief    CSI Source File for SPI Driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23 #include "csi_core.h"
24 #include "drv_spi.h"
25 #include "dw_spi.h"
26 #include "drv_gpio.h"
27 #ifdef CONFIG_SPI_DMA
28 #include "ck_dmac.h"
29 #include <string.h>
30 #endif
31 #include "soc.h"   /*CONFIG_SPI_NUM*/
32 
33 #define ERR_SPI(errno) (CSI_DRV_ERRNO_SPI_BASE | errno)
34 
35 #define SPI_NULL_PARAM_CHK(para)                  \
36     do {                                        \
37         if (para == NULL) {                     \
38             return ERR_SPI(EDRV_PARAMETER);   \
39         }                                       \
40     } while (0)
41 
42 typedef struct {
43     uint32_t base;
44     uint32_t irq;
45     pin_t ssel;
46     spi_event_cb_t cb_event;
47     void *cb_arg;
48     uint32_t send_num;
49     uint32_t recv_num;
50     uint8_t *send_buf;
51     uint8_t *recv_buf;
52     uint8_t enable_slave;
53     uint32_t transfer_num;
54     uint32_t clk_num;            //clock number with a process of communication
55     uint8_t state;              //Current SPI state
56     uint32_t mode;               //Current SPI mode
57     uint8_t ss_mode;
58     spi_status_t status;
59 #ifdef CONFIG_SPI_DMA
60     dmac_handle_t dma_handle;
61     int32_t dma_tx_id;
62     int32_t dma_rx_id;
63 #endif
64 } dw_spi_priv_t;
65 
66 static dw_spi_priv_t spi_instance[CONFIG_SPI_NUM];
67 static gpio_pin_handle_t   pgpio_pin_handle;
68 
69 static const spi_capabilities_t spi_capabilities = {
70     .simplex = 1,           /* Simplex Mode (Master and Slave) */
71     .ti_ssi = 1,            /* TI Synchronous Serial Interface */
72     .microwire = 1,         /* Microwire Interface */
73     .event_mode_fault = 0   /* Signal Mode Fault event: \ref CSKY_SPI_EVENT_MODE_FAULT */
74 };
75 
76 static int32_t dw_spi_set_datawidth(dw_spi_reg_t *addr, DWENUM_SPI_DATAWIDTH datawidth);
77 static int32_t dw_spi_set_mode(spi_handle_t handle, DWENUM_SPI_MODE mode);
78 
79 /**
80   \brief use phobos gpio pin to simulate ss line for hardware controlled Output mode.
81 */
dw_spi_ss_init(dw_spi_priv_t * spi_priv)82 static int32_t dw_spi_ss_init(dw_spi_priv_t *spi_priv)
83 {
84     csi_gpio_port_initialize(0, NULL);
85     pgpio_pin_handle = csi_gpio_pin_initialize(spi_priv->ssel);
86     csi_gpio_pin_config(pgpio_pin_handle, GPIO_MODE_PULLNONE, GPIO_DIRECTION_OUTPUT);
87     csi_gpio_pin_write(pgpio_pin_handle, true);
88     spi_priv->ss_mode = SPI_SS_MASTER_HW_OUTPUT;
89     return 0;
90 }
91 
92 /**
93   \brief control ss line depend on controlled Output mode.
94 */
dw_spi_ss_control(dw_spi_priv_t * spi_priv,spi_ss_stat_e stat)95 static int32_t dw_spi_ss_control(dw_spi_priv_t *spi_priv, spi_ss_stat_e stat)
96 {
97     if (spi_priv->ss_mode == SPI_SS_MASTER_HW_OUTPUT) {
98         if (stat == SPI_SS_INACTIVE) {
99             csi_gpio_pin_write(pgpio_pin_handle, true);
100         } else if (stat == SPI_SS_ACTIVE) {
101             csi_gpio_pin_write(pgpio_pin_handle, false);
102         } else {
103             return -1;
104         }
105     }
106 
107     return 0;
108 }
109 
110 #ifdef CONFIG_SPI_DMA
dw_spi_dma_event_cb(dma_event_e event,int32_t ch)111 void dw_spi_dma_event_cb(dma_event_e event, int32_t ch)
112 {
113     dw_spi_priv_t *spi_priv = NULL;
114 
115     uint8_t i = 0u;
116 
117     for (i = 0; i < CONFIG_SPI_NUM; i++) { /* find the SPI id */
118         spi_priv = &spi_instance[i];
119 
120         if ((spi_priv->dma_tx_id == ch) || (spi_priv->dma_rx_id == ch)) {
121             break;
122         }
123     }
124 
125 
126     if (spi_priv->dma_tx_id == ch) {
127         spi_priv->dma_tx_id = -1;
128     } else {
129         spi_priv->dma_rx_id = -1;
130     }
131 
132     if (event == DMA_EVENT_TRANSFER_ERROR) {           /* DMA transfer ERROR */
133 
134         if (spi_priv->cb_event) {
135             spi_priv->cb_event(SPI_EVENT_DATA_LOST, NULL);
136         }
137     } else if (event == DMA_EVENT_TRANSFER_DONE) {  /* DMA transfer complete */
138 
139         if (spi_priv->mode == DWENUM_SPI_TXRX) {
140             if (spi_priv->cb_event) {
141                 spi_priv->cb_event(SPI_EVENT_TRANSFER_COMPLETE, spi_priv->cb_arg);
142             }
143         } else if (spi_priv->mode == DWENUM_SPI_TX) {
144             dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
145 
146             while (addr->SR & DW_SPI_DISABLE);
147 
148             if (spi_priv->cb_event) {
149                 spi_priv->cb_event(SPI_EVENT_TX_COMPLETE, spi_priv->cb_arg);
150             }
151         } else {
152             if (spi_priv->cb_event) {
153                 spi_priv->cb_event(SPI_EVENT_RX_COMPLETE, spi_priv->cb_arg);
154             }
155         }
156     }
157 
158     spi_priv->status.busy = 0U;
159 }
160 
161 /**
162   \brief sending data to SPI transmitter with DMA,(received data is ignored).
163 */
dw_spi_dma_send(dw_spi_priv_t * spi_priv,const void * data,uint32_t num)164 static int32_t dw_spi_dma_send(dw_spi_priv_t *spi_priv, const void *data, uint32_t num)
165 {
166     int32_t ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
167     spi_priv->dma_tx_id = ch;
168 
169     dma_config_t config;
170     config.src_inc  = DMA_ADDR_INC;
171     config.dst_inc  = DMA_ADDR_CONSTANT;
172     config.src_tw   = DMA_DATAWIDTH_SIZE8;
173     config.dst_tw   = DMA_DATAWIDTH_SIZE8;
174     config.hs_if    = CKENUM_DMA_SPI1_TX;
175     config.type     = DMA_MEM2PERH;
176 
177     dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
178 
179     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
180     uint8_t *ptxbuffer = (uint8_t *)data;
181 
182     int32_t ret = csi_dma_config(spi_priv->dma_handle, ch, ptxbuffer, (uint8_t *) & (addr->DR), num, &config, dw_spi_dma_event_cb);
183 
184     if (ret < 0) {
185         return ret;
186     }
187 
188     addr->SPIENR    = DW_SPI_DISABLE; /* enable SPI */
189     dw_spi_set_mode(spi_priv, DWENUM_SPI_TX);
190 
191     addr->DMATDLR   = 0;
192     addr->DMACR     = DW_SPI_TDMAE;
193     addr->SER       = spi_priv->enable_slave;
194     addr->SPIENR  = DW_SPI_ENABLE;
195     csi_dma_start(spi_priv->dma_handle, ch);
196 
197     while (csi_dma_get_status(spi_priv->dma_handle, ch) != DMA_STATE_DONE);
198 
199     while (addr->SR & DW_SPI_BUSY);
200 
201     csi_dma_stop(spi_priv->dma_handle, ch);
202     csi_dma_release_channel(spi_priv->dma_handle, ch);
203     addr->SPIENR = DW_SPI_DISABLE;
204     addr->SER = 0;
205 
206     dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
207     spi_priv->status.busy = 0U;
208     return 0;
209 
210 }
211 
212 /**
213   \brief receiving data from SPI receiver with DMA.
214 */
dw_spi_dma_receive(dw_spi_priv_t * spi_priv,void * data,uint32_t num)215 static int32_t dw_spi_dma_receive(dw_spi_priv_t *spi_priv, void *data, uint32_t num)
216 {
217     int32_t ch;
218     ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
219     spi_priv->dma_tx_id = ch;
220 
221     dma_config_t config;
222 
223     config.src_inc  = DMA_ADDR_CONSTANT;
224     config.dst_inc  = DMA_ADDR_INC;
225     config.src_tw   = DMA_DATAWIDTH_SIZE8;
226     config.dst_tw   = DMA_DATAWIDTH_SIZE8;
227     config.hs_if    = CKENUM_DMA_SPI1_RX;
228     config.type     = DMA_PERH2MEM;
229 
230     dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
231     uint8_t *prx_buffer = (uint8_t *)data;
232 
233     spi_priv->recv_buf      = prx_buffer;
234     spi_priv->clk_num       = num;
235     spi_priv->recv_num      = num;
236 
237     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
238     int32_t ret;
239 
240     while (spi_priv->clk_num) {
241         if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV / 2) {
242             spi_priv->recv_num = DW_SPI_FIFO_MAX_LV / 2;
243         }
244 
245         ret = csi_dma_config(spi_priv->dma_handle, ch, (uint8_t *) & (addr->DR), spi_priv->recv_buf, spi_priv->recv_num, &config, dw_spi_dma_event_cb);
246 
247         if (ret < 0) {
248             return ret;
249         }
250 
251         addr->SPIENR    = DW_SPI_DISABLE; /* enable SPI */
252         dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
253         addr->DMARDLR = spi_priv->recv_num - 1;
254         addr->CTRLR1 = spi_priv->recv_num - 1;
255 
256         addr->DMACR = DW_SPI_RDMAE;
257         addr->SER = spi_priv->enable_slave;
258         csi_dma_start(spi_priv->dma_handle, ch);
259         addr->SPIENR  = DW_SPI_ENABLE;
260         addr->DR = DW_SPI_START_RX;
261 
262         while (csi_dma_get_status(spi_priv->dma_handle, ch) != DMA_STATE_DONE);
263 
264         csi_dma_stop(spi_priv->dma_handle, ch);
265         spi_priv->clk_num -= spi_priv->recv_num;
266         spi_priv->recv_buf += spi_priv->recv_num;
267 
268 
269     }
270 
271     addr->SPIENR = DW_SPI_DISABLE;
272     addr->SER = 0;
273     csi_dma_release_channel(spi_priv->dma_handle, ch);
274     dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
275     spi_priv->status.busy = 0U;
276     return 0;
277 
278 }
279 
280 /**
281   \brief sending/receiving data to/from SPI transmitter/receiver with DMA.
282 */
dw_spi_dma_transfer(dw_spi_priv_t * spi_priv,const void * data_out,void * data_in,uint32_t num_out,uint32_t num_in)283 static int32_t dw_spi_dma_transfer(dw_spi_priv_t *spi_priv, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
284 {
285     int32_t tx_ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
286 
287     if (tx_ch < 0) {
288         return tx_ch;
289     }
290 
291     spi_priv->dma_tx_id = tx_ch;
292 
293     int32_t rx_ch = csi_dma_alloc_channel(spi_priv->dma_handle, -1);
294 
295     if (rx_ch < 0) {
296         return rx_ch;
297     }
298 
299     spi_priv->dma_rx_id = rx_ch;
300 
301     dma_config_t tx_config, rx_config;
302 
303     tx_config.src_inc  = DMA_ADDR_INC;
304     tx_config.dst_inc  = DMA_ADDR_CONSTANT;
305     tx_config.src_tw   = DMA_DATAWIDTH_SIZE8;
306     tx_config.dst_tw   = DMA_DATAWIDTH_SIZE8;
307     tx_config.hs_if    = CKENUM_DMA_SPI1_TX;
308     tx_config.type     = DMA_MEM2PERH;
309 
310     rx_config.src_inc  = DMA_ADDR_CONSTANT;
311     rx_config.dst_inc  = DMA_ADDR_INC;
312     rx_config.src_tw   = DMA_DATAWIDTH_SIZE8;
313     rx_config.dst_tw   = DMA_DATAWIDTH_SIZE8;
314     rx_config.hs_if    = CKENUM_DMA_SPI1_RX;
315     rx_config.type     = DMA_PERH2MEM;
316 
317     dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
318 
319     uint8_t *ptx_buffer = (uint8_t *)data_out;
320     uint8_t *prx_buffer = (uint8_t *)data_in;
321     spi_priv->send_buf      = ptx_buffer;
322     spi_priv->recv_buf      = prx_buffer;
323     spi_priv->send_num      = num_out;
324     spi_priv->recv_num      = num_in;
325     spi_priv->clk_num       = num_in;
326 
327     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
328     int32_t ret;
329     uint8_t dma_send_buf[DW_SPI_FIFO_MAX_LV];
330 
331     while (spi_priv->clk_num) {
332         if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
333             spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
334         } else {
335             spi_priv->transfer_num = spi_priv->clk_num;
336         }
337 
338         if (spi_priv->send_num >= spi_priv->transfer_num) {
339             memcpy(dma_send_buf, spi_priv->send_buf, spi_priv->transfer_num);
340             spi_priv->send_num -= spi_priv->transfer_num;
341             spi_priv->send_buf += spi_priv->transfer_num;
342         } else {
343             if (spi_priv->send_num > 0) {
344                 memcpy(dma_send_buf, spi_priv->send_buf, spi_priv->send_num);
345                 spi_priv->send_buf = NULL;
346             }
347 
348             memset(&dma_send_buf[spi_priv->send_num], 0, spi_priv->transfer_num - spi_priv->send_num);
349             spi_priv->send_num = 0;
350         }
351 
352         ret = csi_dma_config(spi_priv->dma_handle, tx_ch, dma_send_buf, (uint8_t *) & (addr->DR), spi_priv->transfer_num, &tx_config, dw_spi_dma_event_cb);
353 
354         if (ret < 0) {
355             return ret;
356         }
357 
358         ret = csi_dma_config(spi_priv->dma_handle, rx_ch, (uint8_t *) & (addr->DR), spi_priv->recv_buf, spi_priv->transfer_num, &rx_config, dw_spi_dma_event_cb);
359 
360         if (ret < 0) {
361             return ret;
362         }
363 
364         addr->SPIENR    = DW_SPI_DISABLE;   /* disable SPI */
365         addr->DMARDLR = (spi_priv->transfer_num - 1) % 16;          /* set dma receive data level */
366         addr->DMATDLR = (spi_priv->transfer_num - 1) % 16 + 1;      /* set dma transmit data level */
367         addr->DMACR   = DW_SPI_RDMAE | DW_SPI_TDMAE;
368         dw_spi_set_mode(spi_priv, DWENUM_SPI_TXRX);
369         addr->SER = spi_priv->enable_slave;
370         addr->SPIENR    = DW_SPI_ENABLE;    /* enable SPI */
371 
372         ret = csi_dma_start(spi_priv->dma_handle, tx_ch);
373 
374         if (ret < 0) {
375             return ret;
376         }
377 
378         while (csi_dma_get_status(spi_priv->dma_handle, tx_ch) != DMA_STATE_DONE);
379 
380         ret = csi_dma_start(spi_priv->dma_handle, rx_ch);
381 
382         if (ret < 0) {
383             return ret;
384         }
385 
386         while (csi_dma_get_status(spi_priv->dma_handle, rx_ch) != DMA_STATE_DONE);
387 
388         spi_priv->recv_buf      += spi_priv->transfer_num;
389         spi_priv->recv_num      -= spi_priv->transfer_num;
390         spi_priv->clk_num       -= spi_priv->transfer_num;
391         addr->SPIENR            = DW_SPI_DISABLE;
392         csi_dma_stop(spi_priv->dma_handle, tx_ch);
393         csi_dma_stop(spi_priv->dma_handle, rx_ch);
394     }
395 
396     dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
397     addr->SER = 0;
398 
399     csi_dma_release_channel(spi_priv->dma_handle, tx_ch);
400     csi_dma_release_channel(spi_priv->dma_handle, rx_ch);
401     spi_priv->status.busy = 0U;
402 
403     return 0;
404 
405 }
406 #endif
407 
408 
409 /**
410   \brief       Set the SPI datawidth.
411   \param[in]   addr pointer to register address
412   \param[in]   datawidth  date frame size
413   \return      error code
414 */
dw_spi_set_datawidth(dw_spi_reg_t * addr,DWENUM_SPI_DATAWIDTH datawidth)415 static int32_t dw_spi_set_datawidth(dw_spi_reg_t *addr, DWENUM_SPI_DATAWIDTH datawidth)
416 {
417     if ((datawidth >= DWENUM_SPI_DATASIZE_4) && (datawidth <= DWENUM_SPI_DATASIZE_16)) {
418         uint16_t temp = addr->CTRLR0;
419         temp &= 0xfff0;         /* temp has the value of CTRLR0 with DFS being cleared.*/
420         temp |= (datawidth);    /* get the final CTRLR0 after datawidth config. */
421         addr->CTRLR0 = temp;    /* write CTRLR0 */
422         return 0;
423     }
424 
425     return -1;
426 }
427 
428 /**
429   \brief       Set the SPI clock divider.
430   \param[in]   addr     pointer to register address
431   \param[in]   baud     spi baud rate
432   \param[in]   apbfreq  sysclk for spi module.
433   \return      error code
434 */
dw_spi_set_baudrate(dw_spi_reg_t * addr,int32_t baud,int32_t apbfreq)435 static int32_t dw_spi_set_baudrate(dw_spi_reg_t *addr, int32_t baud, int32_t apbfreq)
436 {
437     int32_t sckdv = apbfreq / baud;
438 
439     if (sckdv < 0x10000) {
440         addr->BAUDR =  sckdv;
441     } else {
442         return -1;
443     }
444 
445     return 0;
446 }
447 
448 /**
449   \brief       Set the SPI polarity.
450   \param[in]   addr  pointer to register address
451   \param[in]   polarity spi polarity
452   \return      error code
453 */
dw_spi_set_polarity(dw_spi_reg_t * addr,DWENUM_SPI_POLARITY polarity)454 static int32_t dw_spi_set_polarity(dw_spi_reg_t *addr, DWENUM_SPI_POLARITY polarity)
455 {
456     /* To config the polarity, we can set the SCPOL bit(CTRLR0[7]) as below:
457      *     0 - inactive state of serial clock is low
458      *     1 - inactive state of serial clock is high
459      */
460     switch (polarity) {
461         case DWENUM_SPI_CLOCK_POLARITY_LOW:
462             addr->CTRLR0 &= (~DW_SPI_POLARITY);
463             break;
464 
465         case DWENUM_SPI_CLOCK_POLARITY_HIGH:
466             addr->CTRLR0 |= DW_SPI_POLARITY;
467             break;
468 
469         default:
470             return -1;
471     }
472 
473     return 0;
474 }
475 
476 /**
477   \brief       Set the SPI Phase.
478   \param[in]   addr  pointer to register address
479   \param[in]   phase    Serial clock phase
480   \return      error code
481 */
dw_spi_set_phase(dw_spi_reg_t * addr,DWENUM_SPI_PHASE phase)482 static int32_t dw_spi_set_phase(dw_spi_reg_t *addr, DWENUM_SPI_PHASE phase)
483 {
484     switch (phase) {
485         case DWENUM_SPI_CLOCK_PHASE_MIDDLE:
486             addr->CTRLR0 &= (~DW_SPI_PHASE);
487             break;
488 
489         case DWENUM_SPI_CLOCK_PHASE_START:
490             addr->CTRLR0 |= DW_SPI_PHASE;
491             break;
492 
493         default:
494             return -1;
495     }
496 
497     return 0;
498 }
499 
500 /**
501   \brief       Set the SPI mode.
502   \param[in]   addr  pointer to register address
503   \param[in]   mode     SPI_Mode
504   \return      error code
505 */
dw_spi_set_mode(spi_handle_t handle,DWENUM_SPI_MODE mode)506 static int32_t dw_spi_set_mode(spi_handle_t handle, DWENUM_SPI_MODE mode)
507 {
508     dw_spi_priv_t *spi_priv = handle;
509     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
510 
511     /* It is impossible to write to this register when the SSI is enabled.*/
512     /* we can set the TMOD to config transfer mode as below:
513      *     TMOD_BIT9  TMOD_BIT8      transfer mode
514      *         0          0         transmit & receive
515      *         0          1           transmit only
516      *         1          0           receive only
517      *         1          1             reserved
518      */
519     switch (mode) {
520         case DWENUM_SPI_TXRX:
521             addr->CTRLR0 &= (~DW_SPI_TMOD_BIT8);
522             addr->CTRLR0 &= (~DW_SPI_TMOD_BIT9);
523             break;
524 
525         case DWENUM_SPI_TX:
526             addr->CTRLR0 |= DW_SPI_TMOD_BIT8;
527             addr->CTRLR0 &= (~DW_SPI_TMOD_BIT9);
528             break;
529 
530         case DWENUM_SPI_RX:
531             addr->CTRLR0 &= (~DW_SPI_TMOD_BIT8);
532             addr->CTRLR0 |= DW_SPI_TMOD_BIT9;
533             break;
534 
535         default:
536             addr->CTRLR0 |= DW_SPI_TMOD_BIT8;
537             addr->CTRLR0 |= DW_SPI_TMOD_BIT9;
538             break;
539     }
540 
541     spi_priv->mode = mode;
542     return 0;
543 }
544 
545 /**
546   \brief       interrupt service function for receive FIFO full interrupt .
547   \param[in]   spi_priv pointer to spi private.
548 */
dw_spi_intr_rx_full(dw_spi_priv_t * spi_priv)549 static void dw_spi_intr_rx_full(dw_spi_priv_t *spi_priv)
550 {
551     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
552 
553     uint8_t temp = addr->ICR;
554     uint8_t *pbuffer = spi_priv->recv_buf;
555     uint32_t length = spi_priv->recv_num;
556 
557 
558     uint8_t rxnum;
559     rxnum = addr->RXFLR;
560     uint32_t i = 0u;
561 
562     for (i = 0; i < rxnum; i++) {
563         *pbuffer = addr->DR;
564         pbuffer++;
565     }
566 
567     length -= rxnum;
568 
569     if (length < DW_SPI_FIFO_MAX_LV) {
570         addr->RXFTLR = length - 1;
571     }
572 
573     if (length <= 0) {
574         temp = addr->IMR;
575         temp &= 0x2f;
576         addr->IMR = temp;
577 
578         addr->SER = 0;
579         addr->SPIENR = DW_SPI_DISABLE;
580         spi_priv->status.busy = 0U;
581 
582         dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
583 
584         if (spi_priv->cb_event) {
585             spi_priv->cb_event(SPI_EVENT_RX_COMPLETE, spi_priv->cb_arg);
586             return;
587         }
588     } else {
589         addr->SPIENR    = DW_SPI_DISABLE;   /* disable SPI */
590         dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
591         addr->SER = spi_priv->enable_slave; /* enable all cs */
592         spi_priv->recv_buf = pbuffer;
593         spi_priv->recv_num = length;
594 
595         if (spi_priv->recv_num > DW_SPI_FIFO_MAX_LV) {
596             addr->RXFTLR = DW_SPI_FIFO_MAX_LV - 1;
597             addr->CTRLR1 = DW_SPI_FIFO_MAX_LV - 1;
598         } else {
599             addr->RXFTLR = spi_priv->recv_num - 1;
600             addr->CTRLR1 = spi_priv->recv_num - 1;
601         }
602 
603         addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
604         addr->DR = DW_SPI_START_RX ;
605     }
606 
607 }
608 
609 /**
610   \brief       interrupt service function for transmit FIFO empty interrupt.
611   \param[in]   spi_priv pointer to spi private.
612 */
dw_spi_intr_tx_empty(dw_spi_priv_t * spi_priv)613 static void dw_spi_intr_tx_empty(dw_spi_priv_t *spi_priv)
614 {
615     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
616     uint8_t temp = addr->ICR;
617 
618     /* transfer mode:transmit & receive */
619     uint32_t i = 0u;
620 
621     if (spi_priv->
622         mode == DWENUM_SPI_TXRX) {
623         /* read data out from rx FIFO */
624         while (spi_priv->transfer_num) {
625             *spi_priv->recv_buf = addr->DR;
626             spi_priv->recv_buf++;
627             spi_priv->transfer_num--;
628         }
629 
630         if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
631             spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
632         } else {
633             spi_priv->transfer_num = spi_priv->clk_num;
634         }
635 
636         for (i = 0; i < spi_priv->transfer_num; i++) {
637             if (spi_priv->send_num == 0) {
638                 addr->DR = 0x0;
639             } else {
640                 addr->DR = *spi_priv->send_buf;
641                 spi_priv->send_buf++;
642             }
643 
644             spi_priv->send_num--;
645         }
646     } else {    //transfer mode :transmit only
647         if (spi_priv->clk_num >= DW_SPI_FIFO_MAX_LV) {
648             spi_priv->transfer_num = DW_SPI_FIFO_MAX_LV;
649         } else {
650             spi_priv->transfer_num = spi_priv->clk_num;
651         }
652 
653         for (i = 0; i < spi_priv->transfer_num; i++) {
654             addr->DR = *spi_priv->send_buf;
655             spi_priv->send_buf++;
656             spi_priv->send_num--;
657         }
658 
659     }
660 
661     if (spi_priv->clk_num == 0) {
662 
663         temp = addr->IMR;
664         temp &= ~DW_SPI_IMR_TXEIM;
665         addr->IMR = temp;
666 
667         addr->SER = 0;
668         addr->SPIENR = DW_SPI_DISABLE;
669         spi_priv->status.busy = 0U;
670 
671         dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
672 
673         if (spi_priv->mode == DWENUM_SPI_TXRX) {
674             if (spi_priv->cb_event) {
675                 spi_priv->cb_event(SPI_EVENT_TRANSFER_COMPLETE, spi_priv->cb_arg);
676                 return;
677             }
678         } else {
679             if (spi_priv->cb_event) {
680                 spi_priv->cb_event(SPI_EVENT_TX_COMPLETE, spi_priv->cb_arg);
681                 return;
682             }
683         }
684     }
685 
686     spi_priv->clk_num -= spi_priv->transfer_num;
687 
688 }
689 /**
690   \brief       handler the interrupt.
691   \param[in]   spi      Pointer to \ref SPI_RESOURCES
692 */
dw_spi_irqhandler(int32_t idx)693 void dw_spi_irqhandler(int32_t idx)
694 {
695     dw_spi_priv_t *spi_priv = &spi_instance[idx];
696     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
697 
698     uint32_t intr = addr->ISR;
699 
700     /* deal with receive FIFO full interrupt */
701     if (intr & DW_SPI_RXFIFO_FULL) {
702         dw_spi_intr_rx_full(spi_priv);
703     }
704     /* deal with transmit FIFO empty interrupt */
705     else if (intr & DW_SPI_TXFIFO_EMPTY) {
706         dw_spi_intr_tx_empty(spi_priv);
707     }
708 }
709 
target_spi_init(pin_t mosi,pin_t miso,pin_t sclk,pin_t ssel,uint32_t * base,uint32_t * irq)710 int32_t __attribute__((weak)) target_spi_init(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, uint32_t *base, uint32_t *irq)
711 {
712     return -1;
713 }
714 
715 /**
716   \brief       Initialize SPI Interface. 1. Initializes the resources needed for the SPI interface 2.registers event callback function
717   \param[in]   spi pin of mosi
718   \param[in]   spi pin of miso
719   \param[in]   spi pin of sclk
720   \param[in]   spi pin of ssel
721   \param[in]   cb_event  event call back function \ref spi_event_cb_t
722   \return      return spi handle if success
723 */
csi_spi_initialize(pin_t mosi,pin_t miso,pin_t sclk,pin_t ssel,spi_event_cb_t cb_event,void * cb_arg)724 spi_handle_t csi_spi_initialize(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel, spi_event_cb_t cb_event, void *cb_arg)
725 {
726     uint32_t base = 0u;
727     uint32_t irq = 0u;
728 
729     int32_t idx = target_spi_init(mosi, miso, sclk, ssel, &base, &irq);
730 
731     if (idx < 0 || idx >= CONFIG_SPI_NUM) {
732         return NULL;
733     }
734 
735     dw_spi_priv_t *spi_priv = &spi_instance[idx];
736 
737     spi_priv->base = base;
738     spi_priv->irq  = irq;
739     spi_priv->ssel = ssel;
740 
741     spi_priv->cb_event          = cb_event;
742     spi_priv->cb_arg            = cb_arg;
743     spi_priv->status.busy       = 0U;
744     spi_priv->status.data_lost  = 0U;
745     spi_priv->status.mode_fault = 0U;
746     spi_priv->enable_slave      = 1U;
747     spi_priv->state             = SPI_INITIALIZED;
748 
749     drv_nvic_enable_irq(spi_priv->irq);
750 #ifdef CONFIG_SPI_DMA
751     spi_priv->dma_handle = csi_dma_initialize(0);
752 #endif
753 
754     return (spi_handle_t)spi_priv;
755 }
756 
757 /**
758   \brief       De-initialize SPI Interface. stops operation and releases the software resources used by the interface
759   \param[in]   handle spi handle to operate.
760   \return      error code
761 */
csi_spi_uninitialize(spi_handle_t handle)762 int32_t csi_spi_uninitialize(spi_handle_t handle)
763 {
764     SPI_NULL_PARAM_CHK(handle);
765 
766     dw_spi_priv_t *spi_priv = handle;
767     drv_nvic_disable_irq(spi_priv->irq);
768 
769     spi_priv->cb_event          = NULL;
770     spi_priv->state             = 0U;
771     spi_priv->status.busy       = 0U;
772     spi_priv->status.data_lost  = 0U;
773     spi_priv->status.mode_fault = 0U;
774 
775 #ifdef CONFIG_SPI_DMA
776     csi_dma_uninitialize(spi_priv->dma_handle);
777 #endif
778     return 0;
779 }
780 
781 /**
782   \brief       Get driver capabilities.
783   \param[in]   spi instance to operate.
784   \return      \ref spi_capabilities_t
785 */
csi_spi_get_capabilities(spi_handle_t handle)786 spi_capabilities_t csi_spi_get_capabilities(spi_handle_t handle)
787 {
788     return spi_capabilities;
789 }
790 
791 /**
792   \brief       config spi mode.
793   \param[in]   handle spi handle to operate.
794   \param[in]   sysclk    sysclk for spi module.
795   \param[in]   baud      spi baud rate. if negative, then this attribute not changed
796   \param[in]   mode      \ref spi_mode_e . if negative, then this attribute not changed
797   \param[in]   format    \ref spi_format_e . if negative, then this attribute not changed
798   \param[in]   order     \ref spi_bit_order_e . if negative, then this attribute not changed
799   \param[in]   ss_mode   \ref spi_ss_mode_e . if negative, then this attribute not changed
800   \param[in]   bit_width spi data bitwidth: (1 ~ SPI_DATAWIDTH_MAX) . if negative, then this attribute not changed
801   \return      error code
802 */
csi_spi_config(spi_handle_t handle,int32_t sysclk,int32_t baud,spi_mode_e mode,spi_format_e format,spi_bit_order_e order,spi_ss_mode_e ss_mode,int32_t bit_width)803 int32_t csi_spi_config(spi_handle_t handle,
804                        int32_t          sysclk,
805                        int32_t          baud,
806                        spi_mode_e       mode,
807                        spi_format_e     format,
808                        spi_bit_order_e  order,
809                        spi_ss_mode_e    ss_mode,
810                        int32_t          bit_width)
811 {
812     SPI_NULL_PARAM_CHK(handle);
813 
814     dw_spi_priv_t *spi_priv = handle;
815     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
816 
817     if ((spi_priv->state & SPI_INITIALIZED) == 0U) {
818         return ERR_SPI(EDRV_UNSUPPORTED);
819     }
820 
821     if (spi_priv->status.busy) {
822         return ERR_SPI(EDRV_BUSY);
823     }
824 
825     spi_priv->status.busy       = 0U;
826     spi_priv->status.data_lost  = 0U;
827     spi_priv->status.mode_fault = 0U;
828 
829     addr->SPIENR    = DW_SPI_DISABLE;
830     addr->IMR       = DW_SPI_INT_DISABLE;
831 
832     int32_t ret = 0;
833 
834     if (baud >= 0) {
835         ret = dw_spi_set_baudrate(addr, baud, sysclk);
836 
837         if (ret < 0) {
838             return ERR_SPI(EDRV_PARAMETER);
839         }
840     }
841 
842     if (mode >= 0) {
843         switch (mode) {
844             case SPI_MODE_MASTER:
845                 break;
846 
847             default:
848                 return ERR_SPI(EDRV_UNSUPPORTED);
849         }
850     }
851 
852     if (format >= 0) {
853         switch (format) {
854             case SPI_FORMAT_CPOL0_CPHA0:
855                 dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_LOW);
856                 dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_MIDDLE);
857                 break;
858 
859             case SPI_FORMAT_CPOL0_CPHA1:
860                 dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_LOW);
861                 dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_START);
862                 break;
863 
864             case SPI_FORMAT_CPOL1_CPHA0:
865                 dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_HIGH);
866                 dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_MIDDLE);
867                 break;
868 
869             case SPI_FORMAT_CPOL1_CPHA1:
870                 dw_spi_set_polarity(addr, DWENUM_SPI_CLOCK_POLARITY_HIGH);
871                 dw_spi_set_phase(addr, DWENUM_SPI_CLOCK_PHASE_START);
872                 break;
873 
874             default:
875                 return ERR_SPI(EDRV_PARAMETER);
876         }
877     }
878 
879     if (order >= 0) {
880         //TD:
881     }
882 
883     if (ss_mode >= 0) {
884         switch (ss_mode) {
885             case SPI_SS_MASTER_SW:
886                 spi_priv->ss_mode = SPI_SS_MASTER_SW;
887                 break;
888 
889             case SPI_SS_MASTER_HW_OUTPUT:
890                 dw_spi_ss_init(spi_priv);
891                 break;
892 
893             default:
894                 return ERR_SPI(EDRV_UNSUPPORTED);
895         }
896     }
897 
898     if (bit_width >= 0) {
899         ret = dw_spi_set_datawidth(addr, bit_width);
900 
901         if (ret < 0) {
902             return ERR_SPI(EDRV_PARAMETER);
903         }
904     }
905 
906     spi_priv->state |= SPI_CONFIGURED;
907 
908     return 0;
909 }
910 
911 /**
912   \brief       config spi default tx value.
913   \param[in]   handle spi handle to operate.
914   \param[in]   value     default tx value
915   \return      error code
916 */
csi_spi_set_default_tx_value(spi_handle_t handle,uint32_t value)917 int32_t csi_spi_set_default_tx_value(spi_handle_t handle, uint32_t value)
918 {
919     SPI_NULL_PARAM_CHK(handle);
920 
921     return ERR_SPI(EDRV_UNSUPPORTED);
922 }
923 
924 /**
925   \brief       sending data to SPI transmitter,(received data is ignored).
926                if non-blocking mode, this function only start the sending,
927                \ref spi_event_e is signaled when operation completes or error happens.
928                \ref csi_spi_get_status can indicates operation status.
929                if blocking mode, this function return after operation completes or error happens.
930   \param[in]   handle spi handle to operate.
931   \param[in]   data  Pointer to buffer with data to send to SPI transmitter. data_type is : uint8_t for 1..8 data bits, uint16_t for 9..16 data bits,uint32_t for 17..32 data bits,
932   \param[in]   num   Number of data items to send.
933   \param[in]   block_mode   blocking and non_blocking to selcect
934   \return      error code
935 */
csi_spi_send(spi_handle_t handle,const void * data,uint32_t num,uint8_t block_mode)936 int32_t csi_spi_send(spi_handle_t handle, const void *data, uint32_t num, uint8_t block_mode)
937 
938 {
939     if (handle == NULL || data == NULL || num == 0) {
940         return ERR_SPI(EDRV_PARAMETER);
941     }
942 
943     dw_spi_priv_t *spi_priv = handle;
944 
945     if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
946         return ERR_SPI(EDRV_UNSUPPORTED);
947     }
948 
949     if (spi_priv->status.busy) {
950         return ERR_SPI(EDRV_BUSY);
951     }
952 
953     spi_priv->status.busy       = 1U;
954     spi_priv->status.data_lost  = 0U;
955     spi_priv->status.mode_fault = 0U;
956 
957 
958 #ifdef CONFIG_SPI_DMA
959     return dw_spi_dma_send(spi_priv, data, num);
960 #endif
961 
962     dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
963     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
964     addr->SPIENR    = DW_SPI_DISABLE; /* disable SPI */
965     dw_spi_set_mode(spi_priv, DWENUM_SPI_TX);
966     addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
967     uint8_t *ptxbuffer = (uint8_t *)data;
968 
969     if (block_mode) {
970         addr->SER = spi_priv->enable_slave;
971         addr->TXFTLR            = DW_SPI_TXFIFO_LV;
972 
973         dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
974         spi_priv->send_num      = num;
975 
976         uint32_t once_len , i;
977 
978         while (spi_priv->send_num) {
979             once_len = (spi_priv->send_num >= DW_SPI_FIFO_MAX_LV) ?
980                        DW_SPI_FIFO_MAX_LV : spi_priv->send_num;
981 
982             for (i = 0; i < once_len; i++) {
983                 addr->DR = *ptxbuffer++;
984             }
985 
986             while (!(addr->SR & DW_SPI_TFE));
987 
988             while (addr->SR & DW_SPI_BUSY);
989 
990             spi_priv->send_num -= once_len;
991         }
992 
993         dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
994         spi_priv->status.busy   = 0U;
995     } else {
996 
997         spi_priv->send_num      = num;
998         spi_priv->clk_num       = num;
999         spi_priv->send_buf      = ptxbuffer;
1000         spi_priv->transfer_num  = 0;
1001         addr->SPIENR            = DW_SPI_ENABLE; /* enable SPI */
1002         addr->TXFTLR            = DW_SPI_TXFIFO_LV;
1003         addr->SER               = spi_priv->enable_slave;
1004         addr->IMR               = DW_SPI_IMR_TXEIM;
1005     }
1006 
1007     return 0;
1008 }
1009 
1010 /**
1011 \brief      receiving data from SPI receiver.transmits the default value as specified by csi_spi_set_default_tx_value
1012             if non-blocking mode, this function only start the receiving,
1013             \ref spi_event_e is signaled when operation completes or error happens.
1014             \ref csi_spi_get_status can indicates operation status.
1015             if blocking mode, this function return after operation completes or error happens.
1016 \param[in]  handle spi handle to operate.
1017 \param[out] data  Pointer to buffer for data to receive from SPI receiver
1018 \param[in]  num   Number of data items to receive
1019 \param[in]  block_mode   blocking and non_blocking to selcect
1020 \return     error code
1021 */
csi_spi_receive(spi_handle_t handle,void * data,uint32_t num,uint8_t block_mode)1022 int32_t csi_spi_receive(spi_handle_t handle, void *data, uint32_t num, uint8_t block_mode)
1023 {
1024 
1025     if (handle == NULL || data == NULL || num == 0) {
1026         return ERR_SPI(EDRV_PARAMETER);
1027     }
1028 
1029     dw_spi_priv_t *spi_priv = handle;
1030 
1031     if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
1032         return ERR_SPI(EDRV_UNSUPPORTED);
1033     }
1034 
1035     if (spi_priv->status.busy) {
1036         return ERR_SPI(EDRV_BUSY);
1037     }
1038 
1039     spi_priv->status.busy = 1U;
1040     spi_priv->status.data_lost = 0U;
1041     spi_priv->status.mode_fault = 0U;
1042 
1043 #ifdef CONFIG_SPI_DMA
1044     return dw_spi_dma_receive(spi_priv, data, num);
1045 #endif
1046     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
1047     uint8_t *prx_buffer = data;
1048 
1049     if (block_mode) {
1050         dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
1051 
1052         spi_priv->recv_buf = prx_buffer;
1053         spi_priv->recv_num = num;
1054 
1055 
1056         while (spi_priv->recv_num) {
1057             addr->SPIENR    = DW_SPI_DISABLE;   /* disable SPI */
1058             dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
1059             addr->SER = spi_priv->enable_slave;   /* enable all cs */
1060 
1061             uint32_t once_len = (spi_priv->recv_num >= DW_SPI_FIFO_MAX_LV) ?
1062                                 DW_SPI_FIFO_MAX_LV : spi_priv->recv_num;
1063             addr->CTRLR1 = once_len - 1;
1064             addr->RXFTLR = once_len - 1;
1065             addr->SPIENR    = DW_SPI_ENABLE;
1066             addr->DR     = 0;
1067 
1068             while (addr->RXFLR < once_len);
1069 
1070             int i = 0;
1071 
1072             for (i = 0; i < once_len; i++) {
1073                 *spi_priv->recv_buf++ = addr->DR;
1074             }
1075 
1076             spi_priv->recv_num -= once_len;
1077         }
1078 
1079         dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
1080         spi_priv->status.busy   = 0U;
1081     } else {
1082         dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
1083 
1084         addr->SPIENR    = DW_SPI_DISABLE;   /* disable SPI */
1085         spi_priv->recv_buf = prx_buffer;
1086         spi_priv->recv_num = num;
1087         dw_spi_set_mode(spi_priv, DWENUM_SPI_RX);
1088         addr->SER = spi_priv->enable_slave;   /* enable all cs */
1089 
1090         if (num > DW_SPI_FIFO_MAX_LV) {
1091             addr->RXFTLR = DW_SPI_FIFO_MAX_LV - 1;
1092             addr->CTRLR1 = DW_SPI_FIFO_MAX_LV - 1;
1093         } else {
1094             addr->RXFTLR = num - 1;
1095             addr->CTRLR1 = num - 1;
1096         }
1097 
1098         addr->IMR    = DW_SPI_IMR_RXFIM;
1099         addr->SPIENR = DW_SPI_ENABLE; /* enable SPI */
1100         addr->DR     = DW_SPI_START_RX ;
1101 
1102     }
1103 
1104     return 0;
1105 }
1106 
1107 /**
1108   \brief       sending/receiving data to/from SPI transmitter/receiver.
1109                if non-blocking mode, this function only start the transfer,
1110                \ref spi_event_e is signaled when operation completes or error happens.
1111                \ref csi_spi_get_status can indicates operation status.
1112                if blocking mode, this function return after operation completes or error happens.
1113   \param[in]   handle spi handle to operate.
1114   \param[in]   data_out  Pointer to buffer with data to send to SPI transmitter
1115   \param[out]  data_in   Pointer to buffer for data to receive from SPI receiver
1116   \param[in]   num_out      Number of data items to send
1117   \param[in]   num_in       Number of data items to receive
1118   \param[in]   block_mode   blocking and non_blocking to selcect
1119   \return      error code
1120 */
csi_spi_transfer(spi_handle_t handle,const void * data_out,void * data_in,uint32_t num_out,uint32_t num_in,uint8_t block_mode)1121 int32_t csi_spi_transfer(spi_handle_t handle, const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in, uint8_t block_mode)
1122 {
1123     if (handle == NULL || data_in == NULL || num_out == 0 || num_in == 0 || data_out == NULL) {
1124         return ERR_SPI(EDRV_PARAMETER);
1125     }
1126 
1127     dw_spi_priv_t *spi_priv = handle;
1128 
1129     if ((spi_priv->state & SPI_CONFIGURED) == 0U) {
1130         return ERR_SPI(EDRV_UNSUPPORTED);
1131     }
1132 
1133     if (spi_priv->status.busy) {
1134         return ERR_SPI(EDRV_BUSY);
1135     }
1136 
1137     spi_priv->status.busy = 1U;
1138     spi_priv->status.data_lost = 0U;
1139     spi_priv->status.mode_fault = 0U;
1140 
1141 #ifdef CONFIG_SPI_DMA
1142     return dw_spi_dma_transfer(spi_priv, data_out, data_in, num_out, num_in);
1143 #endif
1144     dw_spi_ss_control(spi_priv, SPI_SS_ACTIVE);
1145     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
1146 
1147     addr->SPIENR    = DW_SPI_DISABLE;   /* disable SPI */
1148     dw_spi_set_mode(spi_priv, DWENUM_SPI_TXRX);
1149     addr->SER = spi_priv->enable_slave;   /* enable all cs */
1150     uint8_t *ptx_buffer = (uint8_t *)data_out;
1151     uint8_t *prx_buffer = (uint8_t *)data_in;
1152     uint32_t i = 0u;
1153 
1154     if (block_mode) {
1155         for (i = 0; i < num_out; i++) { /* transmit datas in transmit-buffer */
1156             addr->DR = *ptx_buffer;
1157             ptx_buffer++;
1158         }
1159 
1160         while ((addr->SR & DW_SPI_BUSY));
1161 
1162         while ((addr->SR & DW_SPI_TFE) == 0);
1163 
1164         while ((addr->SR & DW_SPI_RFNE) == 0);
1165 
1166         addr->SPIENR    = DW_SPI_DISABLE; /* disable SPI */
1167 
1168         dw_spi_set_mode(addr, DWENUM_SPI_RX);
1169         addr->SPIENR  = DW_SPI_ENABLE;
1170         addr->DR    = DW_SPI_START_RX;
1171 
1172         for (i = 0; i < num_in; i++) {
1173             *prx_buffer = addr->DR;
1174             prx_buffer++;
1175         }
1176 
1177         addr->SER = 0;
1178 
1179         dw_spi_ss_control(spi_priv, SPI_SS_INACTIVE);
1180         addr->SPIENR = DW_SPI_DISABLE;
1181         spi_priv->status.busy = 0U;
1182     } else {
1183         spi_priv->send_buf      = ptx_buffer;
1184         spi_priv->recv_buf      = prx_buffer;
1185         spi_priv->send_num      = num_out;
1186         spi_priv->recv_num      = num_in;
1187         spi_priv->clk_num       = num_in;
1188         spi_priv->transfer_num  = 0;
1189 
1190         addr->TXFTLR            = DW_SPI_TXFIFO_LV;
1191         addr->SPIENR            = DW_SPI_ENABLE;
1192         /* enable transmit FIFO empty interrupt */
1193         addr->IMR               |= DW_SPI_IMR_TXEIM;
1194     }
1195 
1196     return 0;
1197 
1198 }
1199 
1200 /**
1201   \brief       abort spi transfer.
1202   \param[in]   handle spi handle to operate.
1203   \return      error code
1204 */
csi_spi_abort_transfer(spi_handle_t handle)1205 int32_t csi_spi_abort_transfer(spi_handle_t handle)
1206 {
1207     SPI_NULL_PARAM_CHK(handle);
1208 
1209     dw_spi_priv_t *spi_priv = handle;
1210     dw_spi_reg_t *addr = (dw_spi_reg_t *)(spi_priv->base);
1211 
1212     addr->SPIENR = DW_SPI_DISABLE;
1213     spi_priv->status.busy = 0U;
1214     spi_priv->recv_buf = NULL;
1215     spi_priv->recv_num = 0;
1216 
1217     return 0;
1218 }
1219 
1220 /**
1221   \brief       Get SPI status.
1222   \param[in]   handle spi handle to operate.
1223   \return      SPI status \ref ARM_SPI_STATUS
1224 */
csi_spi_get_status(spi_handle_t handle)1225 spi_status_t csi_spi_get_status(spi_handle_t handle)
1226 {
1227     spi_status_t spi_status = {0};
1228 
1229     if (handle == NULL) {
1230         return spi_status;
1231     }
1232 
1233     dw_spi_priv_t *spi_priv = handle;
1234 
1235     return spi_priv->status;
1236 }
1237 
1238