• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Winner Microelectronics Co., Ltd. All rights reserved.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 /**
17  * @file    wm_hostspi.c
18  *
19  * @brief   host spi Driver Module
20  *
21  * @author  dave
22  *
23  * Copyright (c) 2015 Winner Microelectronics Co., Ltd.
24  */
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include "wm_regs.h"
29 #include "wm_irq.h"
30 #include "wm_gpio.h"
31 #include "wm_dma.h"
32 #include "wm_dbg.h"
33 #include "wm_mem.h"
34 #include "wm_cpu.h"
35 #include "wm_spi_hal.h"
36 #include "wm_wl_task.h"
37 #include "tls_common.h"
38 #include "core_804.h"
39 #include "wm_pmu.h"
40 #include "wm_hostspi.h"
41 
42 static struct tls_spi_port *spi_port = NULL;
43 
44 #define MSG_QUEUE_SIZE      (8)
45 
46 #define SPI_SCHEDULER_STK_SIZE      (256)
47 #if TLS_OS_FREERTOS
48 static u32 *spi_scheduler_stk = NULL;
49 #endif
50 void tls_spi_queue_send(u32 msg);
51 
52 #define SPI_SCHED_MSG_START_ENGINE      (1)
53 #define SPI_SCHED_MSG_TX_FIFO_READY      (2)
54 #define SPI_SCHED_MSG_RX_FIFO_READY      (3)
55 #define SPI_SCHED_MSG_TRANSFER_COMPLETE      (4)
56 #define SPI_SCHED_MSG_EXIT      (5)
57 #define SPI_SCHED_MSG_END      (6)
58 static void spi_start_transfer(u32 transfer_bytes);
59 
60 int tls_spi_async(struct tls_spi_message *message);
61 int tls_spi_sync(struct tls_spi_message *message);
62 
63 #ifdef SPI_USE_DMA
64 unsigned char *SPI_DMA_CMD_ADDR = NULL;
65 unsigned char *SPI_DMA_BUF_ADDR = NULL;
66 
SpiMasterInit(u8 mode,u8 cs_active,u32 fclk)67 static void SpiMasterInit(u8 mode, u8 cs_active, u32 fclk)
68 {
69     tls_sys_clk sysclk;
70 
71     SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
72     while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
73 
74     tls_sys_clk_get(&sysclk);
75 
76     SPIM_CLKCFG_REG = sysclk.apbclk*UNIT_MHZ/(fclk*2) - 1;
77     SPIM_SPICFG_REG = 0;
78     SPIM_SPICFG_REG = SPI_FRAME_FORMAT_MOTO | SPI_SET_MASTER_SLAVE(SPI_MASTER) | mode;
79     SPIM_INTEN_REG = 0xff;      /* Disable INT */
80 
81     if (SPI_DMA_CMD_ADDR == NULL) {
82         SPI_DMA_CMD_ADDR = tls_mem_alloc(SPI_DMA_CMD_MAX_SIZE);
83         if (SPI_DMA_CMD_ADDR == NULL) {
84             return;
85         }
86     }
87 
88     if (SPI_DMA_BUF_ADDR == NULL) {
89         SPI_DMA_BUF_ADDR = tls_mem_alloc(SPI_DMA_BUF_MAX_SIZE);
90         if (SPI_DMA_BUF_ADDR == NULL) {
91             tls_mem_free(SPI_DMA_CMD_ADDR);
92             SPI_DMA_CMD_ADDR = NULL;
93             return;
94         }
95     }
96 
97     tls_dma_init();
98 }
99 
spiWaitIdle(void)100 int spiWaitIdle(void)
101 {
102     unsigned long regVal;
103     unsigned long timeout = 0;
104 
105     do {
106         timeout++;
107         if (timeout > 0x4FFFFF) // 5s
108             return TLS_SPI_STATUS_EBUSY;
109         regVal = SPIM_SPISTATUS_REG;
110     }
111     while (regVal & (1 << 12));
112 
113     return TLS_SPI_STATUS_OK;
114 }
115 
SpiDmaBlockWrite(u8 * data,u32 len,u8 ifusecmd,u32 cmd)116 static int SpiDmaBlockWrite(u8 * data, u32 len, u8 ifusecmd, u32 cmd)
117 {
118     struct tls_dma_descriptor DmaDesc;
119     u32 txlen, txlenbk;
120     u32 i, blocknum, blocksize = 0;
121     int ret = TLS_SPI_STATUS_OK;
122     int txcmdover = 0;
123 
124     if (data == NULL) {
125         return TLS_SPI_STATUS_EINVAL;
126     }
127     if (spiWaitIdle())
128         return TLS_SPI_STATUS_EBUSY;
129     SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
130     while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
131 
132     if (ifusecmd)
133         SPIM_TXDATA_REG = cmd;
134 
135     if (len % 4) {
136         txlen = len & 0xfffffffc;
137     } else {
138         txlen = len;
139     }
140 
141     txlenbk = txlen;
142     if (txlen > 0) {
143         blocknum = txlen / SPI_DMA_MAX_TRANS_SIZE;
144 
145     /* Request DMA Channel */
146         unsigned char dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_TX) |
147                             TLS_DMA_FLAGS_HARD_MODE);
148         for (i = 0; i <= blocknum; i++) {
149             DmaDesc.src_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE);
150             DmaDesc.dest_addr = HR_SPI_TXDATA_REG;
151             blocksize = (txlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : txlen;
152 
153             if (blocksize == 0)
154                 break;
155             DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC |
156                                      TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
157                                      TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize);
158             DmaDesc.valid = TLS_DMA_DESC_VALID;
159             DmaDesc.next = NULL;
160             tls_dma_start(dmaCh, &DmaDesc, 0);
161             /* Enable SPI TX DMA */
162             SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) | SPI_TX_DMA_ON;
163             SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
164 
165             if (ifusecmd && i == 0) {
166                 SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON |
167                                         SPI_CONTINUE_MODE | SPI_START |
168                                         SPI_VALID_CLKS_NUM(((blocksize + 4) * 8));
169                 txcmdover = 1;
170             } else
171                 SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE |
172                                          SPI_START | SPI_VALID_CLKS_NUM((blocksize * 8));
173 
174             if (spiWaitIdle()) {
175                 ret = TLS_SPI_STATUS_EBUSY;
176                 break;
177             }
178         /* Wait Dma Channel Complete and Free Dma channel */
179             if (tls_dma_wait_complt(dmaCh)) {
180                 ret = TLS_SPI_STATUS_EBUSY;
181                 break;
182             }
183             txlen -= blocksize;
184         }
185         tls_dma_free(dmaCh);
186     }
187 
188     if (len > txlenbk) {
189         u32 word32 = 0;
190         int temp = 0;
191         for (i = 0; i < (len - txlenbk); i++) {
192             word32 |= (data[txlenbk + i] << (i * 8));
193         }
194         SPIM_TXDATA_REG = word32;
195         SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0);
196         SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
197         if (ifusecmd && txcmdover == 0)
198             temp = 4;
199         SPIM_CHCFG_REG = SPI_FORCE_SPI_CS_OUT | SPI_TX_CHANNEL_ON | SPI_CONTINUE_MODE |
200                             SPI_START | SPI_VALID_CLKS_NUM(((temp + len - txlenbk) * 8));
201         if (spiWaitIdle()) {
202             ret = TLS_SPI_STATUS_EBUSY;
203         }
204     }
205     SPIM_CHCFG_REG = 0x00000000;
206     SPIM_MODECFG_REG = 0x00000000;
207     SPIM_SPITIMEOUT_REG = 0x00000000;
208 
209     return ret;
210 }
211 
SpiDmaBlockRead(u8 * data,u32 len,u8 * txdata,u8 txlen)212 static int SpiDmaBlockRead(u8 * data, u32 len, u8 * txdata, u8 txlen)
213 {
214     unsigned char dmaCh = 0;
215     struct tls_dma_descriptor DmaDesc;
216     u32 word32 = 0;
217     u32 i;
218     u32 rxlen, rxlenbk;
219     u8 blocknum;
220     u32 blocksize = 0;
221     int ret = TLS_SPI_STATUS_OK;
222     if (data == NULL) {
223         return TLS_SPI_STATUS_EINVAL;
224     }
225     if (spiWaitIdle()) {
226         return TLS_SPI_STATUS_EBUSY;
227     }
228 
229     SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
230     while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
231 
232     if (len % 4) {
233         rxlen = len & 0xfffffffc;
234     } else {
235         rxlen = len;
236     }
237     rxlenbk = rxlen;
238     blocknum = rxlen / SPI_DMA_MAX_TRANS_SIZE;
239 
240     if (txlen > 0 && txlen <= 32) {
241         for (i = 0; i < txlen; i++) {
242             if ((i > 0) && (i % 4 == 0)) {
243                 SPIM_TXDATA_REG = word32;
244                 word32 = 0;
245             }
246             word32 |= (txdata[i] << ((i % 4) * 8));
247         }
248         SPIM_TXDATA_REG = word32;
249     }
250 
251 /* Request DMA Channel */
252     dmaCh = tls_dma_request(1, TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_LSSPI_RX) |
253                         TLS_DMA_FLAGS_HARD_MODE);
254     DmaDesc.src_addr = HR_SPI_RXDATA_REG;
255     for (i = 0; i <= blocknum; i++) {
256         if (rxlenbk > 0) {
257             DmaDesc.dest_addr = (int) (data + i * SPI_DMA_MAX_TRANS_SIZE);
258             blocksize = (rxlen > SPI_DMA_MAX_TRANS_SIZE) ? SPI_DMA_MAX_TRANS_SIZE : rxlen;
259             if (blocksize == 0) {
260                 break;
261             }
262             DmaDesc.dma_ctrl =
263                 TLS_DMA_DESC_CTRL_DEST_ADD_INC | TLS_DMA_DESC_CTRL_BURST_SIZE1 |
264                 TLS_DMA_DESC_CTRL_DATA_SIZE_WORD |
265                 TLS_DMA_DESC_CTRL_TOTAL_BYTES(blocksize);
266             DmaDesc.valid = TLS_DMA_DESC_VALID;
267             DmaDesc.next = NULL;
268             tls_dma_start(dmaCh, &DmaDesc, 0);
269             /* Enable SPI RX DMA */
270             SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0) |
271                                     SPI_RX_DMA_ON;
272         } else {
273             SPIM_MODECFG_REG = SPI_RX_TRIGGER_LEVEL(0) | SPI_TX_TRIGGER_LEVEL(0);
274         }
275         SPIM_SPITIMEOUT_REG = SPI_TIMER_EN | SPI_TIME_OUT((u32) 0xffff);
276         if (blocknum == 0) {
277             SPIM_CHCFG_REG =
278                 SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON |
279                 SPI_CONTINUE_MODE | SPI_START |
280                 SPI_VALID_CLKS_NUM(((len + txlen) * 8)) | SPI_RX_INVALID_BITS(txlen *8);
281         } else {
282             if (i == 0) {
283                 SPIM_CHCFG_REG =
284                     SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_TX_CHANNEL_ON
285                     | SPI_CONTINUE_MODE | SPI_START |
286                     SPI_VALID_CLKS_NUM(((blocksize + txlen) *8)) | SPI_RX_INVALID_BITS(txlen * 8);
287             } else if (i == blocknum) {
288                 SPIM_CHCFG_REG =
289                     SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE
290                     | SPI_START | SPI_VALID_CLKS_NUM((blocksize + len - rxlenbk) * 8);
291             } else {
292                 SPIM_CHCFG_REG =
293                     SPI_FORCE_SPI_CS_OUT | SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE
294                     | SPI_START | SPI_VALID_CLKS_NUM(blocksize * 8);
295             }
296         }
297         if (spiWaitIdle()) {
298             ret = TLS_SPI_STATUS_EBUSY;
299             break;
300         }
301 
302     /* Wait Dma Channel Complete and Free Dma channel */
303         if (tls_dma_wait_complt(dmaCh)) {
304             ret = TLS_SPI_STATUS_EBUSY;
305             break;
306         }
307         rxlen -= blocksize;
308     }
309     tls_dma_free(dmaCh);
310 
311     if (len > rxlenbk) {
312         word32 = SPIM_RXDATA_REG;
313         *((int *) data + rxlenbk / 4) = word32;
314     }
315     SPIM_CHCFG_REG = 0x00000000;
316     SPIM_MODECFG_REG = 0x00000000;
317     SPIM_SPITIMEOUT_REG = 0x00000000;
318     return ret;
319 }
320 #endif
321 
322 /**
323  * @brief          This function is used to set SPI transfer mode.
324  *
325  * @param[in]      type             is the transfer type.
326  *                                type == SPI_BYTE_TRANSFER    byte transfer
327  *                                         type == SPI_WORD_TRANSFER    word transfer
328  *                                type == SPI_USE_DMA_TRANSFER    DMA transfer
329  *
330  * @return         None
331  *
332  * @note           None
333  */
tls_spi_trans_type(u8 type)334 void tls_spi_trans_type(u8 type)
335 {
336     spi_port->transtype = type;
337     if (SPI_WORD_TRANSFER == type) {
338         spi_set_endian(0);
339     } else if (SPI_USE_DMA_TRANSFER == type) {
340 #ifdef SPI_USE_DMA
341         SpiMasterInit(spi_port->mode, TLS_SPI_CS_LOW, spi_port->speed_hz);
342 #endif
343     }
344 }
345 
spi_message_init(struct tls_spi_message * m)346 static void spi_message_init(struct tls_spi_message *m)
347 {
348     memset_s(m, sizeof(m), 0, sizeof(*m));
349     dl_list_init(&m->transfers);
350 }
351 
spi_complete(void * arg)352 static void spi_complete(void *arg)
353 {
354     tls_os_sem_t *sem;
355 
356     sem = (tls_os_sem_t *) arg;
357     tls_os_sem_release(sem);
358 }
359 
spi_fill_txfifo(struct tls_spi_transfer * current_transfer,u32 current_remaining_bytes)360 static u32 spi_fill_txfifo(struct tls_spi_transfer *current_transfer,
361                            u32 current_remaining_bytes)
362 {
363     u8 fifo_level;
364     u16 rw_words;
365     u16 rw_bytes;
366     u8 data8;
367     u8 i;
368     u32 data32 = 0;
369     u32 tx_remaining_bytes;
370     if ((current_transfer == NULL) || (current_remaining_bytes == 0))
371         return 0;
372 
373     tx_remaining_bytes = current_remaining_bytes;
374     spi_get_status(NULL, NULL, &fifo_level);
375     rw_words =
376         ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) / 4;
377     rw_bytes =
378         ((fifo_level > tx_remaining_bytes) ? tx_remaining_bytes : fifo_level) % 4;
379 
380     for (i = 0; i < rw_words; i++) {
381         if (current_transfer->tx_buf) {
382             if (SPI_BYTE_TRANSFER == spi_port->transtype) {
383                 data32 = 0;
384                 data32 |= ((u8 *) current_transfer->tx_buf +
385                      (current_transfer->len - tx_remaining_bytes))[0] << 24;
386                 data32 |= ((u8 *) current_transfer->tx_buf +
387                      (current_transfer->len - tx_remaining_bytes))[1] << 16;
388                 data32 |= ((u8 *) current_transfer->tx_buf +
389                      (current_transfer->len - tx_remaining_bytes))[2] << 8;
390                 data32 |= ((u8 *) current_transfer->tx_buf +
391                      (current_transfer->len - tx_remaining_bytes))[3] << 0;
392             } else if (SPI_WORD_TRANSFER == spi_port->transtype) {
393                 data32 = *((u32 *) ((u8 *) current_transfer->tx_buf +
394                                current_transfer->len - tx_remaining_bytes));
395             }
396         } else {
397             data32 = 0xffffffff;
398         }
399         TLS_DBGPRT_SPI_INFO("spi fifo[%d]: 0x%x.\n", i, data32);
400         spi_data_put(data32);
401         tx_remaining_bytes -= 4;
402     }
403 
404     if (rw_bytes) {
405         data32 = 0;
406         for (i = 0; i < rw_bytes; i++) {
407             if (current_transfer->tx_buf) {
408                 data8 =  ((u8 *) current_transfer->tx_buf)[current_transfer->len -
409                                   tx_remaining_bytes];
410             } else {
411                 data8 = 0xff;
412             }
413             if (SPI_BYTE_TRANSFER == spi_port->transtype)
414                 data32 |= data8 << ((3 - i) * 8);
415             else if (SPI_WORD_TRANSFER == spi_port->transtype) {
416                 data32 |= data8 << (i * 8);
417             }
418             tx_remaining_bytes -= 1;
419         }
420         TLS_DBGPRT_SPI_INFO("spi_fifo: 0x%x.\n", data32);
421         spi_data_put(data32);
422     }
423 
424     return (current_remaining_bytes - tx_remaining_bytes);
425 }
426 
spi_get_rxfifo(struct tls_spi_transfer * current_transfer,u32 current_remaining_bytes)427 static u32 spi_get_rxfifo(struct tls_spi_transfer *current_transfer,
428                           u32 current_remaining_bytes)
429 {
430     u8 fifo_level;
431     u8 rw_words;
432     u8 rw_bytes;
433     u8 data8 = 0;
434     u8 i;
435     u32 data32;
436     u32 rx_remaining_bytes;
437 
438     if ((current_transfer == NULL) || (current_remaining_bytes == 0))
439         return 0;
440 
441     rx_remaining_bytes = current_remaining_bytes;
442     spi_get_status(NULL, &fifo_level, NULL);
443 
444     rw_words = fifo_level / 4;
445     rw_bytes = fifo_level % 4;
446 
447     for (i = 0; i < rw_words; i++) {
448         data32 = spi_data_get();
449         if (current_transfer->rx_buf) {
450             if (SPI_BYTE_TRANSFER == spi_port->transtype) {
451                 data32 = swap_32(data32);
452                 (((u8 *) current_transfer->rx_buf +
453                 (current_transfer->len - rx_remaining_bytes)))[0] = (u8) data32;
454                 (((u8 *) current_transfer->rx_buf +
455                   (current_transfer->len - rx_remaining_bytes)))[1] = (u8) (data32 >> 8);
456                 (((u8 *) current_transfer->rx_buf +
457                   (current_transfer->len - rx_remaining_bytes)))[2] = (u8) (data32 >> 16);
458                 (((u8 *) current_transfer->rx_buf +
459                   (current_transfer->len - rx_remaining_bytes)))[3] = (u8) (data32 >> 24);
460             } else if (SPI_WORD_TRANSFER == spi_port->transtype) {
461                 *((u32 *) ((u8 *) current_transfer->rx_buf +
462                            current_transfer->len - rx_remaining_bytes)) = data32;
463             }
464         }
465         rx_remaining_bytes -= 4;
466     }
467 
468     if (rw_bytes) {
469         data32 = spi_data_get();
470         if (current_transfer->rx_buf) {
471             for (i = 0; i < rw_bytes; i++) {
472                 if (SPI_BYTE_TRANSFER == spi_port->transtype)
473                     data8 = (u8) (data32 >> ((3 - i) * 8));
474                 else if (SPI_WORD_TRANSFER == spi_port->transtype)
475                     data8 = (u8) (data32 >> (i * 8));
476                 ((u8 *) current_transfer->rx_buf)[current_transfer->len -rx_remaining_bytes] = data8;
477                 rx_remaining_bytes -= 1;
478             }
479         } else {
480             rx_remaining_bytes -= rw_bytes;
481         }
482     }
483 
484     return (current_remaining_bytes - rx_remaining_bytes);
485 }
486 
spi_next_transfer(struct tls_spi_message * current_message)487 static struct tls_spi_transfer *spi_next_transfer(struct tls_spi_message
488                                                   *current_message)
489 {
490     if (current_message == NULL) {
491         return NULL;
492     }
493 
494     return dl_list_first(&current_message->transfers, struct tls_spi_transfer, transfer_list);
495 }
496 
spi_next_message(void)497 static struct tls_spi_message *spi_next_message(void)
498 {
499     struct tls_spi_message *current_message;
500 
501     current_message =
502         dl_list_first(&spi_port->wait_queue, struct tls_spi_message, queue);
503     if (current_message == NULL) {
504         return NULL;
505     }
506 
507     spi_port->current_transfer = spi_next_transfer(current_message);
508     current_message->status = SPI_MESSAGE_STATUS_INPROGRESS;
509 
510     return current_message;
511 }
512 
513 int gSpiCsFlag = 0;
spi_start_transfer(u32 transfer_bytes)514 static void spi_start_transfer(u32 transfer_bytes)
515 {
516     if (spi_port->reconfig) {
517         TLS_DBGPRT_SPI_INFO("reconfig the spi master controller.\n");
518         spi_set_mode(spi_port->mode);
519         spi_set_chipselect_mode(spi_port->cs_active);
520         spi_set_sclk(spi_port->speed_hz);
521 
522         spi_port->reconfig = 0;
523     }
524 
525     spi_set_sclk_length(transfer_bytes * 8, 0);
526     {
527         spi_set_chipselect_mode(SPI_CS_ACTIVE_MODE);
528     }
529     spi_sclk_start();
530 }
531 
spi_continue_transfer(void)532 static void spi_continue_transfer(void)
533 {
534     struct tls_spi_message *current_message;
535     struct tls_spi_transfer *current_transfer;
536     u32 transfer_bytes;
537 
538     current_message = spi_port->current_message;
539     current_transfer = spi_port->current_transfer;
540     if ((current_message == NULL) || (current_transfer == NULL)) {
541         return;
542     }
543     transfer_bytes =
544         spi_get_rxfifo(current_transfer, spi_port->current_remaining_bytes);
545 
546     spi_port->current_remaining_bytes -= transfer_bytes;
547     if (spi_port->current_remaining_bytes == 0) {
548         tls_os_sem_acquire(spi_port->lock, 0);
549 
550         dl_list_del(&current_transfer->transfer_list);
551         spi_port->current_transfer =
552             spi_next_transfer(spi_port->current_message);
553         if (spi_port->current_transfer == NULL) {
554             spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE);
555             current_message->status = SPI_MESSAGE_STATUS_DONE;
556             dl_list_del(&current_message->queue);
557             spi_port->current_message = spi_next_message();
558         }
559 
560         tls_os_sem_release(spi_port->lock);
561         current_transfer = spi_port->current_transfer;
562         if (current_transfer != NULL) {
563             spi_port->current_remaining_bytes = current_transfer->len;
564         }
565     }
566 
567     transfer_bytes =
568         spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes);
569     if (transfer_bytes) {
570         spi_start_transfer(transfer_bytes);
571     }
572 
573     if (current_message->status == SPI_MESSAGE_STATUS_DONE) {
574         current_message->complete(current_message->context);
575     }
576 }
577 
spi_scheduler(void * data)578 static void spi_scheduler(void *data)
579 {
580     u8 err;
581     u32 msg;
582     u32 transfer_bytes;
583     struct tls_spi_transfer *current_transfer;
584 
585     while (1) {
586         err = tls_os_queue_receive(spi_port->msg_queue, (void **) &msg, 4, 0);
587         if (err == TLS_OS_SUCCESS) {
588             switch (msg) {
589                 case SPI_SCHED_MSG_START_ENGINE:
590                     if (spi_port->current_message) {
591                         TLS_DBGPRT_WARNING("spi transaction scheduler is running now!\n");
592                         break;
593                     }
594 
595                     TLS_DBGPRT_SPI_INFO("acquire the first transaction message in waiting queue.\n");
596                     tls_os_sem_acquire(spi_port->lock, 0);
597 
598                     spi_port->current_message = spi_next_message();
599 
600                     tls_os_sem_release(spi_port->lock);
601                     current_transfer = spi_port->current_transfer;
602                     if (current_transfer == NULL) {
603                         break;
604                     }
605                     spi_port->current_remaining_bytes = current_transfer->len;
606 
607                     TLS_DBGPRT_SPI_INFO("fill the tx fifo.\n");
608                     transfer_bytes = spi_fill_txfifo(current_transfer, spi_port->current_remaining_bytes);
609                     TLS_DBGPRT_SPI_INFO("start the spi transfer - %d.\n", transfer_bytes);
610                     spi_start_transfer(transfer_bytes);
611 
612                     break;
613 
614                 case SPI_SCHED_MSG_TX_FIFO_READY:
615                     TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_TX_FIFO_READY.\n");
616                     break;
617 
618                 case SPI_SCHED_MSG_RX_FIFO_READY:
619                     TLS_DBGPRT_SPI_INFO("process SPI_SCHED_MSG_RX_FIFO_READY.\n");
620                     break;
621 
622                 case SPI_SCHED_MSG_TRANSFER_COMPLETE:
623                     spi_continue_transfer();
624                     break;
625 
626                 case SPI_SCHED_MSG_EXIT:
627                     break;
628 
629                 default:
630                     break;
631             }
632         }
633     }
634 }
635 
SPI_LS_IRQHandler(void)636 ATTRIBUTE_ISR void SPI_LS_IRQHandler(void)
637 {
638     u32 int_status;
639     u32 int_mask;
640     csi_kernel_intrpt_enter();
641     int_status = spi_get_int_status();
642     spi_clear_int_status(int_status);
643 
644     int_mask = spi_int_mask();
645     int_status &= ~int_mask;
646 
647     if (int_status & SPI_INT_TX_FIFO_RDY) {
648         tls_spi_queue_send(SPI_SCHED_MSG_TX_FIFO_READY);
649     }
650 
651     if (int_status & SPI_INT_RX_FIFO_RDY) {
652         tls_spi_queue_send(SPI_SCHED_MSG_RX_FIFO_READY);
653     }
654 
655     if (int_status & SPI_INT_TRANSFER_DONE) {
656         if (SPI_WORD_TRANSFER == spi_port->transtype) {
657             spi_continue_transfer();
658         } else {
659             tls_spi_queue_send(SPI_SCHED_MSG_TRANSFER_COMPLETE);
660         }
661     }
662     csi_kernel_intrpt_exit();
663 }
664 
665  /**
666  * @brief          This function is used to setup the spi CPOL,CPHA,cs signal and clock.
667  *
668  * @param[in]      mode         is CPOL and CPHA type defined in TLS_SPI_MODE_0 to TLS_SPI_MODE_3
669  * @param[in]      cs_active    is cs mode, defined as TLS_SPI_CS_LOW or TLS_SPI_CS_HIGH
670  * @param[in]      fclk            is spi clock,the unit is HZ.
671  *
672  * @retval         TLS_SPI_STATUS_OK            if setup success
673  * @retval         TLS_SPI_STATUS_EMODENOSUPPORT    if mode is not support
674  * @retval         TLS_SPI_STATUS_EINVAL            if cs_active is not support
675  * @retval         TLS_SPI_STATUS_ECLKNOSUPPORT    if fclk is not support
676  *
677  * @note           None
678  */
tls_spi_setup(u8 mode,u8 cs_active,u32 fclk)679 int tls_spi_setup(u8 mode, u8 cs_active, u32 fclk)
680 {
681     tls_sys_clk sysclk;
682 
683     if ((spi_port->mode == mode) && (spi_port->cs_active == cs_active)
684         && (spi_port->speed_hz == fclk)) {
685         TLS_DBGPRT_WARNING("@mode, @cs_activer, @fclk is the same as settings of the current spi master driver!\n");
686         return TLS_SPI_STATUS_OK;
687     }
688 
689     switch (mode) {
690         case TLS_SPI_MODE_0:
691         case TLS_SPI_MODE_1:
692         case TLS_SPI_MODE_2:
693         case TLS_SPI_MODE_3:
694             spi_port->mode = mode;
695             break;
696 
697         default:
698             TLS_DBGPRT_ERR("@mode is invalid!\n");
699             return TLS_SPI_STATUS_EMODENOSUPPORT;
700     }
701 
702     if ((cs_active != TLS_SPI_CS_HIGH) && (cs_active != TLS_SPI_CS_LOW)) {
703         TLS_DBGPRT_ERR("@cs_active  is invalid!\n");
704         return TLS_SPI_STATUS_EINVAL;
705     } else {
706         spi_port->cs_active = cs_active;
707     }
708 
709     tls_sys_clk_get(&sysclk);
710 
711     if ((fclk < TLS_SPI_FCLK_MIN) || (fclk > sysclk.apbclk * UNIT_MHZ / 2)) { // 2:TLS_SPI_FCLK_MAX
712         TLS_DBGPRT_ERR("@fclk is invalid!\n");
713         return TLS_SPI_STATUS_ECLKNOSUPPORT;
714     } else {
715         spi_port->speed_hz = fclk;
716     }
717 
718 #ifdef SPI_USE_DMA
719     if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
720         SpiMasterInit(mode, TLS_SPI_CS_LOW, fclk);
721         return TLS_SPI_STATUS_OK;
722     }
723 #endif
724 
725     spi_port->reconfig = 1;
726 
727     return TLS_SPI_STATUS_OK;
728 }
729 
730 /**
731  * @brief          This function is used to synchronous write command then read data by SPI.
732  *
733  * @param[in]      txbuf        is the write data buffer.
734  * @param[in]      n_tx         is the write data length.
735  * @param[in]      rxbuf        is the read data buffer.
736  * @param[in]      n_rx         is the read data length.
737  *
738  * @retval         TLS_SPI_STATUS_OK            if write success.
739  * @retval         TLS_SPI_STATUS_EINVAL        if argument is invalid.
740  * @retval         TLS_SPI_STATUS_ENOMEM            if there is no enough memory.
741  * @retval         TLS_SPI_STATUS_ESHUTDOWN        if SPI driver does not installed.
742  *
743  * @note           None
744  */
tls_spi_read_with_cmd(const u8 * txbuf,u32 n_tx,u8 * rxbuf,u32 n_rx)745 int tls_spi_read_with_cmd(const u8 * txbuf, u32 n_tx, u8 * rxbuf, u32 n_rx)
746 {
747     int status;
748     struct tls_spi_message message;
749     struct tls_spi_transfer x[2];
750 
751     if ((txbuf == NULL) || (n_tx == 0) || (rxbuf == NULL) || (n_rx == 0)) {
752         return TLS_SPI_STATUS_EINVAL;
753     }
754 
755 #ifdef SPI_USE_DMA
756     if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
757         if (n_rx > SPI_DMA_BUF_MAX_SIZE || n_tx > SPI_DMA_CMD_MAX_SIZE) {
758             TLS_DBGPRT_ERR("\nread length too long\n");
759             return TLS_SPI_STATUS_EINVAL;
760         }
761         tls_os_sem_acquire(spi_port->lock, 0);
762         tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
763         if (SPI_DMA_CMD_ADDR && SPI_DMA_BUF_ADDR) {
764             MEMCPY((u8 *) SPI_DMA_CMD_ADDR, txbuf, n_tx);
765             SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, n_rx, (u8 *) SPI_DMA_CMD_ADDR,
766                             n_tx);
767             MEMCPY(rxbuf, (u8 *) SPI_DMA_BUF_ADDR, n_rx);
768             status = TLS_SPI_STATUS_OK;
769         } else {
770             status = TLS_SPI_STATUS_ENOMEM;
771         }
772 
773         tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
774         tls_os_sem_release(spi_port->lock);
775         return status;
776     }
777 #endif
778 
779     spi_message_init(&message);
780 
781     memset_s(x, sizeof(x), 0, sizeof(x));
782     if (n_tx) {
783         x[0].len = n_tx;
784         x[0].tx_buf = txbuf;
785         dl_list_add_tail(&message.transfers, &x[0].transfer_list);
786     }
787     if (n_rx) {
788         x[1].len = n_rx;
789         x[1].rx_buf = rxbuf;
790         dl_list_add_tail(&message.transfers, &x[1].transfer_list);
791     }
792 
793 /* do the i/o. */
794     status = tls_spi_sync(&message);
795 
796     return status;
797 }
798 
799 /**
800  * @brief          This function is used to synchronous read data by SPI.
801  *
802  * @param[in]      buf          is the buffer for saving SPI data.
803  * @param[in]      len          is the data length.
804  *
805  * @retval         TLS_SPI_STATUS_OK            if write success.
806  * @retval         TLS_SPI_STATUS_EINVAL        if argument is invalid.
807  * @retval         TLS_SPI_STATUS_ENOMEM            if there is no enough memory.
808  * @retval         TLS_SPI_STATUS_ESHUTDOWN        if SPI driver does not installed.
809  *
810  * @note           None
811  */
tls_spi_read(u8 * buf,u32 len)812 int tls_spi_read(u8 * buf, u32 len)
813 {
814     struct tls_spi_transfer t;
815     struct tls_spi_message m;
816 
817     if ((buf == NULL) || (len == 0)) {
818         return TLS_SPI_STATUS_EINVAL;
819     }
820 
821 #ifdef SPI_USE_DMA
822     if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
823         u32 data32 = 0;
824         u16 rxBitLen;
825         u32 rdval1 = 0;
826         u32 i;
827         tls_os_sem_acquire(spi_port->lock, 0);
828         tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
829 
830         if (len <= 4) {
831             SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
832             while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
833 
834             rxBitLen = 8 * len;
835             rdval1 =
836                 SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON |
837                 SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START |
838                 SPI_VALID_CLKS_NUM(rxBitLen);
839             SPIM_CHCFG_REG = rdval1;
840             spiWaitIdle();
841             SPIM_CHCFG_REG |= SPI_CS_HIGH;
842 
843             data32 = SPIM_RXDATA_REG;
844 
845             for (i = 0; i < len; i++) {
846                 *(buf + i) = (u8) (data32 >> (i * 8));
847             }
848             SPIM_CHCFG_REG = 0x00000000;
849             SPIM_MODECFG_REG = 0x00000000;
850         } else {
851             if (len > SPI_DMA_BUF_MAX_SIZE) {
852                 TLS_DBGPRT_ERR("\nread len too long\n");
853                 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
854                 tls_os_sem_release(spi_port->lock);
855                 return TLS_SPI_STATUS_EINVAL;
856             }
857             if (SPI_DMA_BUF_ADDR) {
858                 SpiDmaBlockRead((u8 *) SPI_DMA_BUF_ADDR, len, NULL, 0);
859                 MEMCPY(buf, (u8 *) SPI_DMA_BUF_ADDR, len);
860             } else {
861                 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
862                 tls_os_sem_release(spi_port->lock);
863                 return TLS_SPI_STATUS_ENOMEM;
864             }
865         }
866         tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
867         tls_os_sem_release(spi_port->lock);
868         return TLS_SPI_STATUS_OK;
869     }
870 #endif
871 
872     memset_s(&t, sizeof(t), 0, sizeof(t));
873     t.rx_buf = buf;
874     t.len = len;
875 
876     spi_message_init(&m);
877 
878     dl_list_add_tail(&m.transfers, &t.transfer_list);
879 
880     return tls_spi_sync(&m);
881 }
882 
883 /**
884  * @brief          This function is used to synchronous write data by SPI.
885  *
886  * @param[in]      buf          is the user data.
887  * @param[in]      len          is the data length.
888  *
889  * @retval         TLS_SPI_STATUS_OK            if write success.
890  * @retval         TLS_SPI_STATUS_EINVAL        if argument is invalid.
891  * @retval         TLS_SPI_STATUS_ENOMEM            if there is no enough memory.
892  * @retval         TLS_SPI_STATUS_ESHUTDOWN        if SPI driver does not installed.
893  *
894  * @note           None
895  */
tls_spi_write(const u8 * buf,u32 len)896 int tls_spi_write(const u8 * buf, u32 len)
897 {
898     struct tls_spi_transfer t;
899     struct tls_spi_message m;
900 
901     if ((buf == NULL) || (len == 0)) {
902         return TLS_SPI_STATUS_EINVAL;
903     }
904 
905 #ifdef SPI_USE_DMA
906     if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
907         u32 data32 = 0;
908         u16 txBitLen;
909         u32 rdval1 = 0;
910         u32 i;
911         tls_os_sem_acquire(spi_port->lock, 0);
912         tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
913         if (len <= 4) {
914             SPIM_CHCFG_REG = SPI_CLEAR_FIFOS;
915             while (SPIM_CHCFG_REG & SPI_CLEAR_FIFOS);
916             for (i = 0; i < len; i++) {
917                 data32 |= (((u8) (buf[i])) << (i * 8));
918             }
919             SPIM_TXDATA_REG = data32;
920             txBitLen = 8 * len;
921             rdval1 =
922                 SPI_FORCE_SPI_CS_OUT | SPI_CS_LOW | SPI_TX_CHANNEL_ON |
923                 SPI_RX_CHANNEL_ON | SPI_CONTINUE_MODE | SPI_START |
924                 SPI_VALID_CLKS_NUM(txBitLen);
925             SPIM_CHCFG_REG = rdval1;
926             spiWaitIdle();
927             SPIM_CHCFG_REG |= SPI_CS_HIGH;
928 
929             SPIM_CHCFG_REG = 0x00000000;
930             SPIM_MODECFG_REG = 0x00000000;
931         } else {
932             if (len > SPI_DMA_BUF_MAX_SIZE) {
933                 TLS_DBGPRT_ERR("\nwrite len too long\n");
934                 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
935                 tls_os_sem_release(spi_port->lock);
936                 return TLS_SPI_STATUS_EINVAL;
937             }
938             if (SPI_DMA_BUF_ADDR) {
939                 MEMCPY((u8 *) SPI_DMA_BUF_ADDR, buf, len);
940                 SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, len, 0, 0);
941             } else {
942                 tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
943                 tls_os_sem_release(spi_port->lock);
944                 return TLS_SPI_STATUS_ENOMEM;
945             }
946         }
947         tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
948         tls_os_sem_release(spi_port->lock);
949         return TLS_SPI_STATUS_OK;
950     }
951 
952 #endif
953     memset_s(&t, sizeof(t), 0, sizeof(t));
954     t.tx_buf = buf;
955     t.len = len;
956 
957     spi_message_init(&m);
958 
959     dl_list_add_tail(&m.transfers, &t.transfer_list);
960 
961     return tls_spi_sync(&m);
962 }
963 
964 /**
965  * @brief          This function is used to synchronous write 32bit command then write data by SPI.
966  *
967  * @param[in]      cmd                     is the command data.
968  * @param[in]      n_cmd                  is the command len,can not bigger than four
969  * @param[in]      txbuf                   is the write data buffer.
970  * @param[in]      n_tx                    is the write data length.
971  *
972  * @retval         TLS_SPI_STATUS_OK            if write success.
973  * @retval         TLS_SPI_STATUS_EINVAL        if argument is invalid.
974  * @retval         TLS_SPI_STATUS_ENOMEM            if there is no enough memory.
975  * @retval         TLS_SPI_STATUS_ESHUTDOWN        if SPI driver does not installed.
976  *
977  * @note           None
978  */
tls_spi_write_with_cmd(const u8 * cmd,u32 n_cmd,const u8 * txbuf,u32 n_tx)979 int tls_spi_write_with_cmd(const u8 * cmd, u32 n_cmd, const u8 * txbuf,
980                            u32 n_tx)
981 {
982     int status;
983     struct tls_spi_message message;
984     struct tls_spi_transfer x[2];
985 
986     if ((cmd == NULL) || (n_cmd == 0) || (txbuf == NULL) || (n_tx == 0)) {
987         return TLS_SPI_STATUS_EINVAL;
988     }
989 
990 #ifdef SPI_USE_DMA
991     if (SPI_USE_DMA_TRANSFER == spi_port->transtype) {
992         if (n_tx > SPI_DMA_BUF_MAX_SIZE) {
993             TLS_DBGPRT_ERR("\nwriten len too long\n");
994             return TLS_SPI_STATUS_EINVAL;
995         }
996         tls_os_sem_acquire(spi_port->lock, 0);
997         tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
998         if (SPI_DMA_BUF_ADDR) {
999             MEMCPY((u8 *) SPI_DMA_BUF_ADDR, (u8 *) cmd, n_cmd);
1000             MEMCPY((u8 *) (SPI_DMA_BUF_ADDR + n_cmd), txbuf, n_tx);
1001             SpiDmaBlockWrite((u8 *) SPI_DMA_BUF_ADDR, (n_cmd + n_tx), 0, 0);
1002             status = TLS_SPI_STATUS_OK;
1003         } else {
1004             status = TLS_SPI_STATUS_ENOMEM;
1005         }
1006         tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1007         tls_os_sem_release(spi_port->lock);
1008         return status;
1009     }
1010 #endif
1011 
1012     spi_message_init(&message);
1013 
1014     memset_s(x, sizeof(x), 0, sizeof(x));
1015     if (n_cmd) {
1016         x[0].len = n_cmd;
1017         x[0].tx_buf = (const void *) cmd;
1018         dl_list_add_tail(&message.transfers, &x[0].transfer_list);
1019     }
1020     if (n_tx) {
1021         x[1].len = n_tx;
1022         x[1].tx_buf = txbuf;
1023         dl_list_add_tail(&message.transfers, &x[1].transfer_list);
1024     }
1025 
1026 /* do the i/o. */
1027     status = tls_spi_sync(&message);
1028 
1029     return status;
1030 }
1031 
1032 /**
1033  * @brief
1034  *
1035  * @param message
1036  *
1037  * @return
1038  */
tls_spi_sync(struct tls_spi_message * message)1039 int tls_spi_sync(struct tls_spi_message *message)
1040 {
1041     int status;
1042     u8 err;
1043     tls_os_sem_t *sem;
1044 
1045     err = tls_os_sem_create(&sem, 0);
1046     if (err != TLS_OS_SUCCESS) {
1047         TLS_DBGPRT_ERR("create spi transaction synchronizing semaphore fail!\n");
1048         return TLS_SPI_STATUS_ENOMEM;
1049     }
1050 
1051     message->context = (void *) sem;
1052     message->complete = spi_complete;
1053 
1054     tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1055     status = tls_spi_async(message);
1056     if (status == TLS_SPI_STATUS_OK) {
1057         TLS_DBGPRT_SPI_INFO("waiting spi transaction finishing!\n");
1058         tls_os_sem_acquire(sem, 0);
1059     }
1060     tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1061 
1062     tls_os_sem_delete(sem);
1063     message->context = NULL;
1064     message->complete = NULL;
1065 
1066     return status;
1067 }
1068 
1069 /**
1070  * @brief
1071  *
1072  * @param message
1073  *
1074  * @return
1075  */
tls_spi_async(struct tls_spi_message * message)1076 int tls_spi_async(struct tls_spi_message *message)
1077 {
1078     u8 need_sched;
1079     struct tls_spi_transfer *transfer;
1080 
1081     if (spi_port == NULL) {
1082         TLS_DBGPRT_ERR("spi master driver module not beed installed!\n");
1083         return TLS_SPI_STATUS_ESHUTDOWN;
1084     }
1085 
1086     if ((message == NULL) || (dl_list_empty(&message->transfers))) {
1087         TLS_DBGPRT_ERR("@message is NULL or @message->transfers is empty!\n");
1088         return TLS_SPI_STATUS_EINVAL;
1089     }
1090 
1091     dl_list_for_each(transfer, &message->transfers, struct tls_spi_transfer,
1092                      transfer_list)
1093     {
1094         if (transfer->len == 0) {
1095             TLS_DBGPRT_ERR("\"@transfer->len\" belong to @message is 0!\n");
1096             return TLS_SPI_STATUS_EINVAL;
1097         }
1098     }
1099 
1100     tls_os_sem_acquire(spi_port->lock, 0);
1101 
1102     if (dl_list_empty(&spi_port->wait_queue)) {
1103         need_sched = 1;
1104     } else {
1105         need_sched = 0;
1106     }
1107     message->status = SPI_MESSAGE_STATUS_IDLE;
1108     dl_list_add_tail(&spi_port->wait_queue, &message->queue);
1109 
1110     tls_os_sem_release(spi_port->lock);
1111 
1112     if (need_sched == 1) {
1113         tls_spi_queue_send(SPI_SCHED_MSG_START_ENGINE);
1114     }
1115 
1116     return TLS_SPI_STATUS_OK;
1117 }
1118 
1119 /**
1120  * @brief          This function is used to initialize the SPI master driver.
1121  *
1122  * @param[in]      None
1123  *
1124  * @retval         TLS_SPI_STATUS_OK            if initialize success
1125  * @retval         TLS_SPI_STATUS_EBUSY        if SPI is already initialized
1126  * @retval         TLS_SPI_STATUS_ENOMEM        if malloc SPI memory fail
1127  *
1128  * @note           None
1129  */
tls_spi_init(void)1130 int tls_spi_init(void)
1131 {
1132     u8 err;
1133     struct tls_spi_port *port;
1134 
1135     if (spi_port != NULL) {
1136         TLS_DBGPRT_ERR("spi driver module has been installed!\n");
1137         return TLS_SPI_STATUS_EBUSY;
1138     }
1139 
1140     TLS_DBGPRT_SPI_INFO("initialize spi master driver module.\n");
1141 
1142     port = (struct tls_spi_port *) tls_mem_alloc(sizeof(struct tls_spi_port));
1143     if (port == NULL) {
1144         TLS_DBGPRT_ERR("allocate \"struct tls_spi_port\" fail!\n");
1145         return TLS_SPI_STATUS_ENOMEM;
1146     }
1147     memset_s(port, sizeof(port), 0, sizeof(struct tls_spi_port));
1148     err = tls_os_sem_create(&port->lock, 1);
1149     if (err != TLS_OS_SUCCESS) {
1150         TLS_DBGPRT_ERR("create semaphore @spi_port->lock fail!\n");
1151         tls_mem_free(port);
1152         return TLS_SPI_STATUS_ENOMEM;
1153     }
1154 
1155     port->speed_hz = SPI_DEFAULT_SPEED;
1156     port->cs_active = SPI_CS_ACTIVE_MODE;
1157     port->mode = SPI_DEFAULT_MODE;  /* CPHA = 0,CPOL = 0 */
1158     port->reconfig = 0;
1159 
1160     dl_list_init(&port->wait_queue);
1161 
1162     port->current_message = NULL;
1163     port->current_remaining_transfer = 0;
1164     port->current_transfer = NULL;
1165     port->current_remaining_bytes = 0;
1166 
1167     spi_port = port;
1168 
1169     TLS_DBGPRT_SPI_INFO("initialize spi master controller.\n");
1170     tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1171 
1172     spi_clear_fifo();
1173     spi_set_endian(1);
1174     tls_spi_trans_type(SPI_BYTE_TRANSFER);
1175     spi_set_mode(spi_port->mode);
1176     spi_set_chipselect_mode(SPI_CS_INACTIVE_MODE);
1177     spi_force_cs_out(1);
1178     spi_set_sclk(spi_port->speed_hz);
1179 
1180     spi_set_tx_trigger_level(0);
1181     spi_set_rx_trigger_level(7);
1182 
1183     spi_set_rx_channel(1);
1184     spi_set_tx_channel(1);
1185     spi_unmask_int(SPI_INT_TRANSFER_DONE);
1186     tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1187 
1188     TLS_DBGPRT_SPI_INFO("register spi master interrupt handler.\n");
1189     tls_irq_enable(SPI_LS_IRQn);
1190 
1191     TLS_DBGPRT_SPI_INFO("spi master driver module initialization finish.\n");
1192 
1193     return TLS_SPI_STATUS_OK;
1194 }
1195 
tls_spi_task_init(void)1196 int tls_spi_task_init(void)
1197 {
1198     u8 err;
1199     if (spi_port == NULL) {
1200         return TLS_SPI_STATUS_ENOMEM;
1201     }
1202 
1203     if (spi_port->msg_queue) {
1204         return TLS_SPI_STATUS_OK;
1205     }
1206 
1207     err = tls_os_queue_create(&spi_port->msg_queue, MSG_QUEUE_SIZE);
1208     if (err != TLS_OS_SUCCESS) {
1209         TLS_DBGPRT_ERR("create message queue @spi_port->msg_queue fail!\n");
1210         return TLS_SPI_STATUS_ENOMEM;
1211     }
1212 #if TLS_OS_LITEOS
1213     err = tls_os_task_create(NULL, "hostspi",
1214                              spi_scheduler,
1215                              (void *) spi_port,
1216                              (void *) NULL,
1217                              SPI_SCHEDULER_STK_SIZE * sizeof(u32),
1218                              TLS_SPI_SCHEDULER_TASK_PRIO, 0);
1219     if (err != TLS_OS_SUCCESS) {
1220         TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n");
1221         tls_os_queue_delete(spi_port->msg_queue);
1222         return TLS_SPI_STATUS_ENOMEM;
1223     }
1224 #else
1225     spi_scheduler_stk = tls_mem_alloc(SPI_SCHEDULER_STK_SIZE * sizeof(u32));
1226     if (spi_scheduler_stk == NULL) {
1227         tls_os_queue_delete(spi_port->msg_queue);
1228         TLS_DBGPRT_ERR("spi_scheduler_stk allocated fail!\n");
1229         return TLS_SPI_STATUS_ENOMEM;
1230     }
1231     err = tls_os_task_create(NULL, "hostspi",
1232                              spi_scheduler,
1233                              (void *) spi_port,
1234                              (void *) spi_scheduler_stk,
1235                              SPI_SCHEDULER_STK_SIZE * sizeof(u32),
1236                              TLS_SPI_SCHEDULER_TASK_PRIO, 0);
1237     if (err != TLS_OS_SUCCESS) {
1238         TLS_DBGPRT_ERR("create spi master driver scheduler task fail!\n");
1239         tls_os_queue_delete(spi_port->msg_queue);
1240         tls_mem_free(spi_scheduler_stk);
1241         spi_scheduler_stk = NULL;
1242         return TLS_SPI_STATUS_ENOMEM;
1243     }
1244 #endif
1245 
1246     return TLS_SPI_STATUS_OK;
1247 }
1248 
tls_spi_queue_send(u32 msg)1249 void tls_spi_queue_send(u32 msg)
1250 {
1251     if (TLS_SPI_STATUS_OK == tls_spi_task_init()) {
1252         tls_os_queue_send(spi_port->msg_queue, (void *) msg, 4); // 4:msg_size
1253     }
1254 }
1255 
1256 /**
1257  * @brief
1258  *
1259  * @return
1260  */
tls_spi_exit(void)1261 int tls_spi_exit(void)
1262 {
1263     TLS_DBGPRT_SPI_INFO("Not support spi master driver module uninstalled!\n");
1264     return TLS_SPI_STATUS_EPERM;
1265 }
1266 
1267 /**********************************************************************************************************
1268 * Description:     This function is used to select SPI slave type.
1269 *
1270 * Arguments  :     slave                    is the slave type,defined as follow:
1271 *                             slave == SPI_SLAVE_FLASH    :flash
1272 *                             slave == SPI_SLAVE_CARD        : sd card
1273 *
1274 * Returns    :     Before communicate with different SPI device, must call the function.
1275 **********************************************************************************************************/
tls_spi_slave_sel(u16 slave)1276 void tls_spi_slave_sel(u16 slave)
1277 {
1278     tls_gpio_cfg((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, WM_GPIO_DIR_OUTPUT,
1279                  WM_GPIO_ATTR_FLOATING);
1280     if (SPI_SLAVE_FLASH == slave) {
1281         tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 0);
1282     } else if (SPI_SLAVE_CARD == slave) {
1283         tls_gpio_write((enum tls_io_name) SPI_SLAVE_CONTROL_PIN, 1);
1284     }
1285 }
1286 
1287 /**********************************************************************************************************
1288 * Description:     This function is used to spi data tx/rx without irq.
1289 *
1290 * Arguments  :  data_out-------data to be sent to slave
1291 *               data_in -------data to be received from slave
1292 *               num_out -------number to be sent to slave  unit:byte
1293 *               num_in  -------number to be received from slave unit:byte
1294 * Returns    :     Before communicate with different SPI device, must call the function.
1295 **********************************************************************************************************/
tls_spi_xfer(const void * data_out,void * data_in,uint32_t num_out,uint32_t num_in)1296 int32_t tls_spi_xfer(const void *data_out, void *data_in, uint32_t num_out, uint32_t num_in)
1297 {
1298     int ret = 0;
1299     uint32_t length = 0;
1300     uint32_t remain_length ;
1301     uint32_t int_status;
1302     struct tls_spi_transfer tls_transfer;
1303     uint32_t tot_num = 0;
1304 
1305     if (data_in == NULL || num_out == 0 || num_in == 0 || data_out == NULL) {
1306         return -1;
1307     }
1308     tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1309     tls_transfer.tx_buf = data_out;
1310     tls_transfer.rx_buf = data_in;
1311 
1312     tot_num = (num_out > num_in) ? num_out : num_in;
1313     remain_length = tot_num;
1314     tls_transfer.len = tot_num;
1315     tls_irq_disable(SPI_LS_IRQn);
1316     length = spi_fill_txfifo(&tls_transfer, remain_length);
1317     spi_set_sclk_length(length * 8, 0);
1318     spi_sclk_start();
1319 
1320     while (remain_length > 0) {
1321         while (spi_get_busy_status() == 1);
1322         length = spi_get_rxfifo(&tls_transfer, remain_length);
1323         remain_length -= length;
1324 
1325         if (remain_length == 0) {
1326             while (spi_get_busy_status() == 1);
1327             break;
1328         }
1329         while (spi_get_busy_status() == 1);
1330         length = spi_fill_txfifo(&tls_transfer, remain_length);
1331         if (length) {
1332             spi_set_sclk_length(length * 8, 0);
1333             spi_sclk_start();
1334         }
1335     }
1336 
1337     while (spi_get_busy_status() == 1);
1338     int_status = spi_get_int_status();
1339     spi_clear_int_status(int_status);
1340     tls_irq_enable(SPI_LS_IRQn);
1341     tls_close_peripheral_clock(TLS_PERIPHERAL_TYPE_LSPI);
1342 
1343     return (ret == TLS_SPI_STATUS_OK) ? 0 : -1;
1344 }