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